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