1 9 package javolution.xml; 10 11 import java.util.Hashtable ; 12 import j2me.lang.CharSequence; 13 import javolution.Javolution; 14 import javolution.text.CharArray; 15 import javolution.text.TextBuilder; 16 import javolution.text.TypeFormat; 17 import javolution.xml.sax.Attributes; 18 import javolution.xml.stream.XMLStreamException; 19 import javolution.xml.stream.XMLStreamReader; 20 import javolution.xml.stream.XMLStreamReaderImpl; 21 import javolution.xml.stream.XMLStreamWriter; 22 import javolution.xml.stream.XMLStreamWriterImpl; 23 24 111 public abstract class XMLFormat{ 112 113 116 private static final String NULL = "Null"; 117 118 121 static volatile XMLFormat[] _ClassInstances = new XMLFormat[64]; 122 123 126 static volatile int _ClassInstancesLength; 127 128 131 final Class _class; 132 133 137 protected XMLFormat() { 138 _class = null; 139 } 140 141 149 protected XMLFormat(Class cls) { 150 if (cls == null) 151 throw new NullPointerException (); 152 _class = cls; 153 synchronized (_ClassToFormat) { 154 if (_ClassToFormat.containsKey(cls)) 156 throw new IllegalArgumentException ( 157 "Multiple static binding for class " + cls 158 + " The XMLFormat(Class) constructor should be " + 159 "used solely for static instances."); 160 final int length = XMLFormat._ClassInstancesLength; 161 final XMLFormat[] formats = XMLFormat._ClassInstances; 162 if (length >= formats.length) { XMLFormat[] tmp = new XMLFormat[length * 2]; 164 System.arraycopy(formats, 0, tmp, 0, length); 165 XMLFormat._ClassInstances = tmp; 166 } 167 XMLFormat._ClassInstances[XMLFormat._ClassInstancesLength++] = this; 168 _ClassToFormat.put(cls, this); 169 } 170 } 171 172 private static Hashtable _ClassToFormat = new Hashtable (); 173 174 180 public final Class getBoundClass() { 181 return _class; 182 } 183 184 193 public boolean isReferenceable() { 194 return true; 195 } 196 197 208 public Object newInstance(Class cls, InputElement xml) 209 throws XMLStreamException { 210 try { 211 return cls.newInstance(); 212 } catch (InstantiationException e) { 213 throw new XMLStreamException(e); 214 } catch (IllegalAccessException e) { 215 throw new XMLStreamException(e); 216 } 217 } 218 219 225 public abstract void write(Object obj, OutputElement xml) 226 throws XMLStreamException; 227 228 235 public abstract void read(InputElement xml, Object obj) 236 throws XMLStreamException; 237 238 241 protected static final class InputElement { 242 243 246 final XMLStreamReaderImpl _reader = new XMLStreamReaderImpl(); 247 248 251 private XMLBinding _binding; 252 253 256 private XMLReferenceResolver _referenceResolver; 257 258 261 private boolean _isReaderAtNext; 262 263 266 InputElement() { 267 reset(); 268 } 269 270 276 public XMLStreamReader getStreamReader() { 277 return _reader; 278 } 279 280 288 public boolean hasNext() throws XMLStreamException { 289 if (!_isReaderAtNext) { 290 _isReaderAtNext = true; 291 _reader.nextTag(); 292 } 293 return _reader.getEventType() == XMLStreamReader.START_ELEMENT; 294 } 295 296 303 publicObject getNext() throws XMLStreamException { 304 if (!hasNext()) throw new XMLStreamException("No more element to read", _reader 306 .getLocation()); 307 308 if (_reader.getLocalName().equals(NULL)) { 310 if (_reader.next() != XMLStreamReader.END_ELEMENT) 311 throw new XMLStreamException("Non Empty Null Element"); 312 _isReaderAtNext = false; 313 return null; 314 } 315 316 if (_referenceResolver != null) { 318 Object obj = _referenceResolver.readReference(this); 319 if (obj != null) { 320 if (_reader.next() != XMLStreamReader.END_ELEMENT) 321 throw new XMLStreamException("Non Empty Reference Element"); 322 _isReaderAtNext = false; 323 return (Object ) obj; 324 } 325 } 326 327 Class cls; 329 try { 330 cls = _binding.getClass(_reader.getLocalName(), _reader 331 .getNamespaceURI()); 332 } catch (ClassNotFoundException e) { 333 throw new XMLStreamException(e); 334 } 335 336 return (Object ) get(cls); 337 } 338 339 346 publicObject get(String name) throws XMLStreamException { 347 if (!hasNext() || !_reader.getLocalName().equals(name)) 349 return null; 350 351 if (_referenceResolver != null) { 353 Object obj = _referenceResolver.readReference(this); 354 if (obj != null) { 355 if (_reader.next() != XMLStreamReader.END_ELEMENT) 356 throw new XMLStreamException("Non Empty Reference Element"); 357 _isReaderAtNext = false; 358 return (Object ) obj; 359 } 360 } 361 362 Class cls = _binding.readClassAttribute(_reader); 364 365 return (Object ) get(cls); 366 } 367 368 376 publicObject get(String localName, String uri) 377 throws XMLStreamException { 378 if (uri == null) 379 return (Object ) get(localName); 380 381 if (!hasNext() || !_reader.getLocalName().equals(localName) 383 || !_reader.getNamespaceURI().equals(uri)) 384 return null; 385 386 if (_referenceResolver != null) { 388 Object obj = _referenceResolver.readReference(this); 389 if (obj != null) { 390 if (_reader.next() != XMLStreamReader.END_ELEMENT) 391 throw new XMLStreamException("Non Empty Reference Element"); 392 _isReaderAtNext = false; 393 return (Object ) obj; 394 } 395 } 396 397 Class cls = _binding.readClassAttribute(_reader); 399 400 return (Object ) get(cls); 401 } 402 403 411 publicObject get(String name, Class cls) 412 throws XMLStreamException { 413 if (!hasNext() || !_reader.getLocalName().equals(name)) 415 return null; 416 417 if (_referenceResolver != null) { 419 Object obj = _referenceResolver.readReference(this); 420 if (obj != null) { 421 if (_reader.next() != XMLStreamReader.END_ELEMENT) 422 throw new XMLStreamException("Non Empty Reference Element"); 423 _isReaderAtNext = false; 424 return (Object ) obj; 425 } 426 } 427 428 return (Object ) get(cls); 429 } 430 431 440 publicObject get(String localName, String uri, 441 Class cls) throws XMLStreamException { 442 if (uri == null) 443 return get(localName, cls); 444 445 if (!hasNext() || !_reader.getLocalName().equals(localName) 447 || !_reader.getNamespaceURI().equals(uri)) 448 return null; 449 450 if (_referenceResolver != null) { 452 Object obj = _referenceResolver.readReference(this); 453 if (obj != null) { 454 if (_reader.next() != XMLStreamReader.END_ELEMENT) 455 throw new XMLStreamException("Non Empty Reference Element"); 456 _isReaderAtNext = false; 457 return (Object ) obj; 458 } 459 } 460 461 return (Object ) get(cls); 462 } 463 464 private Object get(Class cls) throws XMLStreamException { 466 467 XMLFormat xmlFormat = _binding.getFormat(cls); 469 470 _isReaderAtNext = false; Object obj = xmlFormat.newInstance(cls, this); 473 474 if (_referenceResolver != null) { 476 _referenceResolver.createReference(obj, this); 477 } 478 479 xmlFormat.read(this, obj); 481 if (hasNext()) throw new XMLStreamException("Incomplete element reading", 483 _reader.getLocation()); 484 _isReaderAtNext = false; return obj; 486 } 487 488 495 public CharArray getText() throws XMLStreamException { 496 CharArray txt = _reader.getElementText(); 497 _isReaderAtNext = true; return txt; 499 } 500 501 506 public Attributes getAttributes() throws XMLStreamException { 507 if (_isReaderAtNext) 508 throw new XMLStreamException( 509 "Attributes should be read before content"); 510 return _reader.getAttributes(); 511 } 512 513 520 public CharArray getAttribute(String name) throws XMLStreamException { 521 if (_isReaderAtNext) 522 throw new XMLStreamException( 523 "Attributes should be read before reading content"); 524 return _reader.getAttributeValue(null, toCsq(name)); 525 } 526 527 535 public String getAttribute(String name, String defaultValue) 536 throws XMLStreamException { 537 CharArray value = getAttribute(name); 538 return (value != null) ? value.toString() : defaultValue; 539 } 540 541 549 public boolean getAttribute(String name, boolean defaultValue) 550 throws XMLStreamException { 551 CharArray value = getAttribute(name); 552 return (value != null) ? value.toBoolean() : defaultValue; 553 } 554 555 564 public int getAttribute(String name, int defaultValue) 565 throws XMLStreamException { 566 CharArray value = getAttribute(name); 567 return (value != null) ? value.toInt() : defaultValue; 568 } 569 570 579 public long getAttribute(String name, long defaultValue) 580 throws XMLStreamException { 581 CharArray value = getAttribute(name); 582 return (value != null) ? value.toLong() : defaultValue; 583 } 584 585 598 599 612 613 624 public Boolean getAttribute(String name, Boolean defaultValue) 625 throws XMLStreamException { 626 CharArray value = getAttribute(name); 627 return (value != null) ? value.toBoolean() ? TRUE : FALSE 628 : defaultValue; 629 } 630 631 private static final Boolean TRUE = new Boolean (true); 632 633 private static final Boolean FALSE = new Boolean (false); 634 635 643 public Byte getAttribute(String name, Byte defaultValue) 644 throws XMLStreamException { 645 CharArray value = getAttribute(name); 646 return (value != null) ? new Byte (TypeFormat.parseByte(value)) 647 : defaultValue; 648 } 649 650 658 public Short getAttribute(String name, Short defaultValue) 659 throws XMLStreamException { 660 CharArray value = getAttribute(name); 661 return (value != null) ? new Short (TypeFormat.parseShort(value)) 662 : defaultValue; 663 } 664 665 673 public Integer getAttribute(String name, Integer defaultValue) 674 throws XMLStreamException { 675 CharArray value = getAttribute(name); 676 return (value != null) ? new Integer (value.toInt()) : defaultValue; 677 } 678 679 687 public Long getAttribute(String name, Long defaultValue) 688 throws XMLStreamException { 689 CharArray value = getAttribute(name); 690 return (value != null) ? new Long (value.toLong()) : defaultValue; 691 } 692 693 706 707 720 721 void setBinding(XMLBinding xmlBinding) { 723 _binding = xmlBinding; 724 } 725 726 void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) { 728 _referenceResolver = xmlReferenceResolver; 729 } 730 731 void reset() { 733 _binding = XMLBinding.DEFAULT; 734 _isReaderAtNext = false; 735 _reader.reset(); 736 _referenceResolver = null; 737 } 738 } 739 740 743 protected static class OutputElement { 744 745 748 final XMLStreamWriterImpl _writer = new XMLStreamWriterImpl(); 749 750 753 private XMLBinding _binding; 754 755 758 private XMLReferenceResolver _referenceResolver; 759 760 763 OutputElement() { 764 reset(); 765 } 766 767 773 public XMLStreamWriter getStreamWriter() { 774 return _writer; 775 } 776 777 783 public void add(Object obj) throws XMLStreamException { 784 if (obj == null) { 785 _writer.writeEmptyElement(toCsq(NULL)); 786 return; 787 } 788 789 Class cls = obj.getClass(); 791 String localName = _binding.getLocalName(cls); 792 String uri = _binding.getURI(cls); 793 if (uri == null) { 794 _writer.writeStartElement(toCsq(localName)); 795 } else { 796 _writer.writeStartElement(toCsq(uri), 797 toCsq(localName)); 798 } 799 800 XMLFormat xmlFormat = _binding.getFormat(cls); 802 if ((_referenceResolver != null) && xmlFormat.isReferenceable() 803 && _referenceResolver.writeReference(obj, this)) { 804 _writer.writeEndElement(); 805 return; } 807 808 xmlFormat.write(obj, this); 809 _writer.writeEndElement(); 810 } 811 812 821 public void add(Object obj, String name) throws XMLStreamException { 822 if (obj == null) 823 return; 824 825 _writer.writeStartElement(toCsq(name)); 827 828 Class cls = obj.getClass(); 830 _binding.writeClassAttribute(_writer, cls); 831 832 XMLFormat xmlFormat = _binding.getFormat(cls); 834 if ((_referenceResolver != null) && xmlFormat.isReferenceable() 835 && _referenceResolver.writeReference(obj, this)) { 836 _writer.writeEndElement(); 837 return; } 839 840 xmlFormat.write(obj, this); 841 _writer.writeEndElement(); 842 } 843 844 854 public void add(Object obj, String localName, String uri) 855 throws XMLStreamException { 856 if (obj == null) 857 return; 858 859 _writer.writeStartElement(toCsq(uri), toCsq(localName)); 861 862 Class cls = obj.getClass(); 864 _binding.writeClassAttribute(_writer, cls); 865 866 XMLFormat xmlFormat = _binding.getFormat(cls); 868 if ((_referenceResolver != null) && xmlFormat.isReferenceable() 869 && _referenceResolver.writeReference(obj, this)) { 870 _writer.writeEndElement(); 871 return; } 873 874 xmlFormat.write(obj, this); 875 _writer.writeEndElement(); 876 } 877 878 887 publicvoid add(Object obj, String name, Class cls) 888 throws XMLStreamException { 889 if (obj == null) 890 return; 891 892 _writer.writeStartElement(toCsq(name)); 894 895 XMLFormat xmlFormat = _binding.getFormat(cls); 897 if ((_referenceResolver != null) && xmlFormat.isReferenceable() 898 && _referenceResolver.writeReference(obj, this)) { 899 _writer.writeEndElement(); 900 return; } 902 903 xmlFormat.write(obj, this); 904 _writer.writeEndElement(); 905 } 906 907 917 publicvoid add(Object obj, String localName, String uri, 918 Class cls) throws XMLStreamException { 919 if (obj == null) 920 return; 921 922 _writer.writeStartElement(toCsq(uri), toCsq(localName)); 924 925 XMLFormat xmlFormat = _binding.getFormat(cls); 927 if ((_referenceResolver != null) && xmlFormat.isReferenceable() 928 && _referenceResolver.writeReference(obj, this)) { 929 _writer.writeEndElement(); 930 return; } 932 933 xmlFormat.write(obj, this); 934 _writer.writeEndElement(); 935 } 936 937 944 public void addText(CharSequence text) throws XMLStreamException { 945 _writer.writeCharacters(text); 946 } 947 948 954 public void addText(String text) throws XMLStreamException { 955 _writer.writeCharacters(toCsq(text)); 956 } 957 958 965 public void setAttribute(String name, CharSequence value) 966 throws XMLStreamException { 967 if (value == null) 968 return; 969 _writer.writeAttribute(toCsq(name), value); 970 } 971 972 979 public void setAttribute(String name, String value) 980 throws XMLStreamException { 981 if (value == null) 982 return; 983 _writer.writeAttribute(toCsq(name), 984 toCsq(value)); 985 } 986 987 993 public void setAttribute(String name, boolean value) 994 throws XMLStreamException { 995 setAttribute(name, _tmpTextBuilder.clear().append(value)); 996 } 997 998 private TextBuilder _tmpTextBuilder = new TextBuilder(); 999 1000 1006 public void setAttribute(String name, int value) 1007 throws XMLStreamException { 1008 setAttribute(name, _tmpTextBuilder.clear().append(value)); 1009 } 1010 1011 1017 public void setAttribute(String name, long value) 1018 throws XMLStreamException { 1019 setAttribute(name, _tmpTextBuilder.clear().append(value)); 1020 } 1021 1022 1032 1033 1043 1044 1054 public void setAttribute(String name, Boolean value) 1055 throws XMLStreamException { 1056 if (value == null) 1057 return; 1058 setAttribute(name, value.booleanValue()); 1059 } 1060 1061 1068 public void setAttribute(String name, Byte value) 1069 throws XMLStreamException { 1070 if (value == null) 1071 return; 1072 setAttribute(name, value.byteValue()); 1073 } 1074 1075 1082 public void setAttribute(String name, Short value) 1083 throws XMLStreamException { 1084 if (value == null) 1085 return; 1086 setAttribute(name, value.shortValue()); 1087 } 1088 1089 1096 public void setAttribute(String name, Integer value) 1097 throws XMLStreamException { 1098 if (value == null) 1099 return; 1100 setAttribute(name, value.intValue()); 1101 } 1102 1103 1110 public void setAttribute(String name, Long value) 1111 throws XMLStreamException { 1112 if (value == null) 1113 return; 1114 setAttribute(name, value.longValue()); 1115 } 1116 1117 1130 1131 1143 1144 void setBinding(XMLBinding xmlBinding) { 1146 _binding = xmlBinding; 1147 } 1148 1149 void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) { 1151 _referenceResolver = xmlReferenceResolver; 1152 } 1153 1154 void reset() { 1156 _binding = XMLBinding.DEFAULT; 1157 _writer.reset(); 1158 _writer.setRepairingNamespaces(true); 1159 _writer.setAutomaticEmptyElements(true); 1160 _referenceResolver = null; 1161 } 1162 1163 } 1164 1165 private static CharSequence toCsq(Object str) { 1166 return Javolution.j2meToCharSeq(str); 1167 } 1168 1169} | Popular Tags |