1 28 29 package com.caucho.xml2; 30 31 import com.caucho.vfs.Depend; 32 import com.caucho.vfs.Path; 33 34 import org.w3c.dom.*; 35 36 import javax.xml.namespace.QName ; 37 import java.io.IOException ; 38 import java.util.ArrayList ; 39 import java.util.HashMap ; 40 import java.util.Iterator ; 41 42 45 public class QDocument extends QDocumentFragment implements CauchoDocument { 46 QDOMImplementation _implementation; 47 QDocumentType _dtd; 48 QElement _element; HashMap <String ,String > _attributes; 50 String _encoding = "UTF-8"; 51 String _version; 52 53 private String _systemId; 54 55 private HashMap <String ,String > _namespaces; 56 57 private transient HashMap <NameKey,QName > _nameCache = new HashMap <NameKey,QName >(); 58 private transient NameKey _nameKey = new NameKey(); 59 private transient ArrayList <Path> _depends; 60 private transient ArrayList <Depend> _dependList; 61 62 int _changeCount; 63 64 String _rootFilename; 67 private boolean _standalone; 68 69 public QDocument() 70 { 71 _implementation = new QDOMImplementation(); 72 _owner = this; 73 } 74 75 public QDocument(DocumentType docType) 76 { 77 _owner = this; 78 setDoctype(docType); 79 } 80 81 public QDocument(QDOMImplementation impl) 82 { 83 _implementation = impl; 84 _owner = this; 85 } 86 87 void setAttribute(String name, String value) 88 { 89 if (name.equals("version")) 90 _version = value; 91 else if (name.equals("encoding")) 92 _encoding = value; 93 else { 94 if (_attributes == null) 95 _attributes = new HashMap <String ,String >(); 96 _attributes.put(name, value); 97 } 98 } 99 100 public String getRootFilename() 101 { 102 return _rootFilename; 103 } 104 105 public void setRootFilename(String filename) 106 { 107 _rootFilename = filename; 108 } 109 110 public void setSystemId(String systemId) 111 { 112 _systemId = systemId; 113 } 114 115 public String getSystemId() 116 { 117 return _systemId; 118 } 119 120 123 public String getBaseURI() 124 { 125 return getSystemId(); 126 } 127 128 public Document getOwnerDocument() 129 { 130 return null; 131 } 132 133 public DOMConfiguration getDomConfig() 134 { 135 return null; 136 } 137 138 public boolean isSupported(String feature, String version) 139 { 140 return _owner.getImplementation().hasFeature(feature, version); 141 } 142 143 146 public String getNodeName() 147 { 148 return "#document"; 149 } 150 151 public short getNodeType() 152 { 153 return DOCUMENT_NODE; 154 } 155 156 protected Node copyNode(QDocument newNode, boolean deep) 157 { 158 newNode._dtd = _dtd; 159 newNode._element = _element; 160 161 return newNode; 162 } 163 164 169 public Node cloneNode(boolean deep) 170 { 171 QDocument newDoc = new QDocument(); 172 173 newDoc._implementation = _implementation; 174 newDoc._dtd = _dtd; 175 if (_attributes != null) 176 newDoc._attributes = (HashMap ) _attributes.clone(); 177 newDoc._encoding = _encoding; 178 newDoc._version = _version; 179 180 if (_namespaces != null) 181 newDoc._namespaces = (HashMap ) _namespaces.clone(); 182 183 if (deep) { 184 for (Node node = getFirstChild(); 185 node != null; 186 node = node.getNextSibling()) { 187 newDoc.appendChild(newDoc.importNode(node, true)); 188 } 189 } 190 191 return newDoc; 192 } 193 194 Node importNode(QDocument doc, boolean deep) 195 { 196 return null; 197 } 198 199 207 public Node importNode(Node node, boolean deep) 208 { 209 if (node == null) 210 return null; 211 212 QName name; 213 214 switch (node.getNodeType()) { 215 case ELEMENT_NODE: 216 return importElement((Element) node, deep); 217 218 case ATTRIBUTE_NODE: 219 Attr attr = (Attr) node; 220 name = createName(attr.getNamespaceURI(), attr.getNodeName()); 221 QAttr newAttr = new QAttr(name, attr.getNodeValue()); 222 newAttr._owner = this; 223 return newAttr; 224 225 case TEXT_NODE: 226 QText newText = new QText(node.getNodeValue()); 227 newText._owner = this; 228 return newText; 229 230 case CDATA_SECTION_NODE: 231 QCdata newCData = new QCdata(node.getNodeValue()); 232 newCData._owner = this; 233 return newCData; 234 235 case ENTITY_REFERENCE_NODE: 236 QEntityReference newER = new QEntityReference(node.getNodeName()); 237 newER._owner = this; 238 return newER; 239 240 case ENTITY_NODE: 241 Entity oldEntity = (Entity) node; 242 QEntity newEntity = new QEntity(oldEntity.getNodeName(), 243 oldEntity.getNodeValue(), 244 oldEntity.getPublicId(), 245 oldEntity.getSystemId()); 246 newEntity._owner = this; 247 return newEntity; 248 249 case PROCESSING_INSTRUCTION_NODE: 250 QProcessingInstruction newPI; 251 newPI = new QProcessingInstruction(node.getNodeName(), 252 node.getNodeValue()); 253 254 newPI._owner = this; 255 return newPI; 256 257 case COMMENT_NODE: 258 QComment newComment = new QComment(node.getNodeValue()); 259 newComment._owner = this; 260 return newComment; 261 262 case DOCUMENT_FRAGMENT_NODE: 263 return importFragment((DocumentFragment) node, deep); 264 265 default: 266 throw new UnsupportedOperationException (String.valueOf(node)); 267 } 268 } 269 270 273 private Element importElement(Element elt, boolean deep) 274 { 275 QElement newElt = new QElement(createName(elt.getNamespaceURI(), 276 elt.getNodeName())); 277 QElement oldElt = null; 278 279 if (elt instanceof QElement) 280 oldElt = (QElement) elt; 281 282 newElt._owner = this; 283 284 if (oldElt != null) { 285 newElt._filename = oldElt._filename; 286 newElt._line = oldElt._line; 287 } 288 289 NamedNodeMap attrs = elt.getAttributes(); 290 291 int len = attrs.getLength(); 292 for (int i = 0; i < len; i++) { 293 Attr attr = (Attr) attrs.item(i); 294 295 newElt.setAttributeNode((Attr) importNode(attr, deep)); 296 } 297 298 if (! deep) 299 return newElt; 300 301 for (Node node = elt.getFirstChild(); 302 node != null; 303 node = node.getNextSibling()) { 304 newElt.appendChild(importNode(node, true)); 305 } 306 307 return newElt; 308 } 309 310 313 private DocumentFragment importFragment(DocumentFragment elt, boolean deep) 314 { 315 QDocumentFragment newFrag = new QDocumentFragment(); 316 317 newFrag._owner = this; 318 319 if (! deep) 320 return newFrag; 321 322 for (Node node = elt.getFirstChild(); 323 node != null; 324 node = node.getNextSibling()) { 325 newFrag.appendChild(importNode(node, true)); 326 } 327 328 return newFrag; 329 } 330 331 public DocumentType getDoctype() { return _dtd; } 332 333 public void setDoctype(DocumentType dtd) 334 { 335 QDocumentType qdtd = (QDocumentType) dtd; 336 337 _dtd = qdtd; 338 if (qdtd != null) 339 qdtd._owner = this; 340 } 341 342 public String getEncoding() 343 { 344 if (_encoding == null) 345 return null; 346 else 347 return _encoding; 348 } 349 350 public DOMImplementation getImplementation() 351 { 352 return _implementation; 353 } 354 355 public Element getDocumentElement() 356 { 357 return _element; 358 } 359 360 public void setDocumentElement(Element elt) 361 { 362 _element = (QElement) elt; 363 } 364 365 368 public Element createElement(String tagName) 369 throws DOMException 370 { 371 if (! isNameValid(tagName)) 372 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 373 "illegal tag `" + tagName + "'"); 374 375 QElement elt = new QElement(createName(null, tagName)); 376 elt._owner = this; 377 378 return elt; 379 } 380 381 384 public Element createElementNS(String namespaceURI, String name) 385 throws DOMException 386 { 387 QName qname = createName(namespaceURI, name); 388 389 validateName(qname); 390 addNamespace(qname); 391 392 QElement elt = new QElement(qname); 393 elt._owner = this; 394 395 return elt; 396 } 397 398 public void validateName(QName qname) 399 throws DOMException 400 { 401 String prefix = qname.getPrefix(); 402 String namespaceURI = qname.getNamespaceURI(); 403 404 if (qname.getPrefix() == "") { 405 } 406 else if (prefix == "xml" && 407 namespaceURI != "http://www.w3.org/XML/1998/namespace") 408 throw new DOMException(DOMException.NAMESPACE_ERR, 409 L.l("`xml' prefix expects namespace uri 'http://www.w3.org/XML/1998/namespace'")); 410 else if (prefix != "" && prefix != null && namespaceURI == null) 411 throw new DOMException(DOMException.NAMESPACE_ERR, 412 L.l("`{0}' prefix expects a namespace uri", 413 prefix)); 414 415 } 416 417 420 public Element createElement(String prefix, String local, String url) 421 throws DOMException 422 { 423 QName name = new QName (prefix, local, url); 424 addNamespace(name); 425 426 QElement elt = new QElement(name); 427 elt._owner = this; 428 429 return elt; 430 } 431 432 public Element createElementByName(QName name) 433 throws DOMException 434 { 435 QElement elt = new QElement(name); 436 elt._owner = this; 437 438 return elt; 439 } 440 441 444 public DocumentFragment createDocumentFragment() 445 { 446 QDocumentFragment frag = new QDocumentFragment(); 447 frag._owner = this; 448 449 return frag; 450 } 451 452 455 public Text createTextNode(String data) 456 { 457 if (data == null) 458 data = ""; 459 460 QText text = new QText(data); 461 text._owner = this; 462 463 return text; 464 } 465 466 public Text createUnescapedTextNode(String data) 467 { 468 if (data == null) 469 data = ""; 470 471 QText text = new QUnescapedText(data); 472 text._owner = this; 473 474 return text; 475 } 476 477 public Comment createComment(String data) 478 { 479 if (data == null) 480 data = ""; 481 482 QComment comment = new QComment(data); 483 comment._owner = this; 484 485 return comment; 486 } 487 488 public CDATASection createCDATASection(String data) 489 { 490 if (data == null) 491 data = ""; 492 493 QCdata cdata = new QCdata(data); 494 cdata._owner = this; 495 496 return cdata; 497 } 498 499 public ProcessingInstruction createProcessingInstruction(String target, 500 String data) 501 throws DOMException 502 { 503 if (target == null || target.length() == 0) 504 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 505 L.l("Empty processing instruction name. The processing instruction syntax is: <?name ... ?>")); 506 507 if (! isNameValid(target)) 508 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 509 L.l("`{0}' is an invalid processing instruction name. The processing instruction syntax is: <?name ... ?>", target)); 510 511 if (data == null) 512 data = ""; 513 514 QProcessingInstruction pi = new QProcessingInstruction(target, data); 515 pi._owner = this; 516 517 return pi; 518 } 519 520 public Attr createAttribute(String name, String value) 521 throws DOMException 522 { 523 if (! isNameValid(name)) 524 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 525 "illegal attribute `" + name + "'"); 526 527 if (value == null) 528 value = ""; 529 530 QAttr attr = new QAttr(new QName (null, name, null), value); 531 attr._owner = this; 532 533 return attr; 534 } 535 536 public Attr createAttribute(String name) 537 throws DOMException 538 { 539 return createAttribute(name, null); 540 } 541 542 545 public Attr createAttribute(String prefix, String local, String url) 546 throws DOMException 547 { 548 QName name = new QName (prefix, local, url); 549 if (url != null && ! url.equals("")) 550 addNamespace(prefix, url); 551 552 QAttr attr = new QAttr(name, null); 553 attr._owner = this; 554 555 return attr; 556 } 557 558 561 public Attr createAttributeNS(String namespaceURI, String qualifiedName) 562 throws DOMException 563 { 564 QName qname = createName(namespaceURI, qualifiedName); 565 566 validateName(qname); 567 addNamespace(qname); 568 569 575 576 QAttr attr = new QAttr(qname, null); 577 attr._owner = this; 578 579 return attr; 580 } 581 582 public QName createName(String uri, String name) 583 { 584 _nameKey.init(name, uri); 585 QName qName = _nameCache.get(_nameKey); 586 587 if (qName != null) 588 return qName; 589 590 if (uri == null) { 591 qName = new QName (null, name, null); 592 } 593 else { 594 int p = name.indexOf(':'); 595 String prefix; 596 String local; 597 if (p < 0) { 598 prefix = null; 599 local = name; 600 } 601 else { 602 prefix = name.substring(0, p); 603 local = name.substring(p + 1); 604 } 605 606 qName = new QName (prefix, local, uri); 607 } 608 609 _nameCache.put(new NameKey(name, uri), qName); 610 611 return qName; 612 } 613 614 617 public Attr createAttribute(QName name, String value) 618 throws DOMException 619 { 620 String url = name.getNamespaceURI(); 621 622 if (url != null && url != "") { 623 addNamespace(name.getPrefix(), url); 624 } 625 626 QAttr attr = new QAttr(name, value); 627 attr._owner = this; 628 629 return attr; 630 } 631 632 public EntityReference createEntityReference(String name) 633 throws DOMException 634 { 635 if (! isNameValid(name)) 636 throw new QDOMException(DOMException.INVALID_CHARACTER_ERR, 637 "illegal entityReference `" + name + "'"); 638 639 QEntityReference er = new QEntityReference(name); 640 er._owner = this; 641 642 return er; 643 } 644 645 648 public NodeList getElementsByTagName(String name) 649 { 650 if (_element == null) 651 return new QDeepNodeList(null, null, null); 652 else 653 return new QDeepNodeList(_element, _element, new QElement.TagPredicate(name)); 654 } 655 656 public NodeList getElementsByTagNameNS(String uri, String name) 657 { 658 if (_element == null) 659 return new QDeepNodeList(null, null, null); 660 else 661 return new QDeepNodeList(_element, _element, new QElement.NSTagPredicate(uri, name)); 662 } 663 664 public Element getElementById(String name) 665 { 666 Node node = _element; 667 668 for (; node != null; node = XmlUtil.getNext(node)) { 669 if (node instanceof Element) { 670 Element elt = (Element) node; 671 672 String id = elt.getAttribute("id"); 673 674 if (name.equals(id)) 675 return elt; 676 } 677 } 678 679 return null; 680 } 681 682 static public Document create() 683 { 684 QDocument doc = new QDocument(); 685 doc._masterDoc = doc; 686 687 return doc; 688 } 689 690 void setAttributes(HashMap <String ,String > attributes) 691 { 692 _attributes = attributes; 693 } 694 695 public Node appendChild(Node newChild) throws DOMException 696 { 697 if (newChild instanceof Element) { 698 _element = (QElement) newChild; 699 700 if (false && _namespaces != null) { 702 Iterator <String > iter = _namespaces.keySet().iterator(); 703 704 while (iter.hasNext()) { 705 String prefix = iter.next(); 706 String ns = _namespaces.get(prefix); 707 708 String xmlns; 709 710 if (prefix.equals("")) 711 xmlns = "xmlns"; 712 else 713 xmlns = "xmlns:" + prefix; 714 715 if (_element.getAttribute(xmlns).equals("")) { 716 QName qName = new QName (xmlns, XmlParser.XMLNS); 717 _element.setAttributeNode(createAttribute(qName, ns)); 718 } 719 } 720 } 721 } 722 723 return super.appendChild(newChild); 724 } 725 726 public Node removeChild(Node oldChild) throws DOMException 727 { 728 Node value = super.removeChild(oldChild); 729 if (oldChild == _element) 730 _element = null; 731 return value; 732 } 733 734 736 public void addNamespace(QName qname) 737 { 738 addNamespace(qname.getPrefix(), qname.getNamespaceURI()); 739 } 740 741 745 public void addNamespace(String prefix, String url) 746 { 747 if (url == null 748 || url.length() == 0 749 || XmlParser.XMLNS.equals(url) 750 || XmlParser.XML.equals(url)) 751 { 752 return; 753 } 754 755 if (prefix == null) 756 prefix = ""; 757 758 if (_namespaces == null) 759 _namespaces = new HashMap <String ,String >(); 760 761 String old = _namespaces.get(prefix); 762 if (old == null) 763 _namespaces.put(prefix, url.intern()); 764 } 765 766 public HashMap <String ,String > getNamespaces() 767 { 768 return _namespaces; 769 } 770 771 774 public String getNamespace(String prefix) 775 { 776 if (_namespaces == null) 777 return null; 778 else 779 return _namespaces.get(prefix); 780 } 781 782 785 public Iterator <String > getNamespaceKeys() 786 { 787 if (_namespaces == null) 788 return null; 789 790 return _namespaces.keySet().iterator(); 791 } 792 793 public Object getProperty(String name) 794 { 795 if (name.equals(DEPENDS)) 796 return _depends; 797 else 798 return null; 799 } 800 801 public ArrayList <Path> getDependList() 802 { 803 return _depends; 804 } 805 806 public ArrayList <Depend> getDependencyList() 807 { 808 return _dependList; 809 } 810 811 public void setProperty(String name, Object value) 812 { 813 if (name.equals(DEPENDS)) 814 _depends = (ArrayList ) value; 815 } 816 817 public String getActualEncoding() 819 { 820 throw new UnsupportedOperationException (); 821 } 822 823 public void setActualEncoding(String actualEncoding) 824 { 825 throw new UnsupportedOperationException (); 826 } 827 833 834 public void setEncoding(String encoding) 835 { 836 throw new UnsupportedOperationException (); 837 } 838 839 public boolean getStandalone() 840 { 841 return _standalone; 842 } 843 844 public void setStandalone(boolean standalone) 845 { 846 _standalone = true; 847 } 848 849 public String getXmlVersion() 850 { 851 return _version; 852 } 853 854 public void setXmlVersion(String version) 855 throws DOMException 856 { 857 _version = version; 858 } 859 860 public void setXmlStandalone(boolean value) 861 throws DOMException 862 { 863 } 864 865 public TypeInfo getSchemaTypeInfo() 866 { 867 return null; 868 } 869 870 public String getXmlEncoding() 871 { 872 return null; 873 } 874 875 public String getInputEncoding() 876 { 877 return null; 878 } 879 880 public boolean getXmlStandalone() 881 throws DOMException 882 { 883 return false; 884 } 885 886 public boolean getStrictErrorChecking() 887 { 888 throw new UnsupportedOperationException (); 889 } 890 891 public void setStrictErrorChecking(boolean strictErrorChecking) 892 { 893 throw new UnsupportedOperationException (); 894 } 895 896 public DOMErrorHandler getErrorHandler() 897 { 898 throw new UnsupportedOperationException (); 899 } 900 901 public void setErrorHandler(DOMErrorHandler errorHandler) 902 { 903 throw new UnsupportedOperationException (); 904 } 905 906 public String getDocumentURI() 907 { 908 throw new UnsupportedOperationException (); 909 } 910 911 public void setDocumentURI(String documentURI) 912 { 913 throw new UnsupportedOperationException (); 914 } 915 916 public Node adoptNode(Node source) 917 throws DOMException 918 { 919 throw new UnsupportedOperationException (); 920 } 921 922 public void normalizeDocument() 923 { 924 throw new UnsupportedOperationException (); 925 } 926 927 public boolean canSetNormalizationFeature(String name, 928 boolean state) 929 { 930 throw new UnsupportedOperationException (); 931 } 932 933 public void setNormalizationFeature(String name, 934 boolean state) 935 throws DOMException 936 { 937 throw new UnsupportedOperationException (); 938 } 939 940 public boolean getNormalizationFeature(String name) 941 throws DOMException 942 { 943 throw new UnsupportedOperationException (); 944 } 945 946 public Node renameNode(Node n, 947 String namespaceURI, 948 String name) 949 throws DOMException 950 { 951 throw new UnsupportedOperationException (); 952 } 953 954 956 public void addDepend(Path path) 957 { 958 if (path == null) 959 return; 960 961 if (_depends == null) 962 _depends = new ArrayList <Path>(); 963 964 if (! _depends.contains(path)) { 965 _depends.add(path); 966 967 if (_dependList == null) 968 _dependList = new ArrayList <Depend>(); 969 970 _dependList.add(new Depend(path)); 971 } 972 } 973 974 public boolean isModified() 975 { 976 if (_dependList == null) 977 return false; 978 979 for (int i = 0; i < _dependList.size(); i++) { 980 Depend depend = _dependList.get(i); 981 982 if (depend.isModified()) 983 return true; 984 } 985 986 return false; 987 } 988 989 void print(XmlPrinter os) throws IOException  990 { 991 os.startDocument(this); 992 993 if (_namespaces != null) { 994 Iterator <String > iter = _namespaces.keySet().iterator(); 995 while (iter.hasNext()) { 996 String prefix = iter.next(); 997 String url = _namespaces.get(prefix); 998 999 if (prefix.equals("")) 1000 os.attribute(null, prefix, "xmlns", url); 1001 else 1002 os.attribute(null, prefix, "xmlns:" + prefix, url); 1003 } 1004 } 1005 1006 if (getFirstChild() == null) 1007 os.printHeader(null); 1008 1009 for (Node node = getFirstChild(); 1010 node != null; 1011 node = node.getNextSibling()) { 1012 ((QAbstractNode) node).print(os); 1013 if (os.isPretty()) 1014 os.println(); 1015 } 1016 1017 os.endDocument(); 1018 } 1019 1020 public String toString() 1021 { 1022 String topElt = _element == null ? "XXX:top" : _element.getNodeName(); 1023 1024 if (_dtd == null) 1025 return "Document[" + topElt + "]"; 1026 1027 if (_dtd.getPublicId() != null && _dtd.getSystemId() != null) 1028 return ("Document[" + topElt + " PUBLIC '" + _dtd.getPublicId() + "' '" + 1029 _dtd.getSystemId() + "']"); 1030 else if (_dtd._publicId != null) 1031 return "Document[" + topElt + " PUBLIC '" + _dtd.getPublicId() + "']"; 1032 else if (_dtd.getSystemId() != null) 1033 return "Document[" + topElt + " SYSTEM '" + _dtd.getSystemId() + "']"; 1034 else 1035 return "Document[" + topElt + "]"; 1036 } 1037 1038 static class NameKey { 1039 String _qName; 1040 String _url; 1041 1042 NameKey() 1043 { 1044 } 1045 1046 NameKey(String qName, String url) 1047 { 1048 init(qName, url); 1049 } 1050 1051 void init(String qName, String url) 1052 { 1053 if (qName == null) 1054 throw new NullPointerException (); 1055 1056 if (url == null) 1057 url = ""; 1058 1059 _qName = qName; 1060 _url = url; 1061 } 1062 1063 public int hashCode() 1064 { 1065 return 65521 * _url.hashCode() + _qName.hashCode(); 1066 } 1067 1068 public boolean equals(Object b) 1069 { 1070 if (! (b instanceof NameKey)) 1071 return false; 1072 1073 NameKey key = (NameKey) b; 1074 1075 return _qName.equals(key._qName) && _url.equals(key._url); 1076 } 1077 } 1078 1079 private Object writeReplace() 1080 { 1081 return new SerializedXml(this); 1082 } 1083} 1084
| Popular Tags
|