1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.xml.dom; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 193c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilsonimport org.apache.xml.serializer.utils.SystemIDResolver; 203c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilsonimport org.apache.xml.utils.URI; 21a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilsonimport org.w3c.dom.Attr; 2212547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilsonimport org.w3c.dom.CharacterData; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.w3c.dom.DOMException; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.w3c.dom.Document; 25cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilsonimport org.w3c.dom.Element; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.w3c.dom.NamedNodeMap; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.w3c.dom.Node; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.w3c.dom.NodeList; 2912547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilsonimport org.w3c.dom.ProcessingInstruction; 3092e01317d2428856cee52965745d17699a33be5aJesse Wilsonimport org.w3c.dom.TypeInfo; 314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.UserDataHandler; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 333c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilsonimport javax.xml.transform.TransformerException; 34cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilsonimport java.util.ArrayList; 35cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilsonimport java.util.List; 36e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilsonimport java.util.Map; 37cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 39a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * A straightforward implementation of the corresponding W3C DOM node. 40a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * 41a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <p>Some fields have package visibility so other classes can access them while 42a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * maintaining the DOM structure. 43a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * 44a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <p>This class represents a Node that has neither a parent nor children. 45a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * Subclasses may have either. 46a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * 47a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <p>Some code was adapted from Apache Xerces. 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class NodeImpl implements Node { 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final NodeList EMPTY_LIST = new NodeListImpl(); 5292e01317d2428856cee52965745d17699a33be5aJesse Wilson 5392e01317d2428856cee52965745d17699a33be5aJesse Wilson static final TypeInfo NULL_TYPE_INFO = new TypeInfo() { 5492e01317d2428856cee52965745d17699a33be5aJesse Wilson public String getTypeName() { 5592e01317d2428856cee52965745d17699a33be5aJesse Wilson return null; 5692e01317d2428856cee52965745d17699a33be5aJesse Wilson } 5792e01317d2428856cee52965745d17699a33be5aJesse Wilson public String getTypeNamespace() { 5892e01317d2428856cee52965745d17699a33be5aJesse Wilson return null; 5992e01317d2428856cee52965745d17699a33be5aJesse Wilson } 6092e01317d2428856cee52965745d17699a33be5aJesse Wilson public boolean isDerivedFrom( 6192e01317d2428856cee52965745d17699a33be5aJesse Wilson String typeNamespaceArg, String typeNameArg, int derivationMethod) { 6292e01317d2428856cee52965745d17699a33be5aJesse Wilson return false; 6392e01317d2428856cee52965745d17699a33be5aJesse Wilson } 6492e01317d2428856cee52965745d17699a33be5aJesse Wilson }; 6592e01317d2428856cee52965745d17699a33be5aJesse Wilson 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DocumentImpl document; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project NodeImpl(DocumentImpl document) { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.document = document; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node appendChild(Node newChild) throws DOMException { 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 764daa600befc82e6f29ee943645dbbcc51f12097eJesse Wilson public final Node cloneNode(boolean deep) { 774daa600befc82e6f29ee943645dbbcc51f12097eJesse Wilson return document.cloneOrImportNode(UserDataHandler.NODE_CLONED, this, deep); 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public NamedNodeMap getAttributes() { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public NodeList getChildNodes() { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return EMPTY_LIST; 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node getFirstChild() { 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node getLastChild() { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getLocalName() { 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getNamespaceURI() { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node getNextSibling() { 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getNodeName() { 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public abstract short getNodeType(); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getNodeValue() throws DOMException { 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 118e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson public final Document getOwnerDocument() { 119e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson return document == this ? null : document; 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node getParentNode() { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getPrefix() { 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node getPreviousSibling() { 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean hasAttributes() { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean hasChildNodes() { 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node insertBefore(Node newChild, Node refChild) throws DOMException { 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean isSupported(String feature, String version) { 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return DOMImplementationImpl.getInstance().hasFeature(feature, version); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void normalize() { 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node removeChild(Node oldChild) throws DOMException { 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Node replaceChild(Node newChild, Node oldChild) throws DOMException { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16112547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson public final void setNodeValue(String nodeValue) throws DOMException { 16212547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson switch (getNodeType()) { 16312547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case CDATA_SECTION_NODE: 16412547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case COMMENT_NODE: 16512547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case TEXT_NODE: 16612547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson ((CharacterData) this).setData(nodeValue); 16712547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson return; 16812547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson 16912547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case PROCESSING_INSTRUCTION_NODE: 17012547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson ((ProcessingInstruction) this).setData(nodeValue); 17112547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson return; 17212547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson 17312547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case ATTRIBUTE_NODE: 17412547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson ((Attr) this).setValue(nodeValue); 17512547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson return; 17612547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson 17712547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case ELEMENT_NODE: 17812547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case ENTITY_REFERENCE_NODE: 17912547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case ENTITY_NODE: 18012547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case DOCUMENT_NODE: 18112547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case DOCUMENT_TYPE_NODE: 18212547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case DOCUMENT_FRAGMENT_NODE: 18312547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson case NOTATION_NODE: 18412547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson return; // do nothing! 18512547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson 18612547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson default: 18712547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 18812547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson "Unsupported node type " + getNodeType()); 18912547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson } 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setPrefix(String prefix) throws DOMException { 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 196a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * Validates the element or attribute namespace prefix on this node. 197a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * 198a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * @param namespaceAware whether this node is namespace aware 199a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * @param namespaceURI this node's namespace URI 200a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson */ 201271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson static String validatePrefix(String prefix, boolean namespaceAware, String namespaceURI) { 202a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (!namespaceAware) { 203a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson throw new DOMException(DOMException.NAMESPACE_ERR, prefix); 204a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 205a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 206a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (prefix != null) { 207a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (namespaceURI == null 208a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson || !DocumentImpl.isXMLIdentifier(prefix) 209a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson || "xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI) 210a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson || "xmlns".equals(prefix) && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) { 211a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson throw new DOMException(DOMException.NAMESPACE_ERR, prefix); 212a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 213a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 214a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 215a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return prefix; 216a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 217a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 218a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson /** 219271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * Sets the element or attribute node to be namespace-aware and assign it 220271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * the specified name and namespace URI. 221271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * 222271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * @param node an AttrImpl or ElementImpl node. 223271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * @param namespaceURI this node's namespace URI. May be null. 224271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson * @param qualifiedName a possibly-prefixed name like "img" or "html:img". 225271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson */ 226271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson static void setNameNS(NodeImpl node, String namespaceURI, String qualifiedName) { 227271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson if (qualifiedName == null) { 228271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); 229271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 230271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 231271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson String prefix = null; 232271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson int p = qualifiedName.lastIndexOf(":"); 233271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson if (p != -1) { 234271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson prefix = validatePrefix(qualifiedName.substring(0, p), true, namespaceURI); 235271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson qualifiedName = qualifiedName.substring(p + 1); 236271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 237271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 238271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson if (!DocumentImpl.isXMLIdentifier(qualifiedName)) { 239271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); 240271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 241271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 242271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson switch (node.getNodeType()) { 243271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson case ATTRIBUTE_NODE: 244271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson if ("xmlns".equals(qualifiedName) 245271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) { 246271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson throw new DOMException(DOMException.NAMESPACE_ERR, qualifiedName); 247271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 248271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 249271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson AttrImpl attr = (AttrImpl) node; 250271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson attr.namespaceAware = true; 251271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson attr.namespaceURI = namespaceURI; 252271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson attr.prefix = prefix; 253271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson attr.localName = qualifiedName; 254271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson break; 255271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 256271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson case ELEMENT_NODE: 257271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson ElementImpl element = (ElementImpl) node; 258271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson element.namespaceAware = true; 259271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson element.namespaceURI = namespaceURI; 260271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson element.prefix = prefix; 261271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson element.localName = qualifiedName; 262271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson break; 263271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 264271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson default: 265271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 266271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson "Cannot rename nodes of type " + node.getNodeType()); 267271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 268271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson } 269271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson 270271825415aa961bdd9f28a551575bcee6f27b4abJesse Wilson /** 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether a required string matches an actual string. This utility 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method is used for comparing namespaces and such. It takes into account 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * null arguments and the "*" special case. 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param required The required string. 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param actual The actual string. 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return True if and only if the actual string matches the required one. 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static boolean matchesName(String required, String actual, boolean wildcard) { 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (wildcard && "*".equals(required)) { 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (required == null) { 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (actual == null); 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return required.equals(actual); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether this node's name matches a required name. It takes into 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * account null arguments and the "*" special case. 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param name The required name. 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return True if and only if the actual name matches the required one. 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean matchesName(String name, boolean wildcard) { 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return matchesName(name, getNodeName(), wildcard); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Checks whether this node's namespace and local name match a required 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pair of namespace and local name. It takes into account null arguments 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the "*" special case. 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param namespaceURI The required namespace. 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param localName The required local name. 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return True if and only if the actual namespace and local name match 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the required pair of namespace and local name. 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean matchesNameNS(String namespaceURI, String localName, boolean wildcard) { 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return matchesName(namespaceURI, getNamespaceURI(), wildcard) && matchesName(localName, getLocalName(), wildcard); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 3154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3163c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson public final String getBaseURI() { 3173c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson switch (getNodeType()) { 3183c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case DOCUMENT_NODE: 3193c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return sanitizeUri(((Document) this).getDocumentURI()); 3203c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3213c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case ELEMENT_NODE: 3223c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson Element element = (Element) this; 3233c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson String uri = element.getAttributeNS( 3243c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson "http://www.w3.org/XML/1998/namespace", "base"); // or "xml:base" 3253c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3263c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // if this node has no base URI, return the parent's. 3273c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson if (uri == null || uri.length() == 0) { 3283c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return getParentBaseUri(); 3293c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3303c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3313c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // if this node's URI is absolute, return that 3323c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson if (SystemIDResolver.isAbsoluteURI(uri)) { 3333c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return uri; 3343c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3353c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3363c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // this node has a relative URI. Try to resolve it against the 3373c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // parent, but if that doesn't work just give up and return null. 3383c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson String parentUri = getParentBaseUri(); 3393c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson if (parentUri == null) { 3403c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3413c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3423c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson try { 3433c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return SystemIDResolver.getAbsoluteURI(uri, parentUri); 3443c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } catch (TransformerException e) { 3453c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; // the spec requires that we swallow exceptions 3463c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3473c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3483c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case PROCESSING_INSTRUCTION_NODE: 3493c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return getParentBaseUri(); 3503c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3513c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case NOTATION_NODE: 3523c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case ENTITY_NODE: 3533c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // When we support these node types, the parser should 3543c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // initialize a base URI field on these nodes. 3553c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3563c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3573c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case ENTITY_REFERENCE_NODE: 3583c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // TODO: get this value from the parser, falling back to the 3593c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson // referenced entity's baseURI if that doesn't exist 3603c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3613c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3623c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case DOCUMENT_TYPE_NODE: 3633c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case DOCUMENT_FRAGMENT_NODE: 3643c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case ATTRIBUTE_NODE: 3653c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case TEXT_NODE: 3663c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case CDATA_SECTION_NODE: 3673c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson case COMMENT_NODE: 3683c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3693c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3703c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson default: 3713c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 3723c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson "Unsupported node type " + getNodeType()); 3733c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3743c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3753c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3763c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson private String getParentBaseUri() { 3773c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson Node parentNode = getParentNode(); 3783c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return parentNode != null ? parentNode.getBaseURI() : null; 3793c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3803c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson 3813c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson /** 3823c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson * Returns the sanitized input if it is a URI, or {@code null} otherwise. 3833c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson */ 3843c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson private String sanitizeUri(String uri) { 3853c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson if (uri == null || uri.length() == 0) { 3863c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3873c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3883c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson try { 3893c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return new URI(uri).toString(); 3903c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } catch (URI.MalformedURIException e) { 3913c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson return null; 3923c5ed1cf96d6b0c24076d60202c9db43315e451dJesse Wilson } 3934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 3944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 3954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public short compareDocumentPosition(Node other) 3964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throws DOMException { 3974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson throw new UnsupportedOperationException(); // TODO 3984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 3994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 4004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public String getTextContent() throws DOMException { 401fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson return getNodeValue(); 402fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson } 403fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson 404fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson void getTextContent(StringBuilder buf) throws DOMException { 405fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson String content = getNodeValue(); 406fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson if (content != null) { 407fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson buf.append(content); 408fb1a80758587eecaa912130640bd9f3ef0d0d7bfJesse Wilson } 4094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 4104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 41112547dd7a3879e22e618f0464eb71a69cc15e2ccJesse Wilson public final void setTextContent(String textContent) throws DOMException { 412a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson switch (getNodeType()) { 413a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_TYPE_NODE: 414a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_NODE: 415a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return; // do nothing! 416a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 417a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ELEMENT_NODE: 418a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ENTITY_NODE: 419a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ENTITY_REFERENCE_NODE: 420a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_FRAGMENT_NODE: 421a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // remove all existing children 422a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson Node child; 423a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson while ((child = getFirstChild()) != null) { 424a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson removeChild(child); 425a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 426a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // create a text node to hold the given content 427606d8d2d12b615f58bc7614c490f9c48cf923e95Jesse Wilson if (textContent != null && textContent.length() != 0) { 428e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson appendChild(document.createTextNode(textContent)); 429a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 430a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return; 431a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 432a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ATTRIBUTE_NODE: 433a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case TEXT_NODE: 434a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case CDATA_SECTION_NODE: 435a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case PROCESSING_INSTRUCTION_NODE: 436a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case COMMENT_NODE: 437a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case NOTATION_NODE: 438a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson setNodeValue(textContent); 439a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return; 440a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 441a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson default: 442a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 443a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson "Unsupported node type " + getNodeType()); 444a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 4454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 4464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 4474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson public boolean isSameNode(Node other) { 448a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return this == other; 4494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 4504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 451a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson /** 452a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * Returns the element whose namespace definitions apply to this node. Use 453a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * this element when mapping prefixes to URIs and vice versa. 454a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson */ 455a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson private NodeImpl getNamespacingElement() { 456a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson switch (this.getNodeType()) { 457a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ELEMENT_NODE: 458a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return this; 459a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 460a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_NODE: 461a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return (NodeImpl) ((Document) this).getDocumentElement(); 462a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 463a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ENTITY_NODE: 464a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case NOTATION_NODE: 465a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_FRAGMENT_NODE: 466a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case DOCUMENT_TYPE_NODE: 467a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return null; 468a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 469a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ATTRIBUTE_NODE: 470a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return (NodeImpl) ((Attr) this).getOwnerElement(); 471a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 472a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case TEXT_NODE: 473a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case CDATA_SECTION_NODE: 474a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case ENTITY_REFERENCE_NODE: 475a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case PROCESSING_INSTRUCTION_NODE: 476a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson case COMMENT_NODE: 477a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return getContainingElement(); 478a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 479a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson default: 480a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson throw new DOMException(DOMException.NOT_SUPPORTED_ERR, 481a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson "Unsupported node type " + getNodeType()); 482a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 483a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 484a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 485a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson /** 486a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * Returns the nearest ancestor element that contains this node. 487a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson */ 488a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson private NodeImpl getContainingElement() { 489a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson for (Node p = getParentNode(); p != null; p = p.getParentNode()) { 490a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (p.getNodeType() == ELEMENT_NODE) { 491a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return (NodeImpl) p; 492a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 493a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 494a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return null; 495a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 496a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 497a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson public final String lookupPrefix(String namespaceURI) { 498a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (namespaceURI == null) { 499a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return null; 500a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 501a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 502a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // the XML specs define some prefixes (like "xml" and "xmlns") but this 503a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // API is explicitly defined to ignore those. 504a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 505a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson NodeImpl target = getNamespacingElement(); 506a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson for (NodeImpl node = target; node != null; node = node.getContainingElement()) { 507a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // check this element's namespace first 508a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (namespaceURI.equals(node.getNamespaceURI()) 509a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson && target.isPrefixMappedToUri(node.getPrefix(), namespaceURI)) { 510a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return node.getPrefix(); 511a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 512a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 513a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // search this element for an attribute of this form: 514a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // xmlns:foo="http://namespaceURI" 515a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (!node.hasAttributes()) { 516a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson continue; 517a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 518a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson NamedNodeMap attributes = node.getAttributes(); 519a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson for (int i = 0, length = attributes.getLength(); i < length; i++) { 520a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson Node attr = attributes.item(i); 521a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI()) 522a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson || !"xmlns".equals(attr.getPrefix()) 523a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson || !namespaceURI.equals(attr.getNodeValue())) { 524a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson continue; 525a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 526a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (target.isPrefixMappedToUri(attr.getLocalName(), namespaceURI)) { 527a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return attr.getLocalName(); 528a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 529a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 530a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 531a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 532a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return null; 533a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 534a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 535a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson /** 536a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * Returns true if the given prefix is mapped to the given URI on this 537a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * element. Since child elements can redefine prefixes, this check is 538a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * necessary: {@code 539a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <foo xmlns:a="http://good"> 540a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <bar xmlns:a="http://evil"> 541a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * <a:baz /> 542a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * </bar> 543a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * </foo>} 544a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * 545a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * @param prefix the prefix to find. Nullable. 546a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson * @param uri the URI to match. Non-null. 547a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson */ 548a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson boolean isPrefixMappedToUri(String prefix, String uri) { 549a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (prefix == null) { 550a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return false; 551a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 552a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 553a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson String actual = lookupNamespaceURI(prefix); 554a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return uri.equals(actual); 5554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 5564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 557cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson public final boolean isDefaultNamespace(String namespaceURI) { 558cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson String actual = lookupNamespaceURI(null); // null yields the default namespace 559cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return namespaceURI == null 560cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson ? actual == null 561cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson : namespaceURI.equals(actual); 5624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 5634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 564a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson public final String lookupNamespaceURI(String prefix) { 565a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson NodeImpl target = getNamespacingElement(); 566a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson for (NodeImpl node = target; node != null; node = node.getContainingElement()) { 567a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // check this element's namespace first 568a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson String nodePrefix = node.getPrefix(); 569a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (node.getNamespaceURI() != null) { 570a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (prefix == null // null => default prefix 571a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson ? nodePrefix == null 572a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson : prefix.equals(nodePrefix)) { 573a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return node.getNamespaceURI(); 574a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 575a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 576a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 577a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // search this element for an attribute of the appropriate form. 578a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // default namespace: xmlns="http://resultUri" 579a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson // non default: xmlns:specifiedPrefix="http://resultUri" 580a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (!node.hasAttributes()) { 581a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson continue; 582a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 583a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson NamedNodeMap attributes = node.getAttributes(); 584a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson for (int i = 0, length = attributes.getLength(); i < length; i++) { 585a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson Node attr = attributes.item(i); 586a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) { 587a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson continue; 588a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 589a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson if (prefix == null // null => default prefix 590a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson ? "xmlns".equals(attr.getNodeName()) 591a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson : "xmlns".equals(attr.getPrefix()) && prefix.equals(attr.getLocalName())) { 592a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson String value = attr.getNodeValue(); 593a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return value.length() > 0 ? value : null; 594a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 595a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 596a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson } 597a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson 598a76b64ab7f0ece60b794af13154d4150ca0170faJesse Wilson return null; 5994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 6004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 601cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson /** 602cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson * Returns a list of objects such that two nodes are equal if their lists 603cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson * are equal. Be careful: the lists may contain NamedNodeMaps and Nodes, 604cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson * neither of which override Object.equals(). Such values must be compared 605cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson * manually. 606cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson */ 607cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson private static List<Object> createEqualityKey(Node node) { 608cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson List<Object> values = new ArrayList<Object>(); 609cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getNodeType()); 610cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getNodeName()); 611cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getLocalName()); 612cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getNamespaceURI()); 613cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getPrefix()); 614cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(node.getNodeValue()); 615cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { 616cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(child); 617cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 618cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 619cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson switch (node.getNodeType()) { 620cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson case DOCUMENT_TYPE_NODE: 621cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson DocumentTypeImpl doctype = (DocumentTypeImpl) node; 622cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(doctype.getPublicId()); 623cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(doctype.getSystemId()); 624cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(doctype.getInternalSubset()); 625cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(doctype.getEntities()); 626cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(doctype.getNotations()); 627cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson break; 628cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 629cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson case ELEMENT_NODE: 630cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson Element element = (Element) node; 631cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson values.add(element.getAttributes()); 632cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson break; 633cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 634cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 635cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return values; 6364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 6374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 638cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson public final boolean isEqualNode(Node arg) { 639cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (arg == this) { 640cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return true; 641cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 642cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 643cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson List<Object> listA = createEqualityKey(this); 644cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson List<Object> listB = createEqualityKey(arg); 645cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 646cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (listA.size() != listB.size()) { 647cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 648cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 649cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 650cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson for (int i = 0; i < listA.size(); i++) { 651cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson Object a = listA.get(i); 652cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson Object b = listB.get(i); 653cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 654cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (a == b) { 655cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson continue; 656cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 657cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } else if (a == null || b == null) { 658cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 659cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 660cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } else if (a instanceof String || a instanceof Short) { 661cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (!a.equals(b)) { 662cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 663cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 664cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 665cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } else if (a instanceof NamedNodeMap) { 666cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (!(b instanceof NamedNodeMap) 667cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson || !namedNodeMapsEqual((NamedNodeMap) a, (NamedNodeMap) b)) { 668cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 669cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 670cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 671cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } else if (a instanceof Node) { 672cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (!(b instanceof Node) 673cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson || !((Node) a).isEqualNode((Node) b)) { 674cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 675cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 676cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 677cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } else { 678cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson throw new AssertionError(); // unexpected type 679cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 680cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 681cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 682cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return true; 683cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 684cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 685cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson private boolean namedNodeMapsEqual(NamedNodeMap a, NamedNodeMap b) { 686cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (a.getLength() != b.getLength()) { 687cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 688cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 689cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson for (int i = 0; i < a.getLength(); i++) { 690cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson Node aNode = a.item(i); 691cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson Node bNode = aNode.getLocalName() == null 692cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson ? b.getNamedItem(aNode.getNodeName()) 693cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson : b.getNamedItemNS(aNode.getNamespaceURI(), aNode.getLocalName()); 694cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson if (bNode == null || !aNode.isEqualNode(bNode)) { 695cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return false; 696cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 697cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 698cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return true; 699cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson } 700cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson 701cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson public final Object getFeature(String feature, String version) { 702cacbb893cd1361e7c7a63aa49ae85c0232813b9cJesse Wilson return isSupported(feature, version) ? this : null; 7034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 7044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 705e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson public final Object setUserData(String key, Object data, UserDataHandler handler) { 706e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson if (key == null) { 707e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson throw new NullPointerException(); 708e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson } 709e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson Map<String, UserData> map = document.getUserDataMap(this); 710e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson UserData previous = data == null 711e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson ? map.remove(key) 712e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson : map.put(key, new UserData(data, handler)); 713e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson return previous != null ? previous.value : null; 7144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 7154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson 716e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson public final Object getUserData(String key) { 717e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson if (key == null) { 718e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson throw new NullPointerException(); 719e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson } 720e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson Map<String, UserData> map = document.getUserDataMapForRead(this); 721e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson UserData userData = map.get(key); 722e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson return userData != null ? userData.value : null; 723e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson } 724e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson 725e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson static class UserData { 726e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson final Object value; 727e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson final UserDataHandler handler; 728e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson UserData(Object value, UserDataHandler handler) { 729e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson this.value = value; 730e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson this.handler = handler; 731e14d736a739d6523fd13d98f13e9d51167197a34Jesse Wilson } 7324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson } 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 734