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.config;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 import org.dbforms.util.FileHolder;
31 import org.dbforms.util.TimeUtil;
32 import org.dbforms.util.UniqueIDGenerator;
33 import org.dbforms.util.Util;
34
35
36 import java.io.Serializable;
37 import java.math.BigDecimal;
38
39 import java.sql.Date;
40 import java.sql.Time;
41 import java.sql.Timestamp;
42
43 import java.text.DecimalFormat;
44 import java.text.SimpleDateFormat;
45
46 import java.util.Calendar;
47 import java.util.Locale;
48
49 /***
50 * This helper-class was originally used to maintain the mapped values between
51 * Main-Form and Sub-Form in the taglib package. in meantime it is used as
52 * holder of data in many places. <br>
53 * It also performs operations that involve "fields" and associated "values"
54 * (i.e. building blocks of SQL SELECT statements, etc) Now it's handles all the
55 * stuf of parsing the resended strings back into java objects.
56 *
57 * @author Joe Peer
58 * @author Philip Grunikiewicz
59 * @author Henner Kollmann
60 */
61 public class FieldValue implements Cloneable, Serializable {
62 /*** field object */
63 private Field field;
64
65 /*** holds the FileHolder object */
66 private FileHolder fileHolder;
67
68 /*** holds the current locale */
69 private Locale locale;
70
71 /*** logging category for this class */
72 private static Log logCat = LogFactory.getLog(FieldValue.class.getName());
73
74 /*** a value a field is associated with */
75 private String fieldValue;
76
77 /*** old value */
78 private String oldValue;
79
80 /*** holds the format object */
81 private String pattern;
82
83 /*** specifies whether to OR all values or AND them... */
84 private boolean logicalOR = false;
85
86 /***
87 * If FieldValue is used in a "childFieldValue", it signalizes if it should
88 * be rendered as hidden tag or not (if "stroke out")
89 */
90 private boolean renderHiddenHtmlTag = true;
91
92 /***
93 * if used in a filter argument: the type of filter comparison operator (see
94 * FILTER_ definitions above)
95 */
96 private int operator;
97
98 /*** if used in an argument for searching: SHARP || WEAK! */
99 private int searchAlgorithm;
100
101 /*** if used in an argument for searching: AND || OR! */
102 private int searchMode;
103
104 /***
105 * Field sor direction. Can be Field.ORDER_ASCENDING or
106 * Field.ORDER_DESCENDING.
107 */
108 private int sortDirection = Constants.ORDER_NONE;
109
110 /***
111 * Creates a new FieldValue object.
112 *
113 * @param field
114 * the name of the field
115 * @param fieldValue
116 * the string representation of the value of the field
117 */
118 public FieldValue(Field field, String fieldValue) {
119 this(field);
120 this.fieldValue = fieldValue;
121 }
122
123 /***
124 * Creates a new FieldValue object.
125 *
126 * @param field
127 * the name of the field
128 */
129 private FieldValue(Field field) {
130 this.field = field;
131 }
132
133 /***
134 * DOCUMENT ME!
135 *
136 * @param field
137 * DOCUMENT ME!
138 * @param fieldValue
139 * DOCUMENT ME!
140 * @param locale
141 * DOCUMENT ME!
142 * @param operator
143 * DOCUMENT ME!
144 * @param searchMode
145 * DOCUMENT ME!
146 * @param searchAlgorithm
147 * DOCUMENT ME!
148 * @param logicalOR
149 * DOCUMENT ME!
150 *
151 * @return DOCUMENT ME!
152 */
153 public static FieldValue createFieldValueForSearching(Field field,
154 String fieldValue, Locale locale, int operator, int searchMode,
155 int searchAlgorithm, boolean logicalOR) {
156 FieldValue fv = new FieldValue(field, fieldValue);
157 fv.setLocale(locale);
158 fv.setOperator(operator);
159 fv.setSearchMode(searchMode);
160 fv.setSearchAlgorithm(searchAlgorithm);
161 fv.setLogicalOR(logicalOR);
162
163 return fv;
164 }
165
166 /***
167 * DOCUMENT ME!
168 *
169 * @param field
170 * DOCUMENT ME!
171 * @param sortDirection
172 * DOCUMENT ME!
173 *
174 * @return DOCUMENT ME!
175 */
176 public static FieldValue createFieldValueForSorting(Field field,
177 int sortDirection) {
178 FieldValue fv = new FieldValue(field);
179 fv.setSortDirection(sortDirection);
180
181 return fv;
182 }
183
184 /***
185 * Sets the field attribute of the FieldValue object
186 *
187 * @param field
188 * The new field value
189 */
190 public void setField(Field field) {
191 this.field = field;
192 }
193
194 /***
195 * Gets the field attribute of the FieldValue object
196 *
197 * @return The field value
198 */
199 public Field getField() {
200 return field;
201 }
202
203 /***
204 * Sets the fieldValue attribute of the FieldValue object
205 *
206 * @param fieldValue
207 * The new fieldValue value
208 */
209 public void setFieldValue(String fieldValue) {
210 this.fieldValue = fieldValue;
211 }
212
213 /***
214 * Gets the fieldValue attribute of the FieldValue object
215 *
216 * @return The fieldValue value
217 */
218 public String getFieldValue() {
219 return fieldValue;
220 }
221
222 /***
223 * parses the given fieldValue according to the given type and creates an
224 * java object of the needed type. during the parsing the given
225 * locale/format settings will be used.
226 *
227 * @return Object of given type;
228 */
229 public Object getFieldValueAsObject() {
230 if (getField() == null) {
231 return null;
232 }
233
234 return getFieldValueAsObject(getFieldValue(), getField().getType());
235 }
236
237 /***
238 * Sets the fileHolder.
239 *
240 * @param fileHolder
241 * The fileHolder to set
242 */
243 public void setFileHolder(FileHolder fileHolder) {
244 this.fileHolder = fileHolder;
245 }
246
247 /***
248 * Return the fileHolder object for this field.
249 *
250 * @return the fileHolder object of this field
251 */
252 public FileHolder getFileHolder() {
253 return fileHolder;
254 }
255
256 /***
257 * DOCUMENT ME!
258 *
259 * @param locale
260 */
261 public void setLocale(Locale locale) {
262 this.locale = locale;
263 }
264
265 /***
266 * DOCUMENT ME!
267 *
268 * @return
269 */
270 public Locale getLocale() {
271 return locale;
272 }
273
274 /***
275 * Set the logicalOR attribute of this FieldValue object.
276 *
277 * @param newLogicalOR
278 * the logicalOR attribute value to set
279 */
280 public void setLogicalOR(boolean newLogicalOR) {
281 logicalOR = newLogicalOR;
282 }
283
284 /***
285 * Get the logicalOR attribute of this FieldValue object.
286 *
287 * @return the logicalOR attribute of this FieldValue object
288 */
289 public boolean getLogicalOR() {
290 return logicalOR;
291 }
292
293 /***
294 * test if given FieldValue[] is empty
295 *
296 * @param arr
297 * FieldValue[] to test
298 *
299 * @return true if array is null or empty
300 */
301 public static final boolean isNull(FieldValue[] arr) {
302 return ((arr == null) || (arr.length == 0));
303 }
304
305 /***
306 * Set the oldValue for this Field object.
307 *
308 * @param string
309 * the oldValue for this Field object
310 */
311 public void setOldValue(String string) {
312 oldValue = string;
313 }
314
315 /***
316 * Get the oldValue of this Field object.
317 *
318 * @return the oldValue of this Field object
319 */
320 public String getOldValue() {
321 return oldValue;
322 }
323
324 /***
325 * DOCUMENT ME!
326 *
327 * @return DOCUMENT ME!
328 */
329 public Object getOldValueAsObject() {
330 if (getField() == null) {
331 return null;
332 }
333
334 return getFieldValueAsObject(getOldValue(), getField().getType());
335 }
336
337 /***
338 * sets the operator
339 *
340 * @param i
341 */
342 public void setOperator(int i) {
343 operator = i;
344 }
345
346 /***
347 * Gets the operator attribute of the FieldValue object
348 *
349 * @return The operator value
350 */
351 public int getOperator() {
352 return operator;
353 }
354
355 /***
356 * DOCUMENT ME!
357 *
358 * @param pattern
359 */
360 public void setPattern(String pattern) {
361 this.pattern = pattern;
362 }
363
364 /***
365 * DOCUMENT ME!
366 *
367 * @return
368 */
369 public String getPattern() {
370 return pattern;
371 }
372
373 /***
374 * Sets the renderHiddenHtmlTag attribute of the FieldValue object
375 *
376 * @param renderHiddenHtmlTag
377 * The new renderHiddenHtmlTag value
378 */
379 public void setRenderHiddenHtmlTag(boolean renderHiddenHtmlTag) {
380 this.renderHiddenHtmlTag = renderHiddenHtmlTag;
381 }
382
383 /***
384 * Gets the renderHiddenHtmlTag attribute of the FieldValue object
385 *
386 * @return The renderHiddenHtmlTag value
387 */
388 public boolean getRenderHiddenHtmlTag() {
389 return renderHiddenHtmlTag;
390 }
391
392 /***
393 * Sets the searchAlgorithm attribute of the FieldValue object
394 *
395 * @param searchAlgorithm
396 * The new searchAlgorithm value
397 */
398 public void setSearchAlgorithm(int searchAlgorithm) {
399 this.searchAlgorithm = searchAlgorithm;
400 }
401
402 /***
403 * Gets the searchAlgorithm attribute of the FieldValue object
404 *
405 * @return The searchAlgorithm value
406 */
407 public int getSearchAlgorithm() {
408 return searchAlgorithm;
409 }
410
411 /***
412 * Sets the searchMode attribute of the FieldValue object
413 *
414 * @param searchMode
415 * The new searchMode value
416 */
417 public void setSearchMode(int searchMode) {
418 this.searchMode = searchMode;
419 }
420
421 /***
422 * Gets the searchMode attribute of the FieldValue object
423 *
424 * @return The searchMode value
425 */
426 public int getSearchMode() {
427 return searchMode;
428 }
429
430 /***
431 * Sets the sortDirection attribute of the FieldValue object
432 *
433 * @param sortDirection
434 * The new sortDirection value
435 */
436 public void setSortDirection(int sortDirection) {
437 this.sortDirection = sortDirection;
438 }
439
440 /***
441 * Gets the sortDirection attribute of the FieldValue object
442 *
443 * @return The sortDirection value
444 */
445 public int getSortDirection() {
446 return sortDirection;
447 }
448
449 /***
450 * Clone this object.
451 *
452 * @return a cloned FieldValue object
453 */
454 public Object clone() {
455
456 try {
457 FieldValue fv = (FieldValue) super.clone();
458
459 return fv;
460 } catch (CloneNotSupportedException e) {
461
462 logCat.error("::clone - exception", e);
463 }
464
465 return null;
466 }
467
468 /***
469 * Inverts the sorting direction of all FieldValue objects in the given
470 * array [ASC-->DESC et vice versa]
471 *
472 * @param fv
473 * the array of FieldValue objects
474 */
475 public static void invert(FieldValue[] fv) {
476 for (int i = 0; i < fv.length; i++) {
477 switch (fv[i].getSortDirection()) {
478 case Constants.ORDER_ASCENDING:
479 fv[i].setSortDirection(Constants.ORDER_DESCENDING);
480
481 break;
482
483 case Constants.ORDER_DESCENDING:
484 fv[i].setSortDirection(Constants.ORDER_ASCENDING);
485
486 break;
487 }
488 }
489 }
490
491 /***
492 * Get the String representation of this object.
493 *
494 * @return the String representation of this object
495 *
496 * @todo toString: to be finished
497 */
498 public String toString() {
499 StringBuffer buf = new StringBuffer();
500 String fieldName = (getField() != null)?getField().getName():"unknown field";
501 buf.append(" ").append("field [").append(fieldName).append(
502 "] has value, oldvalue [").append(getFieldValue()).append(", ")
503 .append(getOldValue()).append("]\n");
504 return buf.toString();
505 }
506
507 /***
508 * Dump the input FieldValue array
509 *
510 * @param fieldValues
511 * the fieldValues array
512 *
513 * @return the string representation of the FieldValues object
514 */
515 public static String toString(FieldValue[] fieldValues) {
516 StringBuffer sb = new StringBuffer();
517 sb.append("FieldValue array size: ").append(fieldValues.length).append(
518 "; elements are:\n");
519
520 for (int i = 0; i < fieldValues.length; i++) {
521 FieldValue fieldValue = fieldValues[i];
522 sb.append(fieldValue.toString());
523 }
524
525 return sb.toString();
526 }
527
528 private Object getFieldValueAsObject(String value, int fieldType) {
529 Object res = null;
530
531 switch (fieldType) {
532 case FieldTypes.INTEGER:
533 res = parseINTEGER(value);
534
535 break;
536
537 case FieldTypes.DOUBLE:
538 res = parseDOUBLE(value);
539
540 break;
541
542 case FieldTypes.FLOAT:
543 res = parseFLOAT(value);
544
545 break;
546
547 case FieldTypes.NUMERIC:
548 res = parseNUMERIC(value);
549
550 break;
551
552 case FieldTypes.LONGVARCHAR:
553 case FieldTypes.VARCHAR:
554 case FieldTypes.CHAR:
555 res = parseCHAR(value);
556
557 break;
558
559 case FieldTypes.DATE:
560 res = parseDATE(value);
561
562 break;
563
564 case FieldTypes.TIME:
565 res = parseTIME(value);
566
567 break;
568
569 case FieldTypes.TIMESTAMP:
570 res = parseTIMESTAMP(value);
571
572 break;
573
574
575
576
577
578
579 case FieldTypes.BOOLEAN:
580 res = parseBOOLEAN(value);
581
582 break;
583 case FieldTypes.BLOB:
584
585
586
587 if (getFileHolder() == null) {
588 res = value;
589 } else {
590 res = getFileHolder();
591 }
592
593 break;
594
595 case FieldTypes.DISKBLOB:
596 res = parseDISKBLOB();
597
598 break;
599
600 default:
601 break;
602 }
603
604 return res;
605 }
606
607 private String parseCHAR(String value) {
608 String res;
609 if ("[NULL]".equals(value)) {
610 res = null;
611 } else {
612 res = value;
613 }
614 return res;
615 }
616
617
618
619
620
621
622 private Boolean parseBOOLEAN(String value) {
623 Boolean res;
624 if (Util.isNull(value)) {
625 res = null;
626 } else {
627 res = new Boolean(value);
628 }
629 return res;
630 }
631
632 private Date parseDATE(String value) {
633 if (Util.isNull(value)) {
634 return null;
635 }
636 String valueStr = value.trim();
637
638 if (Util.isNull(valueStr)) {
639 return null;
640 }
641
642 if (getLocale() != null) {
643 try {
644 SimpleDateFormat f = (SimpleDateFormat) getField().getFormat(
645 getPattern(), getLocale());
646 Calendar result = TimeUtil.parseDate(f, valueStr);
647 result.set(Calendar.HOUR_OF_DAY, 0);
648 result.set(Calendar.MINUTE, 0);
649 result.set(Calendar.SECOND, 0);
650
651 return new Date(result.getTime().getTime());
652 } catch (Exception e) {
653 logCat.error(e.getMessage() + " <" + valueStr + "/"
654 + getPattern() + ">");
655
656
657 try {
658 SimpleDateFormat f = (SimpleDateFormat) getField()
659 .getFormat("short", getLocale());
660 Calendar result = TimeUtil.parseDate(f, valueStr);
661 result.set(Calendar.HOUR_OF_DAY, 0);
662 result.set(Calendar.MINUTE, 0);
663 result.set(Calendar.SECOND, 0);
664
665 return new Date(result.getTime().getTime());
666 } catch (Exception ex) {
667 logCat.error(ex.getMessage() + " <" + valueStr + "/"
668 + getPattern() + ">");
669 }
670 }
671 }
672
673 try {
674
675
676
677 String[] vStr = StringUtils.split(valueStr, " ");
678 String str = vStr[0];
679
680 return Date.valueOf(str);
681 } catch (Exception e) {
682 logCat.error(e.getMessage() + " <" + valueStr + ">");
683 }
684
685 return null;
686 }
687
688 private String parseDISKBLOB() {
689 if (getField().hasEncodedSet()) {
690 String fileName = getFileHolder().getFileName();
691 int dotIndex = fileName.lastIndexOf('.');
692 String suffix = (dotIndex != -1) ? fileName.substring(dotIndex)
693 : "";
694 fileHolder.setFileName(UniqueIDGenerator.getUniqueID() + suffix);
695 }
696
697 return fileHolder.getFileName();
698 }
699
700 private Double parseDOUBLE(String value) {
701 if (Util.isNull(value)) {
702 return null;
703 }
704 String valueStr = value.trim();
705
706 if (Util.isNull(valueStr)) {
707 return null;
708 }
709
710 if (getLocale() != null) {
711 try {
712 DecimalFormat f = (DecimalFormat) getField().getFormat(
713 getPattern(), getLocale());
714
715 return new Double(f.parse(valueStr).doubleValue());
716 } catch (Exception e) {
717 logCat.error(e.getMessage() + " <" + valueStr + "/"
718 + getPattern() + ">");
719 }
720 }
721
722 try {
723 return new Double(valueStr);
724 } catch (Exception e) {
725 logCat.error(e.getMessage() + " <" + valueStr + ">");
726 }
727
728 return null;
729 }
730
731 private Float parseFLOAT(String value) {
732 if (Util.isNull(value)) {
733 return null;
734 }
735 String valueStr = value.trim();
736
737 if (Util.isNull(valueStr)) {
738 return null;
739 }
740
741 if (getLocale() != null) {
742 try {
743 DecimalFormat f = (DecimalFormat) getField().getFormat(
744 getPattern(), getLocale());
745
746 return new Float(f.parse(valueStr).floatValue());
747 } catch (Exception e) {
748 logCat.error(e.getMessage() + " <" + valueStr + "/"
749 + getPattern() + ">");
750 }
751 }
752
753 try {
754 return new Float(valueStr);
755 } catch (Exception e) {
756 logCat.error(e.getMessage() + " <" + valueStr + ">");
757 }
758
759 return null;
760 }
761
762 private Integer parseINTEGER(String value) {
763 if (Util.isNull(value)) {
764 return null;
765 }
766 String valueStr = value.trim();
767
768 if (Util.isNull(valueStr)) {
769 return null;
770 }
771
772 if (getLocale() != null) {
773 try {
774 DecimalFormat f = (DecimalFormat) getField().getFormat(
775 getPattern(), getLocale());
776
777 return new Integer(f.parse(valueStr).intValue());
778 } catch (Exception e) {
779 logCat.error(e.getMessage() + " <" + valueStr + "/"
780 + getPattern() + ">");
781 }
782 }
783
784 try {
785 return new Integer(valueStr);
786 } catch (Exception e) {
787 logCat.error(e.getMessage() + " <" + valueStr + ">");
788 }
789
790 return null;
791 }
792
793 private BigDecimal parseNUMERIC(String value) {
794 if (Util.isNull(value)) {
795 return null;
796 }
797 String valueStr = value.trim();
798
799 if (Util.isNull(valueStr)) {
800 return null;
801 }
802
803 if (getLocale() != null) {
804 try {
805 DecimalFormat f = (DecimalFormat) getField().getFormat(
806 getPattern(), getLocale());
807
808 return new BigDecimal(f.parse(valueStr).doubleValue());
809 } catch (Exception e) {
810 logCat.error(e.getMessage() + " <" + valueStr + "/"
811 + getPattern() + ">");
812 }
813 }
814
815 try {
816 return new BigDecimal(valueStr);
817 } catch (Exception e) {
818 logCat.error(e.getMessage() + " <" + valueStr + ">");
819 }
820
821 return null;
822 }
823
824 private Time parseTIME(String value) {
825 if (Util.isNull(value)) {
826 return null;
827 }
828 String valueStr = value.trim();
829
830 if (Util.isNull(valueStr)) {
831 return null;
832 }
833
834 if (getLocale() != null) {
835 try {
836 SimpleDateFormat f = (SimpleDateFormat) getField().getFormat(
837 getPattern(), getLocale());
838 Calendar result = TimeUtil.parseDate(f, valueStr);
839 result.set(Calendar.DAY_OF_MONTH, 0);
840 result.set(Calendar.MONTH, 0);
841 result.set(Calendar.YEAR, 0);
842
843 return new Time(result.getTime().getTime());
844 } catch (Exception e) {
845 logCat.error(e.getMessage() + " <" + valueStr + "/"
846 + getPattern() + ">");
847
848
849 try {
850 SimpleDateFormat f = (SimpleDateFormat) getField()
851 .getFormat("short", getLocale());
852 Calendar result = TimeUtil.parseDate(f, valueStr);
853 result.set(Calendar.DAY_OF_MONTH, 0);
854 result.set(Calendar.MONTH, 0);
855 result.set(Calendar.YEAR, 0);
856
857 return new Time(result.getTime().getTime());
858 } catch (Exception ex) {
859 logCat.error(ex.getMessage() + " <" + valueStr + "/"
860 + getPattern() + ">");
861 }
862 }
863 }
864
865 try {
866 return Time.valueOf(valueStr);
867 } catch (Exception e) {
868 logCat.error(e.getMessage() + " <" + valueStr + ">");
869 }
870
871 return null;
872 }
873
874 private Timestamp parseTIMESTAMP(String value) {
875 if (Util.isNull(value)) {
876 return null;
877 }
878 String valueStr = value.trim();
879 if (Util.isNull(valueStr)) {
880 return null;
881 }
882
883 if (getLocale() != null) {
884 try {
885 SimpleDateFormat f = (SimpleDateFormat) getField().getFormat(
886 getPattern(), getLocale());
887 Calendar result = TimeUtil.parseDate(f, valueStr);
888
889 return new Timestamp(result.getTime().getTime());
890 } catch (Exception e) {
891 logCat.error(e.getMessage() + " <" + valueStr + "/"
892 + getPattern() + ">");
893
894
895 try {
896 SimpleDateFormat f = (SimpleDateFormat) getField()
897 .getFormat("short", getLocale());
898 Calendar result = TimeUtil.parseDate(f, valueStr);
899
900 return new Timestamp(result.getTime().getTime());
901 } catch (Exception ex) {
902 logCat.error(ex.getMessage() + " <" + valueStr + "/"
903 + getPattern() + ">");
904 }
905 }
906 }
907
908 try {
909 return Timestamp.valueOf(valueStr);
910 } catch (Exception e) {
911 logCat.error(e.getMessage() + " <" + valueStr + ">");
912 }
913
914 return null;
915 }
916 }