1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.common.xml;
21
22 import org.waarp.common.exception.InvalidArgumentException;
23 import org.waarp.common.utility.WaarpStringUtils;
24
25 import java.io.InvalidObjectException;
26 import java.math.BigDecimal;
27 import java.math.BigInteger;
28 import java.sql.Date;
29 import java.sql.Timestamp;
30 import java.text.ParseException;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.List;
34
35
36
37
38 public class XmlValue {
39
40 private static final String CAN_NOT_CONVERT_VALUE = "Can not convert value ";
41
42 private static final String TO_TYPE = " to type ";
43
44 private static final String CAN_NOT_CONVERT_VALUE_FROM =
45 "Can not convert value from ";
46
47 private final XmlDecl decl;
48
49 private Object value;
50
51 private List<?> values;
52
53 private XmlValue[] subXml;
54
55 public XmlValue(final XmlDecl decl) {
56 this.decl = decl;
57 if (this.decl.isSubXml()) {
58 if (this.decl.isMultiple()) {
59 value = null;
60 values = new ArrayList<XmlValue>();
61 subXml = null;
62 return;
63 }
64 final int len = this.decl.getSubXmlSize();
65 final XmlDecl[] newDecls = this.decl.getSubXml();
66 subXml = new XmlValue[len];
67 for (int i = 0; i < len; i++) {
68 subXml[i] = new XmlValue(newDecls[i]);
69 }
70 value = null;
71 values = null;
72 return;
73 }
74 if (this.decl.isMultiple()) {
75 value = null;
76 switch (getType()) {
77 case BOOLEAN:
78 case STRING:
79 case TIMESTAMP:
80 case SQLDATE:
81 case SHORT:
82 case DOUBLE:
83 case LONG:
84 case BYTE:
85 case CHARACTER:
86 case FLOAT:
87 case INTEGER:
88 values = new ArrayList<Boolean>();
89 break;
90 case XVAL:
91 case EMPTY:
92 default:
93 break;
94 }
95 }
96 }
97
98 @SuppressWarnings("unchecked")
99 public XmlValue(final XmlValue from) {
100 this(from.decl);
101 if (decl.isSubXml()) {
102 if (decl.isMultiple()) {
103 final List<XmlValue[]> subvalues = (List<XmlValue[]>) from.values;
104 for (final XmlValue[] xmlValues : subvalues) {
105 final XmlValue[] newValues = new XmlValue[xmlValues.length];
106 for (int i = 0; i < xmlValues.length; i++) {
107 newValues[i] = new XmlValue(xmlValues[i]);
108 }
109 ((Collection<XmlValue[]>) values).add(newValues);
110 }
111 } else {
112 for (int i = 0; i < from.subXml.length; i++) {
113 subXml[i] = new XmlValue(from.subXml[i]);
114 }
115 }
116 } else if (decl.isMultiple()) {
117 final List<Object> subvalues = (List<Object>) from.values;
118 for (final Object object : subvalues) {
119 try {
120 addValue(getCloneValue(getType(), object));
121 } catch (final InvalidObjectException e) {
122
123 }
124 }
125 } else {
126 try {
127 setValue(from.getCloneValue());
128 } catch (final InvalidObjectException e) {
129
130 }
131 }
132 }
133
134
135
136
137 public final XmlDecl getDecl() {
138 return decl;
139 }
140
141
142
143
144
145
146 public final String getName() {
147 return decl.getName();
148 }
149
150
151
152
153 public final Class<?> getClassType() {
154 return decl.getClassType();
155 }
156
157
158
159
160 public final XmlType getType() {
161 return decl.getType();
162 }
163
164
165
166
167 public final String getXmlPath() {
168 return decl.getXmlPath();
169 }
170
171
172
173
174 public final boolean isSubXml() {
175 return decl.isSubXml();
176 }
177
178
179
180
181
182
183 public final XmlValue[] getSubXml() {
184 return subXml;
185 }
186
187
188
189
190 public final boolean isMultiple() {
191 return decl.isMultiple();
192 }
193
194
195
196
197
198
199 public final List<?> getList() {
200 return values;
201 }
202
203
204
205
206
207
208
209
210
211
212 @SuppressWarnings("unchecked")
213 public final void addFromString(final String valueOrig)
214 throws InvalidObjectException, InvalidArgumentException {
215 final String valueNew = XmlUtil.getExtraTrimed(valueOrig);
216 switch (getType()) {
217 case BOOLEAN:
218 ((Collection<Boolean>) values).add(
219 (Boolean) convert(getClassType(), valueNew));
220 break;
221 case INTEGER:
222 ((Collection<Integer>) values).add(
223 (Integer) convert(getClassType(), valueNew));
224 break;
225 case FLOAT:
226 ((Collection<Float>) values).add(
227 (Float) convert(getClassType(), valueNew));
228 break;
229 case CHARACTER:
230 ((Collection<Character>) values).add(
231 (Character) convert(getClassType(), valueNew));
232 break;
233 case BYTE:
234 ((Collection<Byte>) values).add(
235 (Byte) convert(getClassType(), valueNew));
236 break;
237 case LONG:
238 ((Collection<Long>) values).add(
239 (Long) convert(getClassType(), valueNew));
240 break;
241 case DOUBLE:
242 ((Collection<Double>) values).add(
243 (Double) convert(getClassType(), valueNew));
244 break;
245 case SHORT:
246 ((Collection<Short>) values).add(
247 (Short) convert(getClassType(), valueNew));
248 break;
249 case SQLDATE:
250 ((Collection<Date>) values).add(
251 (Date) convert(getClassType(), valueNew));
252 break;
253 case TIMESTAMP:
254 ((Collection<Timestamp>) values).add(
255 (Timestamp) convert(getClassType(), valueNew));
256 break;
257 case STRING:
258 ((Collection<String>) values).add(
259 (String) convert(getClassType(), valueNew));
260 break;
261 case XVAL:
262 throw new InvalidObjectException(
263 "XVAL cannot be assigned from String directly");
264
265 case EMPTY:
266 throw new InvalidObjectException("EMPTY cannot be assigned");
267 }
268 }
269
270
271
272
273
274
275
276
277 @SuppressWarnings("unchecked")
278 public final void addValue(final Object value) throws InvalidObjectException {
279 if (getType().isNativelyCompatible(value)) {
280 switch (getType()) {
281 case BOOLEAN:
282 ((Collection<Boolean>) values).add((Boolean) value);
283 break;
284 case INTEGER:
285 ((Collection<Integer>) values).add((Integer) value);
286 break;
287 case FLOAT:
288 ((Collection<Float>) values).add((Float) value);
289 break;
290 case CHARACTER:
291 ((Collection<Character>) values).add((Character) value);
292 break;
293 case BYTE:
294 ((Collection<Byte>) values).add((Byte) value);
295 break;
296 case LONG:
297 ((Collection<Long>) values).add((Long) value);
298 break;
299 case DOUBLE:
300 ((Collection<Double>) values).add((Double) value);
301 break;
302 case SHORT:
303 ((Collection<Short>) values).add((Short) value);
304 break;
305 case SQLDATE:
306 if (Date.class.isAssignableFrom(value.getClass())) {
307 ((Collection<Date>) values).add((Date) value);
308 } else if (java.util.Date.class.isAssignableFrom(value.getClass())) {
309 ((Collection<Date>) values).add(
310 new Date(((java.util.Date) value).getTime()));
311 }
312 break;
313 case TIMESTAMP:
314 ((Collection<Timestamp>) values).add((Timestamp) value);
315 break;
316 case STRING:
317 ((Collection<String>) values).add(
318 XmlUtil.getExtraTrimed((String) value));
319 break;
320 case XVAL:
321 ((Collection<XmlValue[]>) values).add((XmlValue[]) value);
322 break;
323 default:
324 throw new InvalidObjectException(
325 CAN_NOT_CONVERT_VALUE_FROM + value.getClass() + TO_TYPE +
326 getClassType());
327 }
328 } else {
329 throw new InvalidObjectException(
330 CAN_NOT_CONVERT_VALUE_FROM + value.getClass() + TO_TYPE +
331 getClassType());
332 }
333 }
334
335
336
337
338 public final Object getValue() {
339 return value;
340 }
341
342
343
344
345
346
347
348
349
350
351
352 public static Object getCloneValue(final XmlType type, final Object value)
353 throws InvalidObjectException {
354 if (value == null) {
355 throw new InvalidObjectException(
356 "Can not convert value from null to type " + type.classType);
357 }
358 switch (type) {
359 case BOOLEAN:
360 return value;
361 case INTEGER:
362 return value;
363 case FLOAT:
364 return value;
365 case CHARACTER:
366 return value;
367 case BYTE:
368 return value;
369 case LONG:
370 return value;
371 case DOUBLE:
372 return value;
373 case SHORT:
374 return value;
375 case SQLDATE:
376 return new Date(((Date) value).getTime());
377 case TIMESTAMP:
378 return new Timestamp(((Timestamp) value).getTime());
379 case STRING:
380 return value;
381 case XVAL:
382 return new XmlValue((XmlValue) value);
383 case EMPTY:
384 default:
385 throw new InvalidObjectException(
386 CAN_NOT_CONVERT_VALUE_FROM + value.getClass() + TO_TYPE +
387 type.classType);
388 }
389 }
390
391
392
393
394
395
396 public final Object getCloneValue() throws InvalidObjectException {
397 if (getType() == XmlType.EMPTY) {
398 return new XmlValue(decl);
399 }
400 return getCloneValue(getType(), value);
401 }
402
403
404
405
406 public final String getString() {
407 if (getType().isString()) {
408 return XmlUtil.getExtraTrimed((String) value);
409 }
410 throw new IllegalArgumentException(
411 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type String");
412 }
413
414
415
416
417 public final int getInteger() {
418 if (getType().isInteger()) {
419 return (Integer) value;
420 }
421 throw new IllegalArgumentException(
422 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Integer");
423 }
424
425
426
427
428 public final boolean getBoolean() {
429 if (getType().isBoolean()) {
430 return (Boolean) value;
431 }
432 throw new IllegalArgumentException(
433 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Boolean");
434 }
435
436
437
438
439 public final long getLong() {
440 if (getType().isLong()) {
441 return (Long) value;
442 }
443 throw new IllegalArgumentException(
444 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Long");
445 }
446
447
448
449
450 public final float getFloat() {
451 if (getType().isFloat()) {
452 return (Float) value;
453 }
454 throw new IllegalArgumentException(
455 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Float");
456 }
457
458
459
460
461 public final char getCharacter() {
462 if (getType().isCharacter()) {
463 return (Character) value;
464 }
465 throw new IllegalArgumentException(
466 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() +
467 " to type Character");
468 }
469
470
471
472
473 public final byte getByte() {
474 if (getType().isByte()) {
475 return (Byte) value;
476 }
477 throw new IllegalArgumentException(
478 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Byte");
479 }
480
481
482
483
484 public final double getDouble() {
485 if (getType().isDouble()) {
486 return (Double) value;
487 }
488 throw new IllegalArgumentException(
489 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Double");
490 }
491
492
493
494
495 public final short getShort() {
496 if (getType().isShort()) {
497 return (Short) value;
498 }
499 throw new IllegalArgumentException(
500 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Short");
501 }
502
503
504
505
506 public final Date getDate() {
507 if (getType().isDate()) {
508 return (Date) value;
509 }
510 throw new IllegalArgumentException(
511 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() + " to type Date");
512 }
513
514
515
516
517 public final Timestamp getTimestamp() {
518 if (getType().isTimestamp()) {
519 return (Timestamp) value;
520 }
521 throw new IllegalArgumentException(
522 CAN_NOT_CONVERT_VALUE_FROM + decl.getClassType() +
523 " to type Timestamp");
524 }
525
526
527
528
529
530
531
532
533 public final void setFromString(final String value)
534 throws InvalidArgumentException {
535 this.value = convert(getClassType(), XmlUtil.getExtraTrimed(value));
536 }
537
538
539
540
541
542
543
544
545 public final boolean isEmpty() {
546 if (isSubXml()) {
547 if (isMultiple()) {
548 return values.isEmpty();
549 } else {
550 return subXml.length == 0;
551 }
552 }
553 if (isMultiple()) {
554 return values.isEmpty();
555 } else {
556 return value == null;
557 }
558 }
559
560
561
562
563
564
565 public final String getIntoString() {
566 if (!isMultiple() && !isSubXml()) {
567 if (value != null) {
568 return value.toString();
569 } else {
570 return "";
571 }
572 } else {
573 throw new IllegalArgumentException(
574 "Cannot convert Multiple values to single String");
575 }
576 }
577
578
579
580
581
582
583
584 @SuppressWarnings("unchecked")
585 public final void setValue(final Object value) throws InvalidObjectException {
586 if (getType().isNativelyCompatible(value)) {
587 switch (getType()) {
588 case BOOLEAN:
589 case TIMESTAMP:
590 case SHORT:
591 case DOUBLE:
592 case LONG:
593 case BYTE:
594 case CHARACTER:
595 case FLOAT:
596 case INTEGER:
597 this.value = value;
598 break;
599 case SQLDATE:
600 if (Date.class.isAssignableFrom(value.getClass())) {
601 this.value = value;
602 } else if (java.util.Date.class.isAssignableFrom(value.getClass())) {
603 this.value = new Date(((java.util.Date) value).getTime());
604 }
605 break;
606 case STRING:
607 this.value = XmlUtil.getExtraTrimed((String) value);
608 break;
609 case XVAL:
610 final XmlValue[] newValue = (XmlValue[]) value;
611 if (isSubXml()) {
612
613
614 if (decl.getSubXmlSize() != newValue.length) {
615 throw new InvalidObjectException(
616 "XmlDecl are not compatible from Array of XmlValue" +
617 TO_TYPE + getClassType());
618 }
619 if (isMultiple()) {
620 ((List<XmlValue[]>) values).add(newValue);
621 } else {
622 subXml = newValue;
623 }
624 } else {
625 throw new InvalidObjectException(
626 "Can not convert value from Array of XmlValue" + TO_TYPE +
627 getClassType());
628 }
629 break;
630 default:
631 throw new InvalidObjectException(
632 CAN_NOT_CONVERT_VALUE_FROM + value.getClass() + TO_TYPE +
633 getClassType());
634 }
635 } else {
636 throw new InvalidObjectException(
637 CAN_NOT_CONVERT_VALUE_FROM + value.getClass() + TO_TYPE +
638 getClassType());
639 }
640 }
641
642
643
644
645
646
647
648
649 protected static Object convert(final Class<?> type, final String value)
650 throws InvalidArgumentException {
651 try {
652
653
654 if (String.class.isAssignableFrom(type)) {
655 return value;
656 }
657
658
659 else if (type.equals(Boolean.TYPE)) {
660 if ("1".equals(value)) {
661 return Boolean.TRUE;
662 }
663 return Boolean.valueOf(value);
664 } else if (type.equals(Integer.TYPE)) {
665 return Integer.valueOf(value);
666 } else if (type.equals(Float.TYPE)) {
667 return Float.valueOf(value);
668 } else if (type.equals(Character.TYPE)) {
669 return Character.valueOf(value.charAt(0));
670 } else if (type.equals(Byte.TYPE)) {
671 return Byte.valueOf(value);
672 } else if (type.equals(Long.TYPE)) {
673 return Long.valueOf(value);
674 } else if (type.equals(Double.TYPE)) {
675 return Double.valueOf(value);
676 } else if (type.equals(Short.TYPE)) {
677 return Short.valueOf(value);
678 }
679
680
681 else if (Boolean.class.isAssignableFrom(type)) {
682 if ("true".equalsIgnoreCase(value)) {
683 return Boolean.TRUE;
684 } else {
685 return Boolean.FALSE;
686 }
687 } else if (Character.class.isAssignableFrom(type)) {
688 if (value.length() == 1) {
689 return Character.valueOf(value.charAt(0));
690 } else {
691 throw new IllegalArgumentException(
692 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
693 }
694 } else if (Number.class.isAssignableFrom(type)) {
695 if (Double.class.isAssignableFrom(type)) {
696 return Double.valueOf(value);
697 } else if (Float.class.isAssignableFrom(type)) {
698 return Float.valueOf(value);
699 } else if (Integer.class.isAssignableFrom(type)) {
700 return Integer.valueOf(value);
701 } else if (Long.class.isAssignableFrom(type)) {
702 return Long.valueOf(value);
703 } else if (Short.class.isAssignableFrom(type)) {
704 return Short.valueOf(value);
705 }
706
707
708 else if (BigDecimal.class.isAssignableFrom(type)) {
709 throw new IllegalArgumentException("Can not use type " + type);
710 } else if (BigInteger.class.isAssignableFrom(type)) {
711 throw new IllegalArgumentException("Can not use type " + type);
712 } else {
713 throw new IllegalArgumentException(
714 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
715 }
716 }
717
718
719
720
721
722
723 else if (Date.class.isAssignableFrom(type)) {
724 return new Date(
725 WaarpStringUtils.getDateFormat().parse(value).getTime());
726 } else if (Timestamp.class.isAssignableFrom(type)) {
727 final int dotIndex = value.indexOf('.');
728 final int spaceIndex = value.indexOf(' ', dotIndex);
729 if (dotIndex < 0 || spaceIndex < 0) {
730 throw new IllegalArgumentException(
731 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
732 }
733 final Timestamp ts = new Timestamp(WaarpStringUtils.getTimestampFormat()
734 .parse(
735 value.substring(
736 0, dotIndex))
737 .getTime());
738 final int nanos =
739 Integer.parseInt(value.substring(dotIndex + 1, spaceIndex));
740 ts.setNanos(nanos);
741
742 return ts;
743 } else if (java.util.Date.class.isAssignableFrom(type)) {
744
745 return new Date(
746 WaarpStringUtils.getTimeFormat().parse(value).getTime());
747 } else {
748 throw new IllegalArgumentException(
749 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
750 }
751 } catch (final NumberFormatException e) {
752 throw new InvalidArgumentException(
753 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
754 } catch (final IllegalArgumentException e) {
755 throw new InvalidArgumentException(
756 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type, e);
757 } catch (final ParseException e) {
758 throw new InvalidArgumentException(
759 CAN_NOT_CONVERT_VALUE + value + TO_TYPE + type);
760 }
761 }
762
763 @Override
764 public String toString() {
765 return "Val: " + (isMultiple()? values.size() + " elements" :
766 value != null? value.toString() :
767 subXml != null? "subXml" : "no value") + ' ' + decl;
768 }
769
770 public final String toFullString() {
771 final StringBuilder detail = new StringBuilder("Val: " + (isMultiple()?
772 values.size() + " elements" : value != null? value.toString() :
773 subXml != null? "subXml" : "no value") + ' ' + decl);
774 if (decl.isSubXml()) {
775 if (isMultiple()) {
776 detail.append('[');
777 for (final Object obj : values) {
778 if (obj instanceof XmlValue) {
779 detail.append(((XmlValue) obj).toFullString()).append(", ");
780 } else {
781 detail.append('[');
782 for (final XmlValue obj2 : (XmlValue[]) obj) {
783 detail.append(obj2.toFullString()).append(", ");
784 }
785 detail.append("], ");
786 }
787 }
788 detail.append(']');
789 } else {
790 detail.append('[');
791 for (final XmlValue obj : subXml) {
792 detail.append(obj.toFullString()).append(", ");
793 }
794 detail.append(']');
795 }
796 }
797 return detail.toString();
798 }
799 }