diff options
author | Elliott Hughes <enh@google.com> | 2010-02-22 12:09:51 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2010-02-22 12:09:51 -0800 |
commit | e2a6f77f112c01109db196d8b19767896ee977ea (patch) | |
tree | c18066db46425e09a89b679c3b08153d0480d7e7 /xml/src | |
parent | cb78ba4051c82075119fd3646922a41e6355151b (diff) | |
parent | ea6435b142df4aaaf8854b3200b9f442b331f143 (diff) | |
download | libcore-e2a6f77f112c01109db196d8b19767896ee977ea.zip libcore-e2a6f77f112c01109db196d8b19767896ee977ea.tar.gz libcore-e2a6f77f112c01109db196d8b19767896ee977ea.tar.bz2 |
Merge remote branch 'goog/master' into mm
Conflicts:
libcore/JavaLibrary.mk
Diffstat (limited to 'xml/src')
37 files changed, 1448 insertions, 1338 deletions
diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java index 9c19835..4e689fb 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/AttrImpl.java @@ -73,7 +73,7 @@ public class AttrImpl extends NodeImpl implements Attr { throw new DOMException(DOMException.NAMESPACE_ERR, localName); } - if (!document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, localName); } @@ -90,11 +90,11 @@ public class AttrImpl extends NodeImpl implements Attr { String prefix = name.substring(0, prefixSeparator); String localName = name.substring(prefixSeparator + 1); - if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } else { - if (!document.isXMLIdentifier(name)) { + if (!DocumentImpl.isXMLIdentifier(name)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } @@ -108,7 +108,9 @@ public class AttrImpl extends NodeImpl implements Attr { } public String getName() { - return (prefix != null ? prefix + ":" : "") + localName; + return prefix != null + ? prefix + ":" + localName + : localName; } @Override @@ -148,27 +150,8 @@ public class AttrImpl extends NodeImpl implements Attr { } @Override - public void setNodeValue(String value) throws DOMException { - setValue(value); - } - - @Override public void setPrefix(String prefix) { - if (!namespaceAware) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if (prefix != null) { - if (namespaceURI == null || !document.isXMLIdentifier(prefix) || "xmlns".equals(prefix)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - } - - this.prefix = prefix; + this.prefix = validatePrefix(prefix, namespaceAware, namespaceURI); } public void setValue(String value) throws DOMException { diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java index 861f0a3..834cc47 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DOMImplementationImpl.java @@ -50,17 +50,24 @@ public class DOMImplementationImpl implements DOMImplementation { } public boolean hasFeature(String feature, String version) { - // We claim to support DOM Core Level 1 & 2, nothing else. + boolean anyVersion = version == null || version.length() == 0; + if (feature.startsWith("+")) { + feature = feature.substring(1); + } - // TODO + // TODO: fully implement these APIs: + // "LS" (org.w3c.dom.ls) versions "3.0" + // "ElementTraversal" (org.w3c.dom.traversal) versions "1.0" - if ("Core".equalsIgnoreCase(feature) || "XML".equalsIgnoreCase(feature)) { - if (version == null || "".equals(version) || "1.0".equals(version) || "2.0".equals(version)) { - return true; - } + if (feature.equalsIgnoreCase("Core")) { + return anyVersion || version.equals("1.0") || version.equals("2.0") || version.equals("3.0"); + } else if (feature.equalsIgnoreCase("XML")) { + return anyVersion || version.equals("1.0") || version.equals("2.0") || version.equals("3.0"); + } else if (feature.equalsIgnoreCase("XMLVersion")) { + return anyVersion || version.equals("1.0") || version.equals("1.1"); + } else { + return false; } - - return false; } /** diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java index 499f518..c8819cb 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentImpl.java @@ -100,6 +100,8 @@ public class DocumentImpl extends InnerNodeImpl implements Document { * @return The new node. */ Node cloneNode(Node node, boolean deep) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_CLONED event + Node target; switch (node.getNodeType()) { @@ -279,6 +281,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { } public Node importNode(Node importedNode, boolean deep) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_IMPORTED event return cloneNode(importedNode, deep); } @@ -296,6 +299,10 @@ public class DocumentImpl extends InnerNodeImpl implements Document { return super.insertChildAt(newChild, index); } + @Override public String getTextContent() throws DOMException { + return null; + } + public String getInputEncoding() { throw new UnsupportedOperationException(); // TODO } @@ -337,6 +344,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { } public Node adoptNode(Node source) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_ADOPTED event throw new UnsupportedOperationException(); // TODO } @@ -350,6 +358,7 @@ public class DocumentImpl extends InnerNodeImpl implements Document { public Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException { + // TODO: callback the UserDataHandler with a NODE_RENAMED event throw new UnsupportedOperationException(); // TODO } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java index df40d4b..67947b7 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/DocumentTypeImpl.java @@ -107,4 +107,7 @@ public class DocumentTypeImpl extends LeafNodeImpl implements DocumentType { return systemId; } + @Override public String getTextContent() throws DOMException { + return null; + } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java index 230e444..df1383d 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/ElementImpl.java @@ -65,7 +65,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { qualifiedName = qualifiedName.substring(p + 1); } - if (!document.isXMLIdentifier(qualifiedName)) { + if (!DocumentImpl.isXMLIdentifier(qualifiedName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, qualifiedName); } @@ -82,11 +82,11 @@ public class ElementImpl extends InnerNodeImpl implements Element { String prefix = name.substring(0, p); String localName = name.substring(p + 1); - if (!document.isXMLIdentifier(prefix) || !document.isXMLIdentifier(localName)) { + if (!DocumentImpl.isXMLIdentifier(prefix) || !DocumentImpl.isXMLIdentifier(localName)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } else { - if (!document.isXMLIdentifier(name)) { + if (!DocumentImpl.isXMLIdentifier(name)) { throw new DOMException(DOMException.INVALID_CHARACTER_ERR, name); } } @@ -241,7 +241,9 @@ public class ElementImpl extends InnerNodeImpl implements Element { } public String getTagName() { - return (prefix != null ? prefix + ":" : "") + localName; + return prefix != null + ? prefix + ":" + localName + : localName; } public boolean hasAttribute(String name) { @@ -281,7 +283,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { throw new DOMException(DOMException.NOT_FOUND_ERR, null); } - attributes.remove(oldAttr); + attributes.remove(oldAttrImpl); oldAttrImpl.ownerElement = null; return oldAttrImpl; @@ -362,21 +364,7 @@ public class ElementImpl extends InnerNodeImpl implements Element { @Override public void setPrefix(String prefix) { - if (!namespaceAware) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if (prefix != null) { - if (namespaceURI == null || !document.isXMLIdentifier(prefix)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - - if ("xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI)) { - throw new DOMException(DOMException.NAMESPACE_ERR, prefix); - } - } - - this.prefix = prefix; + this.prefix = validatePrefix(prefix, namespaceAware, namespaceURI); } public class ElementAttrNamedNodeMapImpl implements NamedNodeMap { diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java index f8ed85e..275bbf3 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java @@ -28,14 +28,16 @@ import java.util.List; * Provides a straightforward implementation of the corresponding W3C DOM * interface. The class is used internally only, thus only notable members that * are not in the original interface are documented (the W3C docs are quite - * extensive). Hope that's ok. - * <p> - * Some of the fields may have package visibility, so other classes belonging to - * the DOM implementation can easily access them while maintaining the DOM tree - * structure. - * <p> - * This class represents a Node that has a parent Node as well as (potentially) - * a number of children. + * extensive). + * + * <p>Some of the fields may have package visibility, so other classes belonging + * to the DOM implementation can easily access them while maintaining the DOM + * tree structure. + * + * <p>This class represents a Node that has a parent Node as well as + * (potentially) a number of children. + * + * <p>Some code was adapted from Apache Xerces. */ public abstract class InnerNodeImpl extends LeafNodeImpl { @@ -218,4 +220,35 @@ public abstract class InnerNodeImpl extends LeafNodeImpl { return oldChildImpl; } + public String getTextContent() throws DOMException { + Node child = getFirstChild(); + if (child == null) { + return ""; + } + + Node next = child.getNextSibling(); + if (next == null) { + return hasTextContent(child) ? child.getTextContent() : ""; + } + + StringBuilder buf = new StringBuilder(); + getTextContent(buf); + return buf.toString(); + } + + void getTextContent(StringBuilder buf) throws DOMException { + Node child = getFirstChild(); + while (child != null) { + if (hasTextContent(child)) { + ((NodeImpl) child).getTextContent(buf); + } + child = child.getNextSibling(); + } + } + + final boolean hasTextContent(Node child) { + // TODO: skip text nodes with ignorable whitespace? + return child.getNodeType() != Node.COMMENT_NODE + && child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE; + } } diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java index bf4d791..ebfdd52 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/NodeImpl.java @@ -16,24 +16,30 @@ package org.apache.harmony.xml.dom; +import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; import org.w3c.dom.DOMException; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.UserDataHandler; +import java.util.ArrayList; +import java.util.List; + /** - * Provides a straightforward implementation of the corresponding W3C DOM - * interface. The class is used internally only, thus only notable members that - * are not in the original interface are documented (the W3C docs are quite - * extensive). Hope that's ok. - * <p> - * Some of the fields may have package visibility, so other classes belonging to - * the DOM implementation can easily access them while maintaining the DOM tree - * structure. - * <p> - * This class represents a Node that has neither a parent nor children. + * A straightforward implementation of the corresponding W3C DOM node. + * + * <p>Some fields have package visibility so other classes can access them while + * maintaining the DOM structure. + * + * <p>This class represents a Node that has neither a parent nor children. + * Subclasses may have either. + * + * <p>Some code was adapted from Apache Xerces. */ public abstract class NodeImpl implements Node { @@ -135,13 +141,64 @@ public abstract class NodeImpl implements Node { throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, null); } - public void setNodeValue(String nodeValue) throws DOMException { + public final void setNodeValue(String nodeValue) throws DOMException { + switch (getNodeType()) { + case CDATA_SECTION_NODE: + case COMMENT_NODE: + case TEXT_NODE: + ((CharacterData) this).setData(nodeValue); + return; + + case PROCESSING_INSTRUCTION_NODE: + ((ProcessingInstruction) this).setData(nodeValue); + return; + + case ATTRIBUTE_NODE: + ((Attr) this).setValue(nodeValue); + return; + + case ELEMENT_NODE: + case ENTITY_REFERENCE_NODE: + case ENTITY_NODE: + case DOCUMENT_NODE: + case DOCUMENT_TYPE_NODE: + case DOCUMENT_FRAGMENT_NODE: + case NOTATION_NODE: + return; // do nothing! + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } } public void setPrefix(String prefix) throws DOMException { } /** + * Validates the element or attribute namespace prefix on this node. + * + * @param namespaceAware whether this node is namespace aware + * @param namespaceURI this node's namespace URI + */ + protected String validatePrefix(String prefix, boolean namespaceAware, String namespaceURI) { + if (!namespaceAware) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + + if (prefix != null) { + if (namespaceURI == null + || !DocumentImpl.isXMLIdentifier(prefix) + || "xml".equals(prefix) && !"http://www.w3.org/XML/1998/namespace".equals(namespaceURI) + || "xmlns".equals(prefix) && !"http://www.w3.org/2000/xmlns/".equals(namespaceURI)) { + throw new DOMException(DOMException.NAMESPACE_ERR, prefix); + } + } + + return prefix; + } + + /** * Checks whether a required string matches an actual string. This utility * method is used for comparing namespaces and such. It takes into account * null arguments and the "*" special case. @@ -190,7 +247,34 @@ public abstract class NodeImpl implements Node { } public String getBaseURI() { - throw new UnsupportedOperationException(); // TODO + /* + * TODO: implement. For reference, here's Xerces' behaviour: + * + * In all cases, the returned URI should be sanitized before it is + * returned. If the URI is malformed, null should be returned instead. + * + * For document nodes, this should return a member field that's + * initialized by the parser. + * + * For element nodes, this should first look for the xml:base attribute. + * if that exists and is absolute, it should be returned. + * if that exists and is relative, it should be resolved to the parent's base URI + * if it doesn't exist, the parent's baseURI should be returned + * + * For entity nodes, if a base URI exists that should be returned. + * Otherwise the document's base URI should be returned + * + * For entity references, if a base URI exists that should be returned + * otherwise it dereferences the entity (via the document) and uses the + * entity's base URI. + * + * For notations, it returns the base URI field. + * + * For processing instructions, it returns the parent's base URI. + * + * For all other node types, it returns null. + */ + return null; } public short compareDocumentPosition(Node other) @@ -199,35 +283,308 @@ public abstract class NodeImpl implements Node { } public String getTextContent() throws DOMException { - throw new UnsupportedOperationException(); // TODO + return getNodeValue(); } - public void setTextContent(String textContent) throws DOMException { - throw new UnsupportedOperationException(); // TODO + void getTextContent(StringBuilder buf) throws DOMException { + String content = getNodeValue(); + if (content != null) { + buf.append(content); + } + } + + public final void setTextContent(String textContent) throws DOMException { + switch (getNodeType()) { + case DOCUMENT_TYPE_NODE: + case DOCUMENT_NODE: + return; // do nothing! + + case ELEMENT_NODE: + case ENTITY_NODE: + case ENTITY_REFERENCE_NODE: + case DOCUMENT_FRAGMENT_NODE: + // remove all existing children + Node child; + while ((child = getFirstChild()) != null) { + removeChild(child); + } + // create a text node to hold the given content + if (textContent != null && textContent.length() != 0){ + appendChild(getOwnerDocument().createTextNode(textContent)); + } + return; + + case ATTRIBUTE_NODE: + case TEXT_NODE: + case CDATA_SECTION_NODE: + case PROCESSING_INSTRUCTION_NODE: + case COMMENT_NODE: + case NOTATION_NODE: + setNodeValue(textContent); + return; + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } } public boolean isSameNode(Node other) { - throw new UnsupportedOperationException(); // TODO + return this == other; } - public String lookupPrefix(String namespaceURI) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns the element whose namespace definitions apply to this node. Use + * this element when mapping prefixes to URIs and vice versa. + */ + private NodeImpl getNamespacingElement() { + switch (this.getNodeType()) { + case ELEMENT_NODE: + return this; + + case DOCUMENT_NODE: + return (NodeImpl) ((Document) this).getDocumentElement(); + + case ENTITY_NODE: + case NOTATION_NODE: + case DOCUMENT_FRAGMENT_NODE: + case DOCUMENT_TYPE_NODE: + return null; + + case ATTRIBUTE_NODE: + return (NodeImpl) ((Attr) this).getOwnerElement(); + + case TEXT_NODE: + case CDATA_SECTION_NODE: + case ENTITY_REFERENCE_NODE: + case PROCESSING_INSTRUCTION_NODE: + case COMMENT_NODE: + return getContainingElement(); + + default: + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported node type " + getNodeType()); + } } - public boolean isDefaultNamespace(String namespaceURI) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns the nearest ancestor element that contains this node. + */ + private NodeImpl getContainingElement() { + for (Node p = getParentNode(); p != null; p = p.getParentNode()) { + if (p.getNodeType() == ELEMENT_NODE) { + return (NodeImpl) p; + } + } + return null; } - public String lookupNamespaceURI(String prefix) { - throw new UnsupportedOperationException(); // TODO + public final String lookupPrefix(String namespaceURI) { + if (namespaceURI == null) { + return null; + } + + // the XML specs define some prefixes (like "xml" and "xmlns") but this + // API is explicitly defined to ignore those. + + NodeImpl target = getNamespacingElement(); + for (NodeImpl node = target; node != null; node = node.getContainingElement()) { + // check this element's namespace first + if (namespaceURI.equals(node.getNamespaceURI()) + && target.isPrefixMappedToUri(node.getPrefix(), namespaceURI)) { + return node.getPrefix(); + } + + // search this element for an attribute of this form: + // xmlns:foo="http://namespaceURI" + if (!node.hasAttributes()) { + continue; + } + NamedNodeMap attributes = node.getAttributes(); + for (int i = 0, length = attributes.getLength(); i < length; i++) { + Node attr = attributes.item(i); + if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI()) + || !"xmlns".equals(attr.getPrefix()) + || !namespaceURI.equals(attr.getNodeValue())) { + continue; + } + if (target.isPrefixMappedToUri(attr.getLocalName(), namespaceURI)) { + return attr.getLocalName(); + } + } + } + + return null; } - public boolean isEqualNode(Node arg) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns true if the given prefix is mapped to the given URI on this + * element. Since child elements can redefine prefixes, this check is + * necessary: {@code + * <foo xmlns:a="http://good"> + * <bar xmlns:a="http://evil"> + * <a:baz /> + * </bar> + * </foo>} + * + * @param prefix the prefix to find. Nullable. + * @param uri the URI to match. Non-null. + */ + boolean isPrefixMappedToUri(String prefix, String uri) { + if (prefix == null) { + return false; + } + + String actual = lookupNamespaceURI(prefix); + return uri.equals(actual); + } + + public final boolean isDefaultNamespace(String namespaceURI) { + String actual = lookupNamespaceURI(null); // null yields the default namespace + return namespaceURI == null + ? actual == null + : namespaceURI.equals(actual); + } + + public final String lookupNamespaceURI(String prefix) { + NodeImpl target = getNamespacingElement(); + for (NodeImpl node = target; node != null; node = node.getContainingElement()) { + // check this element's namespace first + String nodePrefix = node.getPrefix(); + if (node.getNamespaceURI() != null) { + if (prefix == null // null => default prefix + ? nodePrefix == null + : prefix.equals(nodePrefix)) { + return node.getNamespaceURI(); + } + } + + // search this element for an attribute of the appropriate form. + // default namespace: xmlns="http://resultUri" + // non default: xmlns:specifiedPrefix="http://resultUri" + if (!node.hasAttributes()) { + continue; + } + NamedNodeMap attributes = node.getAttributes(); + for (int i = 0, length = attributes.getLength(); i < length; i++) { + Node attr = attributes.item(i); + if (!"http://www.w3.org/2000/xmlns/".equals(attr.getNamespaceURI())) { + continue; + } + if (prefix == null // null => default prefix + ? "xmlns".equals(attr.getNodeName()) + : "xmlns".equals(attr.getPrefix()) && prefix.equals(attr.getLocalName())) { + String value = attr.getNodeValue(); + return value.length() > 0 ? value : null; + } + } + } + + return null; } - public Object getFeature(String feature, String version) { - throw new UnsupportedOperationException(); // TODO + /** + * Returns a list of objects such that two nodes are equal if their lists + * are equal. Be careful: the lists may contain NamedNodeMaps and Nodes, + * neither of which override Object.equals(). Such values must be compared + * manually. + */ + private static List<Object> createEqualityKey(Node node) { + List<Object> values = new ArrayList<Object>(); + values.add(node.getNodeType()); + values.add(node.getNodeName()); + values.add(node.getLocalName()); + values.add(node.getNamespaceURI()); + values.add(node.getPrefix()); + values.add(node.getNodeValue()); + for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { + values.add(child); + } + + switch (node.getNodeType()) { + case DOCUMENT_TYPE_NODE: + DocumentTypeImpl doctype = (DocumentTypeImpl) node; + values.add(doctype.getPublicId()); + values.add(doctype.getSystemId()); + values.add(doctype.getInternalSubset()); + values.add(doctype.getEntities()); + values.add(doctype.getNotations()); + break; + + case ELEMENT_NODE: + Element element = (Element) node; + values.add(element.getAttributes()); + break; + } + + return values; + } + + public final boolean isEqualNode(Node arg) { + if (arg == this) { + return true; + } + + List<Object> listA = createEqualityKey(this); + List<Object> listB = createEqualityKey(arg); + + if (listA.size() != listB.size()) { + return false; + } + + for (int i = 0; i < listA.size(); i++) { + Object a = listA.get(i); + Object b = listB.get(i); + + if (a == b) { + continue; + + } else if (a == null || b == null) { + return false; + + } else if (a instanceof String || a instanceof Short) { + if (!a.equals(b)) { + return false; + } + + } else if (a instanceof NamedNodeMap) { + if (!(b instanceof NamedNodeMap) + || !namedNodeMapsEqual((NamedNodeMap) a, (NamedNodeMap) b)) { + return false; + } + + } else if (a instanceof Node) { + if (!(b instanceof Node) + || !((Node) a).isEqualNode((Node) b)) { + return false; + } + + } else { + throw new AssertionError(); // unexpected type + } + } + + return true; + } + + private boolean namedNodeMapsEqual(NamedNodeMap a, NamedNodeMap b) { + if (a.getLength() != b.getLength()) { + return false; + } + for (int i = 0; i < a.getLength(); i++) { + Node aNode = a.item(i); + Node bNode = aNode.getLocalName() == null + ? b.getNamedItem(aNode.getNodeName()) + : b.getNamedItemNS(aNode.getNamespaceURI(), aNode.getLocalName()); + if (bNode == null || !aNode.isEqualNode(bNode)) { + return false; + } + } + return true; + } + + public final Object getFeature(String feature, String version) { + return isSupported(feature, version) ? this : null; } public Object setUserData(String key, Object data, diff --git a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java index 3905865..5c9d123 100644 --- a/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/dom/TextImpl.java @@ -46,11 +46,6 @@ public class TextImpl extends CharacterDataImpl implements Text { return Node.TEXT_NODE; } - @Override - public String getNodeValue() { - return getData(); - } - public Text splitText(int offset) throws DOMException { Text newText = getOwnerDocument().createTextNode( substringData(offset, getLength() - offset)); diff --git a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java index 5a3c48c..52240aa 100644 --- a/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java +++ b/xml/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java @@ -115,8 +115,8 @@ class DocumentBuilderImpl extends DocumentBuilder { Document document = newDocument(); try { - XmlPullParser parser = new KXmlParser(); - + KXmlParser parser = new KXmlParser(); + parser.keepNamespaceAttributes(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, namespaceAware); diff --git a/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java b/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java index 78d0cc5..618b412 100644 --- a/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java +++ b/xml/src/main/java/org/apache/xalan/processor/TransformerFactoryImpl.java @@ -792,7 +792,7 @@ public class TransformerFactoryImpl extends SAXTransformerFactory try { m_errorListener.fatalError( ex ); - return null; + return null; // TODO: but the API promises to never return null... } catch( TransformerConfigurationException ex1 ) { diff --git a/xml/src/main/java/org/apache/xml/utils/DOMHelper.java b/xml/src/main/java/org/apache/xml/utils/DOMHelper.java index 76721d0..53d0adc 100644 --- a/xml/src/main/java/org/apache/xml/utils/DOMHelper.java +++ b/xml/src/main/java/org/apache/xml/utils/DOMHelper.java @@ -85,16 +85,23 @@ public class DOMHelper DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); dfactory.setNamespaceAware(true); - dfactory.setValidating(true); - - if (isSecureProcessing) - { - try - { - dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } - catch (ParserConfigurationException pce) {} - } + // BEGIN android-removed + // If set, DocumentBuilderFactoryImpl.newDocumentBuilder() fails + // because we haven't implemented validation + // dfactory.setValidating(true); + // BEGIN android-removed + + // BEGIN android-removed + // We haven't implemented secure processing + // if (isSecureProcessing) + // { + // try + // { + // dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + // } + // catch (ParserConfigurationException pce) {} + // } + // END android-removed DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); Document outNode = docBuilder.newDocument(); diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java index c4d8f3d..99eb03b 100644 --- a/xml/src/main/java/org/kxml2/io/KXmlParser.java +++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java @@ -45,6 +45,7 @@ public class KXmlParser implements XmlPullParser { private boolean processNsp; private boolean relaxed; + private boolean keepNamespaceAttributes; // android-added private Hashtable entityMap; private int depth; private String[] elementStack = new String[16]; @@ -80,6 +81,14 @@ public class KXmlParser implements XmlPullParser { private boolean degenerated; private int attributeCount; + + /** + * The current element's attributes arranged in groups of 4: + * i + 0 = attribute namespace URI + * i + 1 = attribute namespace prefix + * i + 2 = attribute qualified name (may contain ":", as in "html:h1") + * i + 3 = attribute value + */ private String[] attributes = new String[16]; // private int stackMismatch = 0; private String error; @@ -100,6 +109,19 @@ public class KXmlParser implements XmlPullParser { new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128]; } + // BEGIN android-added + /** + * Retains namespace attributes like {@code xmlns="http://foo"} or {@code + * xmlns:foo="http:foo"} in pulled elements. Most applications will only be + * interested in the effective namespaces of their elements, so these + * attributes aren't useful. But for structure preserving wrappers like DOM, + * it is necessary to keep the namespace data around. + */ + public void keepNamespaceAttributes() { + this.keepNamespaceAttributes = true; + } + // END android-added + private final boolean isProp(String n1, boolean prop, String n2) { if (!n1.startsWith("http://xmlpull.org/v1/doc/")) return false; @@ -148,14 +170,23 @@ public class KXmlParser implements XmlPullParser { //System.out.println (prefixMap); - System.arraycopy( - attributes, - i + 4, - attributes, - i, - ((--attributeCount) << 2) - i); - - i -= 4; + // BEGIN android-changed + if (keepNamespaceAttributes) { + // explicitly set the namespace for unprefixed attributes + // such as xmlns="http://foo" + attributes[i] = "http://www.w3.org/2000/xmlns/"; + any = true; + } else { + System.arraycopy( + attributes, + i + 4, + attributes, + i, + ((--attributeCount) << 2) - i); + + i -= 4; + } + // END android-changed } } diff --git a/xml/src/main/java/org/w3c/dom/Attr.java b/xml/src/main/java/org/w3c/dom/Attr.java index d9ed6ff..bd7267b 100644 --- a/xml/src/main/java/org/w3c/dom/Attr.java +++ b/xml/src/main/java/org/w3c/dom/Attr.java @@ -176,7 +176,7 @@ public interface Attr extends Node { /** * On retrieval, the value of the attribute is returned as a string. * Character and general entity references are replaced with their - * values. See also the method <code>getAttribute</code> on the + * values. See also the method <code>getAttribute</code> on the * <code>Element</code> interface. * <br>On setting, this creates a <code>Text</code> node with the unparsed * contents of the string, i.e. any characters that an XML processor diff --git a/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java b/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java deleted file mode 100644 index 76644bc..0000000 --- a/xml/src/main/java/org/w3c/dom/events/DocumentEvent.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.DOMException; - -/** - * The <code>DocumentEvent</code> interface provides a mechanism by which the - * user can create an Event of a type supported by the implementation. It is - * expected that the <code>DocumentEvent</code> interface will be - * implemented on the same object which implements the <code>Document</code> - * interface in an implementation which supports the Event model. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface DocumentEvent { - /** - * - * @param eventType The <code>eventType</code> parameter specifies the - * type of <code>Event</code> interface to be created. If the - * <code>Event</code> interface specified is supported by the - * implementation this method will return a new <code>Event</code> of - * the interface type requested. If the <code>Event</code> is to be - * dispatched via the <code>dispatchEvent</code> method the - * appropriate event init method must be called after creation in - * order to initialize the <code>Event</code>'s values. As an example, - * a user wishing to synthesize some kind of <code>UIEvent</code> - * would call <code>createEvent</code> with the parameter "UIEvents". - * The <code>initUIEvent</code> method could then be called on the - * newly created <code>UIEvent</code> to set the specific type of - * UIEvent to be dispatched and set its context information.The - * <code>createEvent</code> method is used in creating - * <code>Event</code>s when it is either inconvenient or unnecessary - * for the user to create an <code>Event</code> themselves. In cases - * where the implementation provided <code>Event</code> is - * insufficient, users may supply their own <code>Event</code> - * implementations for use with the <code>dispatchEvent</code> method. - * @return The newly created <code>Event</code> - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the implementation does not support the - * type of <code>Event</code> interface requested - */ - public Event createEvent(String eventType) - throws DOMException; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/Event.java b/xml/src/main/java/org/w3c/dom/events/Event.java deleted file mode 100644 index 14a9239..0000000 --- a/xml/src/main/java/org/w3c/dom/events/Event.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The <code>Event</code> interface is used to provide contextual information - * about an event to the handler processing the event. An object which - * implements the <code>Event</code> interface is generally passed as the - * first parameter to an event handler. More specific context information is - * passed to event handlers by deriving additional interfaces from - * <code>Event</code> which contain information directly relating to the - * type of event they accompany. These derived interfaces are also - * implemented by the object passed to the event listener. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface Event { - // PhaseType - /** - * The current event phase is the capturing phase. - */ - public static final short CAPTURING_PHASE = 1; - /** - * The event is currently being evaluated at the target - * <code>EventTarget</code>. - */ - public static final short AT_TARGET = 2; - /** - * The current event phase is the bubbling phase. - */ - public static final short BUBBLING_PHASE = 3; - - /** - * The name of the event (case-insensitive). The name must be an XML name. - */ - public String getType(); - - /** - * Used to indicate the <code>EventTarget</code> to which the event was - * originally dispatched. - */ - public EventTarget getTarget(); - - /** - * Used to indicate the <code>EventTarget</code> whose - * <code>EventListeners</code> are currently being processed. This is - * particularly useful during capturing and bubbling. - */ - public EventTarget getCurrentTarget(); - - /** - * Used to indicate which phase of event flow is currently being - * evaluated. - */ - public short getEventPhase(); - - /** - * Used to indicate whether or not an event is a bubbling event. If the - * event can bubble the value is true, else the value is false. - */ - public boolean getBubbles(); - - /** - * Used to indicate whether or not an event can have its default action - * prevented. If the default action can be prevented the value is true, - * else the value is false. - */ - public boolean getCancelable(); - - /** - * Used to specify the time (in milliseconds relative to the epoch) at - * which the event was created. Due to the fact that some systems may - * not provide this information the value of <code>timeStamp</code> may - * be not available for all events. When not available, a value of 0 - * will be returned. Examples of epoch time are the time of the system - * start or 0:0:0 UTC 1st January 1970. - */ - public long getTimeStamp(); - - /** - * The <code>stopPropagation</code> method is used prevent further - * propagation of an event during event flow. If this method is called - * by any <code>EventListener</code> the event will cease propagating - * through the tree. The event will complete dispatch to all listeners - * on the current <code>EventTarget</code> before event flow stops. This - * method may be used during any stage of event flow. - */ - public void stopPropagation(); - - /** - * If an event is cancelable, the <code>preventDefault</code> method is - * used to signify that the event is to be canceled, meaning any default - * action normally taken by the implementation as a result of the event - * will not occur. If, during any stage of event flow, the - * <code>preventDefault</code> method is called the event is canceled. - * Any default action associated with the event will not occur. Calling - * this method for a non-cancelable event has no effect. Once - * <code>preventDefault</code> has been called it will remain in effect - * throughout the remainder of the event's propagation. This method may - * be used during any stage of event flow. - */ - public void preventDefault(); - - /** - * The <code>initEvent</code> method is used to initialize the value of an - * <code>Event</code> created through the <code>DocumentEvent</code> - * interface. This method may only be called before the - * <code>Event</code> has been dispatched via the - * <code>dispatchEvent</code> method, though it may be called multiple - * times during that phase if necessary. If called multiple times the - * final invocation takes precedence. If called from a subclass of - * <code>Event</code> interface only the values specified in the - * <code>initEvent</code> method are modified, all other attributes are - * left unchanged. - * @param eventTypeArg Specifies the event type. This type may be any - * event type currently defined in this specification or a new event - * type.. The string must be an XML name. Any new event type must not - * begin with any upper, lower, or mixed case version of the string - * "DOM". This prefix is reserved for future DOM event sets. It is - * also strongly recommended that third parties adding their own - * events use their own prefix to avoid confusion and lessen the - * probability of conflicts with other new events. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - */ - public void initEvent(String eventTypeArg, - boolean canBubbleArg, - boolean cancelableArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventException.java b/xml/src/main/java/org/w3c/dom/events/EventException.java deleted file mode 100644 index 7a6ff26..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * Event operations may throw an <code>EventException</code> as specified in - * their method descriptions. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public class EventException extends RuntimeException { - public EventException(short code, String message) { - super(message); - this.code = code; - } - public short code; - // EventExceptionCode - /** - * If the <code>Event</code>'s type was not specified by initializing the - * event before the method was called. Specification of the Event's type - * as <code>null</code> or an empty string will also trigger this - * exception. - */ - public static final short UNSPECIFIED_EVENT_TYPE_ERR = 0; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventListener.java b/xml/src/main/java/org/w3c/dom/events/EventListener.java deleted file mode 100644 index 1df8020..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The <code>EventListener</code> interface is the primary method for - * handling events. Users implement the <code>EventListener</code> interface - * and register their listener on an <code>EventTarget</code> using the - * <code>AddEventListener</code> method. The users should also remove their - * <code>EventListener</code> from its <code>EventTarget</code> after they - * have completed using the listener. - * <p> When a <code>Node</code> is copied using the <code>cloneNode</code> - * method the <code>EventListener</code>s attached to the source - * <code>Node</code> are not attached to the copied <code>Node</code>. If - * the user wishes the same <code>EventListener</code>s to be added to the - * newly created copy the user must add them manually. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface EventListener { - /** - * This method is called whenever an event occurs of the type for which - * the <code> EventListener</code> interface was registered. - * @param evt The <code>Event</code> contains contextual information - * about the event. It also contains the <code>stopPropagation</code> - * and <code>preventDefault</code> methods which are used in - * determining the event's flow and default action. - */ - public void handleEvent(Event evt); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/EventTarget.java b/xml/src/main/java/org/w3c/dom/events/EventTarget.java deleted file mode 100644 index f076636..0000000 --- a/xml/src/main/java/org/w3c/dom/events/EventTarget.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -/** - * The <code>EventTarget</code> interface is implemented by all - * <code>Nodes</code> in an implementation which supports the DOM Event - * Model. Therefore, this interface can be obtained by using - * binding-specific casting methods on an instance of the <code>Node</code> - * interface. The interface allows registration and removal of - * <code>EventListeners</code> on an <code>EventTarget</code> and dispatch - * of events to that <code>EventTarget</code>. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface EventTarget { - /** - * This method allows the registration of event listeners on the event - * target. If an <code>EventListener</code> is added to an - * <code>EventTarget</code> while it is processing an event, it will not - * be triggered by the current actions but may be triggered during a - * later stage of event flow, such as the bubbling phase. - * <br> If multiple identical <code>EventListener</code>s are registered - * on the same <code>EventTarget</code> with the same parameters the - * duplicate instances are discarded. They do not cause the - * <code>EventListener</code> to be called twice and since they are - * discarded they do not need to be removed with the - * <code>removeEventListener</code> method. - * @param type The event type for which the user is registering - * @param listener The <code>listener</code> parameter takes an interface - * implemented by the user which contains the methods to be called - * when the event occurs. - * @param useCapture If true, <code>useCapture</code> indicates that the - * user wishes to initiate capture. After initiating capture, all - * events of the specified type will be dispatched to the registered - * <code>EventListener</code> before being dispatched to any - * <code>EventTargets</code> beneath them in the tree. Events which - * are bubbling upward through the tree will not trigger an - * <code>EventListener</code> designated to use capture. - */ - public void addEventListener(String type, - EventListener listener, - boolean useCapture); - - /** - * This method allows the removal of event listeners from the event - * target. If an <code>EventListener</code> is removed from an - * <code>EventTarget</code> while it is processing an event, it will not - * be triggered by the current actions. <code>EventListener</code>s can - * never be invoked after being removed. - * <br>Calling <code>removeEventListener</code> with arguments which do - * not identify any currently registered <code>EventListener</code> on - * the <code>EventTarget</code> has no effect. - * @param type Specifies the event type of the <code>EventListener</code> - * being removed. - * @param listener The <code>EventListener</code> parameter indicates the - * <code>EventListener </code> to be removed. - * @param useCapture Specifies whether the <code>EventListener</code> - * being removed was registered as a capturing listener or not. If a - * listener was registered twice, one with capture and one without, - * each must be removed separately. Removal of a capturing listener - * does not affect a non-capturing version of the same listener, and - * vice versa. - */ - public void removeEventListener(String type, - EventListener listener, - boolean useCapture); - - /** - * This method allows the dispatch of events into the implementations - * event model. Events dispatched in this manner will have the same - * capturing and bubbling behavior as events dispatched directly by the - * implementation. The target of the event is the - * <code> EventTarget</code> on which <code>dispatchEvent</code> is - * called. - * @param evt Specifies the event type, behavior, and contextual - * information to be used in processing the event. - * @return The return value of <code>dispatchEvent</code> indicates - * whether any of the listeners which handled the event called - * <code>preventDefault</code>. If <code>preventDefault</code> was - * called the value is false, else the value is true. - * @exception EventException - * UNSPECIFIED_EVENT_TYPE_ERR: Raised if the <code>Event</code>'s type - * was not specified by initializing the event before - * <code>dispatchEvent</code> was called. Specification of the - * <code>Event</code>'s type as <code>null</code> or an empty string - * will also trigger this exception. - */ - public boolean dispatchEvent(Event evt) - throws EventException; - -} diff --git a/xml/src/main/java/org/w3c/dom/events/MouseEvent.java b/xml/src/main/java/org/w3c/dom/events/MouseEvent.java deleted file mode 100644 index be78035..0000000 --- a/xml/src/main/java/org/w3c/dom/events/MouseEvent.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.views.AbstractView; - -/** - * The <code>MouseEvent</code> interface provides specific contextual - * information associated with Mouse events. - * <p>The <code>detail</code> attribute inherited from <code>UIEvent</code> - * indicates the number of times a mouse button has been pressed and - * released over the same screen location during a user action. The - * attribute value is 1 when the user begins this action and increments by 1 - * for each full sequence of pressing and releasing. If the user moves the - * mouse between the mousedown and mouseup the value will be set to 0, - * indicating that no click is occurring. - * <p>In the case of nested elements mouse events are always targeted at the - * most deeply nested element. Ancestors of the targeted element may use - * bubbling to obtain notification of mouse events which occur within its - * descendent elements. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface MouseEvent extends UIEvent { - /** - * The horizontal coordinate at which the event occurred relative to the - * origin of the screen coordinate system. - */ - public int getScreenX(); - - /** - * The vertical coordinate at which the event occurred relative to the - * origin of the screen coordinate system. - */ - public int getScreenY(); - - /** - * The horizontal coordinate at which the event occurred relative to the - * DOM implementation's client area. - */ - public int getClientX(); - - /** - * The vertical coordinate at which the event occurred relative to the DOM - * implementation's client area. - */ - public int getClientY(); - - /** - * Used to indicate whether the 'ctrl' key was depressed during the firing - * of the event. - */ - public boolean getCtrlKey(); - - /** - * Used to indicate whether the 'shift' key was depressed during the - * firing of the event. - */ - public boolean getShiftKey(); - - /** - * Used to indicate whether the 'alt' key was depressed during the firing - * of the event. On some platforms this key may map to an alternative - * key name. - */ - public boolean getAltKey(); - - /** - * Used to indicate whether the 'meta' key was depressed during the firing - * of the event. On some platforms this key may map to an alternative - * key name. - */ - public boolean getMetaKey(); - - /** - * During mouse events caused by the depression or release of a mouse - * button, <code>button</code> is used to indicate which mouse button - * changed state. The values for <code>button</code> range from zero to - * indicate the left button of the mouse, one to indicate the middle - * button if present, and two to indicate the right button. For mice - * configured for left handed use in which the button actions are - * reversed the values are instead read from right to left. - */ - public short getButton(); - - /** - * Used to identify a secondary <code>EventTarget</code> related to a UI - * event. Currently this attribute is used with the mouseover event to - * indicate the <code>EventTarget</code> which the pointing device - * exited and with the mouseout event to indicate the - * <code>EventTarget</code> which the pointing device entered. - */ - public EventTarget getRelatedTarget(); - - /** - * The <code>initMouseEvent</code> method is used to initialize the value - * of a <code>MouseEvent</code> created through the - * <code>DocumentEvent</code> interface. This method may only be called - * before the <code>MouseEvent</code> has been dispatched via the - * <code>dispatchEvent</code> method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param viewArg Specifies the <code>Event</code>'s - * <code>AbstractView</code>. - * @param detailArg Specifies the <code>Event</code>'s mouse click count. - * @param screenXArg Specifies the <code>Event</code>'s screen x - * coordinate - * @param screenYArg Specifies the <code>Event</code>'s screen y - * coordinate - * @param clientXArg Specifies the <code>Event</code>'s client x - * coordinate - * @param clientYArg Specifies the <code>Event</code>'s client y - * coordinate - * @param ctrlKeyArg Specifies whether or not control key was depressed - * during the <code>Event</code>. - * @param altKeyArg Specifies whether or not alt key was depressed during - * the <code>Event</code>. - * @param shiftKeyArg Specifies whether or not shift key was depressed - * during the <code>Event</code>. - * @param metaKeyArg Specifies whether or not meta key was depressed - * during the <code>Event</code>. - * @param buttonArg Specifies the <code>Event</code>'s mouse button. - * @param relatedTargetArg Specifies the <code>Event</code>'s related - * <code>EventTarget</code>. - */ - public void initMouseEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - AbstractView viewArg, - int detailArg, - int screenXArg, - int screenYArg, - int clientXArg, - int clientYArg, - boolean ctrlKeyArg, - boolean altKeyArg, - boolean shiftKeyArg, - boolean metaKeyArg, - short buttonArg, - EventTarget relatedTargetArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/MutationEvent.java b/xml/src/main/java/org/w3c/dom/events/MutationEvent.java deleted file mode 100644 index 3db4003..0000000 --- a/xml/src/main/java/org/w3c/dom/events/MutationEvent.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.Node; - -/** - * The <code>MutationEvent</code> interface provides specific contextual - * information associated with Mutation events. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface MutationEvent extends Event { - // attrChangeType - /** - * The <code>Attr</code> was modified in place. - */ - public static final short MODIFICATION = 1; - /** - * The <code>Attr</code> was just added. - */ - public static final short ADDITION = 2; - /** - * The <code>Attr</code> was just removed. - */ - public static final short REMOVAL = 3; - - /** - * <code>relatedNode</code> is used to identify a secondary node related - * to a mutation event. For example, if a mutation event is dispatched - * to a node indicating that its parent has changed, the - * <code>relatedNode</code> is the changed parent. If an event is - * instead dispatched to a subtree indicating a node was changed within - * it, the <code>relatedNode</code> is the changed node. In the case of - * the DOMAttrModified event it indicates the <code>Attr</code> node - * which was modified, added, or removed. - */ - public Node getRelatedNode(); - - /** - * <code>prevValue</code> indicates the previous value of the - * <code>Attr</code> node in DOMAttrModified events, and of the - * <code>CharacterData</code> node in DOMCharacterDataModified events. - */ - public String getPrevValue(); - - /** - * <code>newValue</code> indicates the new value of the <code>Attr</code> - * node in DOMAttrModified events, and of the <code>CharacterData</code> - * node in DOMCharacterDataModified events. - */ - public String getNewValue(); - - /** - * <code>attrName</code> indicates the name of the changed - * <code>Attr</code> node in a DOMAttrModified event. - */ - public String getAttrName(); - - /** - * <code>attrChange</code> indicates the type of change which triggered - * the DOMAttrModified event. The values can be <code>MODIFICATION</code> - * , <code>ADDITION</code>, or <code>REMOVAL</code>. - */ - public short getAttrChange(); - - /** - * The <code>initMutationEvent</code> method is used to initialize the - * value of a <code>MutationEvent</code> created through the - * <code>DocumentEvent</code> interface. This method may only be called - * before the <code>MutationEvent</code> has been dispatched via the - * <code>dispatchEvent</code> method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param relatedNodeArg Specifies the <code>Event</code>'s related Node. - * @param prevValueArg Specifies the <code>Event</code>'s - * <code>prevValue</code> attribute. This value may be null. - * @param newValueArg Specifies the <code>Event</code>'s - * <code>newValue</code> attribute. This value may be null. - * @param attrNameArg Specifies the <code>Event</code>'s - * <code>attrName</code> attribute. This value may be null. - * @param attrChangeArg Specifies the <code>Event</code>'s - * <code>attrChange</code> attribute - */ - public void initMutationEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - Node relatedNodeArg, - String prevValueArg, - String newValueArg, - String attrNameArg, - short attrChangeArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/events/UIEvent.java b/xml/src/main/java/org/w3c/dom/events/UIEvent.java deleted file mode 100644 index 15affe8..0000000 --- a/xml/src/main/java/org/w3c/dom/events/UIEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.events; - -import org.w3c.dom.views.AbstractView; - -/** - * The <code>UIEvent</code> interface provides specific contextual information - * associated with User Interface events. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113'>Document Object Model (DOM) Level 2 Events Specification</a>. - * @since DOM Level 2 - */ -public interface UIEvent extends Event { - /** - * The <code>view</code> attribute identifies the <code>AbstractView</code> - * from which the event was generated. - */ - public AbstractView getView(); - - /** - * Specifies some detail information about the <code>Event</code>, - * depending on the type of event. - */ - public int getDetail(); - - /** - * The <code>initUIEvent</code> method is used to initialize the value of - * a <code>UIEvent</code> created through the <code>DocumentEvent</code> - * interface. This method may only be called before the - * <code>UIEvent</code> has been dispatched via the - * <code>dispatchEvent</code> method, though it may be called multiple - * times during that phase if necessary. If called multiple times, the - * final invocation takes precedence. - * @param typeArg Specifies the event type. - * @param canBubbleArg Specifies whether or not the event can bubble. - * @param cancelableArg Specifies whether or not the event's default - * action can be prevented. - * @param viewArg Specifies the <code>Event</code>'s - * <code>AbstractView</code>. - * @param detailArg Specifies the <code>Event</code>'s detail. - */ - public void initUIEvent(String typeArg, - boolean canBubbleArg, - boolean cancelableArg, - AbstractView viewArg, - int detailArg); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java b/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java deleted file mode 100644 index 601a5be..0000000 --- a/xml/src/main/java/org/w3c/dom/ls/LSLoadEvent.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2004 World Wide Web Consortium, - * - * (Massachusetts Institute of Technology, European Research Consortium for - * Informatics and Mathematics, Keio University). All Rights Reserved. This - * work is distributed under the W3C(r) Software License [1] in the hope that - * it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - */ - -package org.w3c.dom.ls; - -import org.w3c.dom.Document; -import org.w3c.dom.events.Event; - -/** - * This interface represents a load event object that signals the completion - * of a document load. - * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407'>Document Object Model (DOM) Level 3 Load -and Save Specification</a>. - */ -public interface LSLoadEvent extends Event { - /** - * The document that finished loading. - */ - public Document getNewDocument(); - - /** - * The input source that was parsed. - */ - public LSInput getInput(); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java b/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java deleted file mode 100644 index da98e14..0000000 --- a/xml/src/main/java/org/w3c/dom/ls/LSProgressEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2004 World Wide Web Consortium, - * - * (Massachusetts Institute of Technology, European Research Consortium for - * Informatics and Mathematics, Keio University). All Rights Reserved. This - * work is distributed under the W3C(r) Software License [1] in the hope that - * it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 - */ - -package org.w3c.dom.ls; - -import org.w3c.dom.events.Event; - -/** - * This interface represents a progress event object that notifies the - * application about progress as a document is parsed. It extends the - * <code>Event</code> interface defined in [<a href='http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107'>DOM Level 3 Events</a>] - * . - * <p> The units used for the attributes <code>position</code> and - * <code>totalSize</code> are not specified and can be implementation and - * input dependent. - * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407'>Document Object Model (DOM) Level 3 Load -and Save Specification</a>. - */ -public interface LSProgressEvent extends Event { - /** - * The input source that is being parsed. - */ - public LSInput getInput(); - - /** - * The current position in the input source, including all external - * entities and other resources that have been read. - */ - public int getPosition(); - - /** - * The total size of the document including all external resources, this - * number might change as a document is being parsed if references to - * more external resources are seen. A value of <code>0</code> is - * returned if the total size cannot be determined or estimated. - */ - public int getTotalSize(); - -} diff --git a/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java b/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java index e7b6350..33b094a 100644 --- a/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java +++ b/xml/src/main/java/org/w3c/dom/ls/LSSerializer.java @@ -330,7 +330,9 @@ public interface LSSerializer { * <br> The filter is invoked after the operations requested by the * <code>DOMConfiguration</code> parameters have been applied. For * example, CDATA sections won't be passed to the filter if "<a href='http://www.w3.org/TR/DOM-Level-3-Core/core.html#parameter-cdata-sections'> - * cdata-sections</a>" is set to <code>false</code>. + * cdata-sections</a>" is set to <code>false</code>. + * + * @hide */ public LSSerializerFilter getFilter(); /** @@ -341,7 +343,9 @@ public interface LSSerializer { * <br> The filter is invoked after the operations requested by the * <code>DOMConfiguration</code> parameters have been applied. For * example, CDATA sections won't be passed to the filter if "<a href='http://www.w3.org/TR/DOM-Level-3-Core/core.html#parameter-cdata-sections'> - * cdata-sections</a>" is set to <code>false</code>. + * cdata-sections</a>" is set to <code>false</code>. + * + * @hide */ public void setFilter(LSSerializerFilter filter); diff --git a/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java b/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java index 049459c..9e76b37 100644 --- a/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java +++ b/xml/src/main/java/org/w3c/dom/ls/LSSerializerFilter.java @@ -41,6 +41,8 @@ import org.w3c.dom.traversal.NodeFilter; * document. * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407'>Document Object Model (DOM) Level 3 Load and Save Specification</a>. + * + * @hide */ public interface LSSerializerFilter extends NodeFilter { /** diff --git a/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java b/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java deleted file mode 100644 index bc45ad9..0000000 --- a/xml/src/main/java/org/w3c/dom/traversal/DocumentTraversal.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.traversal; - -import org.w3c.dom.Node; -import org.w3c.dom.DOMException; - -/** - * <code>DocumentTraversal</code> contains methods that create - * <code>NodeIterators</code> and <code>TreeWalkers</code> to traverse a - * node and its children in document order (depth first, pre-order - * traversal, which is equivalent to the order in which the start tags occur - * in the text representation of the document). In DOMs which support the - * Traversal feature, <code>DocumentTraversal</code> will be implemented by - * the same objects that implement the Document interface. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document Object Model (DOM) Level 2 Traversal and Range Specification</a>. - * @since DOM Level 2 - */ -public interface DocumentTraversal { - /** - * Create a new <code>NodeIterator</code> over the subtree rooted at the - * specified node. - * @param root The node which will be iterated together with its - * children. The <code>NodeIterator</code> is initially positioned - * just before this node. The <code>whatToShow</code> flags and the - * filter, if any, are not considered when setting this position. The - * root must not be <code>null</code>. - * @param whatToShow This flag specifies which node types may appear in - * the logical view of the tree presented by the - * <code>NodeIterator</code>. See the description of - * <code>NodeFilter</code> for the set of possible <code>SHOW_</code> - * values.These flags can be combined using <code>OR</code>. - * @param filter The <code>NodeFilter</code> to be used with this - * <code>NodeIterator</code>, or <code>null</code> to indicate no - * filter. - * @param entityReferenceExpansion The value of this flag determines - * whether entity reference nodes are expanded. - * @return The newly created <code>NodeIterator</code>. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the specified <code>root</code> is - * <code>null</code>. - */ - public NodeIterator createNodeIterator(Node root, - int whatToShow, - NodeFilter filter, - boolean entityReferenceExpansion) - throws DOMException; - - /** - * Create a new <code>TreeWalker</code> over the subtree rooted at the - * specified node. - * @param root The node which will serve as the <code>root</code> for the - * <code>TreeWalker</code>. The <code>whatToShow</code> flags and the - * <code>NodeFilter</code> are not considered when setting this value; - * any node type will be accepted as the <code>root</code>. The - * <code>currentNode</code> of the <code>TreeWalker</code> is - * initialized to this node, whether or not it is visible. The - * <code>root</code> functions as a stopping point for traversal - * methods that look upward in the document structure, such as - * <code>parentNode</code> and nextNode. The <code>root</code> must - * not be <code>null</code>. - * @param whatToShow This flag specifies which node types may appear in - * the logical view of the tree presented by the - * <code>TreeWalker</code>. See the description of - * <code>NodeFilter</code> for the set of possible <code>SHOW_</code> - * values.These flags can be combined using <code>OR</code>. - * @param filter The <code>NodeFilter</code> to be used with this - * <code>TreeWalker</code>, or <code>null</code> to indicate no filter. - * @param entityReferenceExpansion If this flag is false, the contents of - * <code>EntityReference</code> nodes are not presented in the logical - * view. - * @return The newly created <code>TreeWalker</code>. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if the specified <code>root</code> is - * <code>null</code>. - */ - public TreeWalker createTreeWalker(Node root, - int whatToShow, - NodeFilter filter, - boolean entityReferenceExpansion) - throws DOMException; - -} diff --git a/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java b/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java index b9beac4..4d179e7 100644 --- a/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java +++ b/xml/src/main/java/org/w3c/dom/traversal/NodeFilter.java @@ -31,6 +31,8 @@ import org.w3c.dom.Node; * encouraging code reuse. * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document Object Model (DOM) Level 2 Traversal and Range Specification</a>. * @since DOM Level 2 + * + * @hide */ public interface NodeFilter { // Constants returned by acceptNode diff --git a/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java b/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java index d1f0d08..e55cd9f 100644 --- a/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java +++ b/xml/src/main/java/org/w3c/dom/traversal/NodeIterator.java @@ -27,6 +27,8 @@ import org.w3c.dom.DOMException; * <code>DocumentTraversal</code><code>.createNodeIterator()</code>. * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document Object Model (DOM) Level 2 Traversal and Range Specification</a>. * @since DOM Level 2 + * + * @hide */ public interface NodeIterator { /** diff --git a/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java b/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java deleted file mode 100644 index f5fff86..0000000 --- a/xml/src/main/java/org/w3c/dom/traversal/TreeWalker.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.traversal; - -import org.w3c.dom.Node; -import org.w3c.dom.DOMException; - -/** - * <code>TreeWalker</code> objects are used to navigate a document tree or - * subtree using the view of the document defined by their - * <code>whatToShow</code> flags and filter (if any). Any function which - * performs navigation using a <code>TreeWalker</code> will automatically - * support any view defined by a <code>TreeWalker</code>. - * <p>Omitting nodes from the logical view of a subtree can result in a - * structure that is substantially different from the same subtree in the - * complete, unfiltered document. Nodes that are siblings in the - * <code>TreeWalker</code> view may be children of different, widely - * separated nodes in the original view. For instance, consider a - * <code>NodeFilter</code> that skips all nodes except for Text nodes and - * the root node of a document. In the logical view that results, all text - * nodes will be siblings and appear as direct children of the root node, no - * matter how deeply nested the structure of the original document. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document Object Model (DOM) Level 2 Traversal and Range Specification</a>. - * @since DOM Level 2 - */ -public interface TreeWalker { - /** - * The <code>root</code> node of the <code>TreeWalker</code>, as specified - * when it was created. - */ - public Node getRoot(); - - /** - * This attribute determines which node types are presented via the - * <code>TreeWalker</code>. The available set of constants is defined in - * the <code>NodeFilter</code> interface. Nodes not accepted by - * <code>whatToShow</code> will be skipped, but their children may still - * be considered. Note that this skip takes precedence over the filter, - * if any. - */ - public int getWhatToShow(); - - /** - * The filter used to screen nodes. - */ - public NodeFilter getFilter(); - - /** - * The value of this flag determines whether the children of entity - * reference nodes are visible to the <code>TreeWalker</code>. If false, - * these children and their descendants will be rejected. Note that - * this rejection takes precedence over <code>whatToShow</code> and the - * filter, if any. - * <br> To produce a view of the document that has entity references - * expanded and does not expose the entity reference node itself, use - * the <code>whatToShow</code> flags to hide the entity reference node - * and set <code>expandEntityReferences</code> to true when creating the - * <code>TreeWalker</code>. To produce a view of the document that has - * entity reference nodes but no entity expansion, use the - * <code>whatToShow</code> flags to show the entity reference node and - * set <code>expandEntityReferences</code> to false. - */ - public boolean getExpandEntityReferences(); - - /** - * The node at which the <code>TreeWalker</code> is currently positioned. - * <br>Alterations to the DOM tree may cause the current node to no longer - * be accepted by the <code>TreeWalker</code>'s associated filter. - * <code>currentNode</code> may also be explicitly set to any node, - * whether or not it is within the subtree specified by the - * <code>root</code> node or would be accepted by the filter and - * <code>whatToShow</code> flags. Further traversal occurs relative to - * <code>currentNode</code> even if it is not part of the current view, - * by applying the filters in the requested direction; if no traversal - * is possible, <code>currentNode</code> is not changed. - */ - public Node getCurrentNode(); - /** - * The node at which the <code>TreeWalker</code> is currently positioned. - * <br>Alterations to the DOM tree may cause the current node to no longer - * be accepted by the <code>TreeWalker</code>'s associated filter. - * <code>currentNode</code> may also be explicitly set to any node, - * whether or not it is within the subtree specified by the - * <code>root</code> node or would be accepted by the filter and - * <code>whatToShow</code> flags. Further traversal occurs relative to - * <code>currentNode</code> even if it is not part of the current view, - * by applying the filters in the requested direction; if no traversal - * is possible, <code>currentNode</code> is not changed. - * @exception DOMException - * NOT_SUPPORTED_ERR: Raised if an attempt is made to set - * <code>currentNode</code> to <code>null</code>. - */ - public void setCurrentNode(Node currentNode) - throws DOMException; - - /** - * Moves to and returns the closest visible ancestor node of the current - * node. If the search for <code>parentNode</code> attempts to step - * upward from the <code>TreeWalker</code>'s <code>root</code> node, or - * if it fails to find a visible ancestor node, this method retains the - * current position and returns <code>null</code>. - * @return The new parent node, or <code>null</code> if the current node - * has no parent in the <code>TreeWalker</code>'s logical view. - */ - public Node parentNode(); - - /** - * Moves the <code>TreeWalker</code> to the first visible child of the - * current node, and returns the new node. If the current node has no - * visible children, returns <code>null</code>, and retains the current - * node. - * @return The new node, or <code>null</code> if the current node has no - * visible children in the <code>TreeWalker</code>'s logical view. - */ - public Node firstChild(); - - /** - * Moves the <code>TreeWalker</code> to the last visible child of the - * current node, and returns the new node. If the current node has no - * visible children, returns <code>null</code>, and retains the current - * node. - * @return The new node, or <code>null</code> if the current node has no - * children in the <code>TreeWalker</code>'s logical view. - */ - public Node lastChild(); - - /** - * Moves the <code>TreeWalker</code> to the previous sibling of the - * current node, and returns the new node. If the current node has no - * visible previous sibling, returns <code>null</code>, and retains the - * current node. - * @return The new node, or <code>null</code> if the current node has no - * previous sibling. in the <code>TreeWalker</code>'s logical view. - */ - public Node previousSibling(); - - /** - * Moves the <code>TreeWalker</code> to the next sibling of the current - * node, and returns the new node. If the current node has no visible - * next sibling, returns <code>null</code>, and retains the current node. - * @return The new node, or <code>null</code> if the current node has no - * next sibling. in the <code>TreeWalker</code>'s logical view. - */ - public Node nextSibling(); - - /** - * Moves the <code>TreeWalker</code> to the previous visible node in - * document order relative to the current node, and returns the new - * node. If the current node has no previous node, or if the search for - * <code>previousNode</code> attempts to step upward from the - * <code>TreeWalker</code>'s <code>root</code> node, returns - * <code>null</code>, and retains the current node. - * @return The new node, or <code>null</code> if the current node has no - * previous node in the <code>TreeWalker</code>'s logical view. - */ - public Node previousNode(); - - /** - * Moves the <code>TreeWalker</code> to the next visible node in document - * order relative to the current node, and returns the new node. If the - * current node has no next node, or if the search for nextNode attempts - * to step upward from the <code>TreeWalker</code>'s <code>root</code> - * node, returns <code>null</code>, and retains the current node. - * @return The new node, or <code>null</code> if the current node has no - * next node in the <code>TreeWalker</code>'s logical view. - */ - public Node nextNode(); - -} diff --git a/xml/src/main/java/org/w3c/dom/views/AbstractView.java b/xml/src/main/java/org/w3c/dom/views/AbstractView.java deleted file mode 100644 index 97e8f0e..0000000 --- a/xml/src/main/java/org/w3c/dom/views/AbstractView.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.views; - -/** - * A base interface that all views shall derive from. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113'>Document Object Model (DOM) Level 2 Views Specification</a>. - * @since DOM Level 2 - */ -public interface AbstractView { - /** - * The source <code>DocumentView</code> of which this is an - * <code>AbstractView</code>. - */ - public DocumentView getDocument(); - -} diff --git a/xml/src/main/java/org/w3c/dom/views/DocumentView.java b/xml/src/main/java/org/w3c/dom/views/DocumentView.java deleted file mode 100644 index 2cb9eeb..0000000 --- a/xml/src/main/java/org/w3c/dom/views/DocumentView.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2000 World Wide Web Consortium, - * (Massachusetts Institute of Technology, Institut National de - * Recherche en Informatique et en Automatique, Keio University). All - * Rights Reserved. This program is distributed under the W3C's Software - * Intellectual Property License. This program is distributed in the - * hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. - * See W3C License http://www.w3.org/Consortium/Legal/ for more details. - */ - -package org.w3c.dom.views; - -/** - * The <code>DocumentView</code> interface is implemented by - * <code>Document</code> objects in DOM implementations supporting DOM - * Views. It provides an attribute to retrieve the default view of a - * document. - * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113'>Document Object Model (DOM) Level 2 Views Specification</a>. - * @since DOM Level 2 - */ -public interface DocumentView { - /** - * The default <code>AbstractView</code> for this <code>Document</code>, - * or <code>null</code> if none available. - */ - public AbstractView getDefaultView(); - -} diff --git a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java index da37c45..3f0d2cb 100644 --- a/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java +++ b/xml/src/test/java/org/apache/harmony/xml/XsltXPathConformanceTestSuite.java @@ -22,15 +22,16 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.w3c.dom.Attr; -import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.ProcessingInstruction; -import org.w3c.dom.Text; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlSerializer; @@ -38,17 +39,25 @@ import org.xmlpull.v1.XmlSerializer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.ErrorListener; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; @@ -60,13 +69,23 @@ import java.util.List; * XSLT conformance test suite</a>, adapted for use by JUnit. To run these tests * on a device: * <ul> - * <li>Obtain the <a href="http://www.oasis-open.org/committees/download.php/12171/XSLT-testsuite-04.ZIP">test - * suite zip file from the OASIS project site.</li> - * <li>Unzip. - * <li>Copy the files to a device: <code>adb shell mkdir /data/oasis ; - * adb push ./XSLT-Conformance-TC /data/oasis</code>. - * <li>Invoke this class' main method, passing the on-device path to the test - * suite's <code>catalog.xml</code> file as an argument. + * <li>Obtain the <a href="http://www.oasis-open.org/committees/download.php/12171/XSLT-testsuite-04.ZIP">test + * suite zip file from the OASIS project site.</li> + * <li>Unzip. + * <li>Copy the files to a device: <code>adb shell mkdir /data/oasis ; + * adb push ./XSLT-Conformance-TC /data/oasis</code>. + * <li>Invoke this class' main method, passing the on-device path to the test + * suite's <code>catalog.xml</code> file as an argument. + * </ul> + * + * <p>Unfortunately, some of the tests in the OASIS suite will fail when + * executed outside of their original development environment: + * <ul> + * <li>The tests assume case insensitive filesystems. Some will fail with + * "Couldn't open file" errors due to a mismatch in file name casing. + * <li>The tests assume certain network hosts will exist and serve + * stylesheet files. In particular, "http://webxtest/" isn't generally + * available. * </ul> */ public class XsltXPathConformanceTestSuite { @@ -77,7 +96,7 @@ public class XsltXPathConformanceTestSuite { /** Orders element attributes by optional URI and name. */ private static final Comparator<Attr> orderByName = new Comparator<Attr>() { public int compare(Attr a, Attr b) { - int result = compareNullsFirst(a.getBaseURI(), b.getBaseURI()); + int result = compareNullsFirst(a.getNamespaceURI(), b.getNamespaceURI()); return result == 0 ? result : compareNullsFirst(a.getName(), b.getName()); } @@ -163,7 +182,7 @@ public class XsltXPathConformanceTestSuite { /** * Returns a JUnit test for the test described by the given element. */ - private Test create(File base, Element testCaseElement) { + private TestCase create(File base, Element testCaseElement) { /* * Extract the XSLT test from a DOM entity with the following structure: @@ -290,7 +309,6 @@ public class XsltXPathConformanceTestSuite { * the result to an expected output file. */ public class XsltTest extends TestCase { - // TODO: include these in toString private final String category; private final String id; private final String purpose; @@ -303,7 +321,10 @@ public class XsltXPathConformanceTestSuite { /** either "standard" or "execution-error" */ private final String operation; - /** the syntax to compare the output file using, such as "XML" or "HTML" */ + /** + * The syntax to compare the output file using, such as "XML", "HTML", + * "manual", or null for expected execution errors. + */ private final String compareAs; XsltTest(String category, String id, String purpose, String spec, @@ -321,6 +342,11 @@ public class XsltXPathConformanceTestSuite { this.compareAs = compareAs; } + XsltTest(File principalData, File principalStylesheet, File principal) { + this("standalone", "test", "", "", + principalData, principalStylesheet, principal, "standard", "XML"); + } + public void test() throws Exception { if (purpose != null) { System.out.println("Purpose: " + purpose); @@ -329,37 +355,50 @@ public class XsltXPathConformanceTestSuite { System.out.println("Spec: " + spec); } - Source xslt = new StreamSource(principalStylesheet); - Source in = new StreamSource(principalData); + Result result; + if ("XML".equals(compareAs)) { + DOMResult domResult = new DOMResult(); + domResult.setNode(documentBuilder.newDocument().createElementNS("", "result")); + result = domResult; + } else { + result = new StreamResult(new StringWriter()); + } + + ErrorRecorder errorRecorder = new ErrorRecorder(); + transformerFactory.setErrorListener(errorRecorder); Transformer transformer; try { + Source xslt = new StreamSource(principalStylesheet); transformer = transformerFactory.newTransformer(xslt); - assertEquals("Expected transformer creation to fail", - "standard", operation); + if (errorRecorder.error == null) { + transformer.setErrorListener(errorRecorder); + transformer.transform(new StreamSource(principalData), result); + } } catch (TransformerConfigurationException e) { - if (operation.equals("execution-error")) { - return; // expected, such as in XSLT-Result-Tree.Attributes__78369 + errorRecorder.fatalError(e); + } + + if (operation.equals("standard")) { + if (errorRecorder.error != null) { + throw errorRecorder.error; } - AssertionFailedError failure = new AssertionFailedError(); - failure.initCause(e); - throw failure; + } else if (operation.equals("execution-error")) { + if (errorRecorder.error != null) { + return; + } + fail("Expected " + operation + ", but transform completed normally." + + " (Warning=" + errorRecorder.warning + ")"); + } else { + throw new UnsupportedOperationException("Unexpected operation: " + operation); } - Result result; - if (compareAs.equals("XML")) { - result = new DOMResult(); + if ("XML".equals(compareAs)) { + assertNodesAreEquivalent(principal, ((DOMResult) result).getNode()); } else { // TODO: implement support for comparing HTML etc. throw new UnsupportedOperationException("Cannot compare as " + compareAs); } - - transformer.transform(in, result); - - if (compareAs.equals("XML")) { - DOMResult domResult = (DOMResult) result; - assertNodesAreEquivalent(principal, domResult.getNode()); - } } @Override public String getName() { @@ -370,19 +409,65 @@ public class XsltXPathConformanceTestSuite { /** * Ensures both XML documents represent the same semantic data. Non-semantic * data such as namespace prefixes, comments, and whitespace is ignored. + * + * @param actual an XML document whose root is a {@code <result>} element. + * @param expected a file containing an XML document fragment. */ private void assertNodesAreEquivalent(File expected, Node actual) throws ParserConfigurationException, IOException, SAXException, XmlPullParserException { - Document expectedDocument = documentBuilder.parse(new FileInputStream(expected)); - String expectedString = nodeToNormalizedString(expectedDocument); + Node expectedNode = fileToResultNode(expected); + String expectedString = nodeToNormalizedString(expectedNode); String actualString = nodeToNormalizedString(actual); Assert.assertEquals("Expected XML to match file " + expected, expectedString, actualString); } + /** + * Returns the given file's XML fragment as a single node, wrapped in + * {@code <result>} tags. This takes care of normalizing the following + * conditions: + * + * <ul> + * <li>Files containing XML document fragments with multiple elements: + * {@code <SPAN style="color=blue">Smurfs!</SPAN><br />} + * + * <li>Files containing XML document fragments with no elements: + * {@code Smurfs!} + * + * <li>Files containing proper XML documents with a single element and an + * XML declaration: + * {@code <?xml version="1.0"?><doc />} + * + * <li>Files prefixed with a byte order mark header, such as 0xEFBBBF. + * </ul> + */ + private Node fileToResultNode(File file) throws IOException, SAXException { + String rawContents = fileToString(file); + String fragment = rawContents; + + // If the file had an XML declaration, strip that. Otherwise wrapping + // it in <result> tags would result in a malformed XML document. + if (fragment.startsWith("<?xml")) { + int declarationEnd = fragment.indexOf("?>"); + fragment = fragment.substring(declarationEnd + 2); + } + + // Parse it as document fragment wrapped in <result> tags. + try { + fragment = "<result>" + fragment + "</result>"; + return documentBuilder.parse(new InputSource(new StringReader(fragment))) + .getDocumentElement(); + } catch (SAXParseException e) { + Error error = new AssertionFailedError( + "Failed to parse XML: " + file + "\n" + rawContents); + error.initCause(e); + throw error; + } + } + private String nodeToNormalizedString(Node node) throws XmlPullParserException, IOException { StringWriter writer = new StringWriter(); @@ -395,14 +480,18 @@ public class XsltXPathConformanceTestSuite { } private void emitNode(XmlSerializer serializer, Node node) throws IOException { - if (node instanceof Element) { + if (node == null) { + throw new UnsupportedOperationException("Cannot emit null nodes"); + + } else if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; - serializer.startTag(element.getBaseURI(), element.getLocalName()); + serializer.startTag(element.getNamespaceURI(), element.getLocalName()); emitAttributes(serializer, element); emitChildren(serializer, element); - serializer.endTag(element.getBaseURI(), element.getLocalName()); + serializer.endTag(element.getNamespaceURI(), element.getLocalName()); - } else if (node instanceof Text) { + } else if (node.getNodeType() == Node.TEXT_NODE + || node.getNodeType() == Node.CDATA_SECTION_NODE) { // TODO: is it okay to trim whitespace in general? This may cause // false positives for elements like HTML's <pre> tag String trimmed = node.getTextContent().trim(); @@ -410,25 +499,28 @@ public class XsltXPathConformanceTestSuite { serializer.text(trimmed); } - } else if (node instanceof Document) { + } else if (node.getNodeType() == Node.DOCUMENT_NODE) { Document document = (Document) node; serializer.startDocument("UTF-8", true); emitNode(serializer, document.getDocumentElement()); serializer.endDocument(); - } else if (node instanceof ProcessingInstruction) { + } else if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { ProcessingInstruction processingInstruction = (ProcessingInstruction) node; String data = processingInstruction.getData(); String target = processingInstruction.getTarget(); serializer.processingInstruction(target + " " + data); - } else if (node instanceof Comment) { + } else if (node.getNodeType() == Node.COMMENT_NODE) { // ignore! + } else if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) { + EntityReference entityReference = (EntityReference) node; + serializer.entityRef(entityReference.getNodeName()); + } else { - Object nodeClass = node != null ? node.getClass() : null; throw new UnsupportedOperationException( - "Cannot serialize nodes of type " + nodeClass); + "Cannot emit " + node + " of type " + node.getNodeType()); } } @@ -457,7 +549,7 @@ public class XsltXPathConformanceTestSuite { * generate one for us, using a predictable pattern. */ } else { - serializer.attribute(attr.getBaseURI(), attr.getLocalName(), attr.getValue()); + serializer.attribute(attr.getNamespaceURI(), attr.getLocalName(), attr.getValue()); } } } @@ -480,4 +572,64 @@ public class XsltXPathConformanceTestSuite { } return result; } + + /** + * Reads the given file into a string. If the file contains a byte order + * mark, the corresponding character set will be used. Otherwise the system + * default charset will be used. + */ + private String fileToString(File file) throws IOException { + InputStream in = new BufferedInputStream(new FileInputStream(file), 1024); + + // Read the byte order mark to determine the charset. + // TODO: use a built-in API for this... + Reader reader; + in.mark(3); + int byte1 = in.read(); + int byte2 = in.read(); + if (byte1 == 0xFF && byte2 == 0xFE) { + reader = new InputStreamReader(in, "UTF-16LE"); + } else if (byte1 == 0xFF && byte2 == 0xFF) { + reader = new InputStreamReader(in, "UTF-16BE"); + } else { + int byte3 = in.read(); + if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF) { + reader = new InputStreamReader(in, "UTF-8"); + } else { + in.reset(); + reader = new InputStreamReader(in); + } + } + + StringWriter out = new StringWriter(); + char[] buffer = new char[1024]; + int count; + while ((count = reader.read(buffer)) != -1) { + out.write(buffer, 0, count); + } + return out.toString(); + } + + static class ErrorRecorder implements ErrorListener { + Exception warning; + Exception error; + + public void warning(TransformerException exception) { + if (this.warning == null) { + this.warning = exception; + } + } + + public void error(TransformerException exception) { + if (this.error == null) { + this.error = exception; + } + } + + public void fatalError(TransformerException exception) { + if (this.error == null) { + this.error = exception; + } + } + } } diff --git a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java index 7318ad0..cfa62dc 100644 --- a/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java +++ b/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java @@ -34,6 +34,7 @@ import org.xml.sax.SAXParseException; import tests.api.org.xml.sax.support.MethodLogger; import tests.api.org.xml.sax.support.MockHandler; import tests.api.org.xml.sax.support.MockResolver; +import tests.support.resource.Support_Resources; import tests.util.TestEnvironment; import javax.xml.parsers.DocumentBuilder; @@ -41,8 +42,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -271,7 +270,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void testGetBaseURI() throws IOException, SAXException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); Document d = db.parse(f); assertTrue(d.getDocumentElement().getBaseURI().startsWith("file://")); } @@ -290,7 +289,7 @@ public class DocumentBuilderTest extends TestCase { args = {java.io.File.class} ) public void test_parseLjava_io_File() throws IOException { - File f = resourceToTmpFile("/simple.xml"); + File f = Support_Resources.resourceToTempFile("/simple.xml"); // case 1: Trivial use. try { @@ -332,7 +331,7 @@ public class DocumentBuilderTest extends TestCase { } // case 4: Try to parse incorrect xml file - f = resourceToTmpFile("/wrong.xml"); + f = Support_Resources.resourceToTempFile("/wrong.xml"); try { db.parse(f); fail("Expected SAXException was not thrown"); @@ -343,22 +342,6 @@ public class DocumentBuilderTest extends TestCase { } } - private File resourceToTmpFile(String path) throws IOException, - FileNotFoundException { - File f = File.createTempFile("out", ".xml"); - f.deleteOnExit(); - FileOutputStream out = new FileOutputStream(f); - - InputStream xml = getClass().getResourceAsStream(path); - while (xml.available() > 0) { - out.write(xml.read()); - } - out.flush(); - out.close(); - xml.close(); - return f; - } - /** * @tests javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream) * Case 1: Try to parse correct xml document. diff --git a/xml/src/test/java/tests/xml/AllTests.java b/xml/src/test/java/tests/xml/AllTests.java index 8a4b4a9..0042967 100644 --- a/xml/src/test/java/tests/xml/AllTests.java +++ b/xml/src/test/java/tests/xml/AllTests.java @@ -26,7 +26,7 @@ public class AllTests { suite.addTestSuite(SimpleParserTest.class); suite.addTestSuite(SimpleBuilderTest.class); - suite.addTestSuite(NodeTests.class); + suite.addTestSuite(NodeTest.class); //suite.addTest(tests.org.w3c.dom.AllTests.suite()); suite.addTest(tests.api.javax.xml.parsers.AllTests.suite()); diff --git a/xml/src/test/java/tests/xml/DomTest.java b/xml/src/test/java/tests/xml/DomTest.java new file mode 100644 index 0000000..5f0a19a --- /dev/null +++ b/xml/src/test/java/tests/xml/DomTest.java @@ -0,0 +1,623 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.xml; + +import junit.framework.TestCase; +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.Entity; +import org.w3c.dom.EntityReference; +import org.w3c.dom.Node; +import org.w3c.dom.Notation; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Construct a DOM and then interrogate it. + */ +public class DomTest extends TestCase { + + private Transformer transformer; + private DocumentBuilder builder; + private DOMImplementation domImplementation; + + private final String xml + = "<!DOCTYPE menu [" + + " <!ENTITY sp \"Maple Syrup\">" + + " <!NOTATION png SYSTEM \"image/png\">" + + "]>" + + "<menu>\n" + + " <item xmlns=\"http://food\" xmlns:a=\"http://addons\">\n" + + " <name a:standard=\"strawberry\" deluxe=\"&sp;\">Waffles</name>\n" + + " <description xmlns=\"http://marketing\">Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)</description>\n" + + " <a:option>Whipped Cream</a:option>\n" + + " <a:option>&sp;</a:option>\n" + + " <?wafflemaker square shape?>\n" + + " <nutrition>\n" + + " <a:vitamins xmlns:a=\"http://usda\">\n" + + " <!-- add other vitamins? --> \n" + + " <a:vitaminc>60%</a:vitaminc>\n" + + " </a:vitamins>\n" + + " </nutrition>\n" + + " </item>\n" + + "</menu>"; + + private Document document; + private DocumentType doctype; + private Entity sp; + private Notation png; + private Element menu; + private Element item; + private Attr itemXmlns; + private Attr itemXmlnsA; + private Element name; + private Attr standard; + private Attr deluxe; + private Element description; + private Text descriptionText1; + private CDATASection descriptionText2; + private Text descriptionText3; + private Element option1; + private Element option2; + private Node option2Reference; // resolved to Text on RI, an EntityReference on Dalvik + private ProcessingInstruction wafflemaker; + private Element nutrition; + private Element vitamins; + private Attr vitaminsXmlnsA; + private Comment comment; + private Element vitaminc; + private Text vitamincText; + private List<Node> allNodes; + + @Override protected void setUp() throws Exception { + transformer = TransformerFactory.newInstance().newTransformer(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + builder = factory.newDocumentBuilder(); + domImplementation = builder.getDOMImplementation(); + + document = builder.parse(new InputSource(new StringReader(xml))); + + // doctype nodes + doctype = document.getDoctype(); + if (doctype.getEntities() != null) { + sp = (Entity) doctype.getEntities().item(0); + } + if (doctype.getNotations() != null) { + png = (Notation) doctype.getNotations().item(0); + } + + // document nodes + menu = document.getDocumentElement(); + item = (Element) menu.getChildNodes().item(1); + itemXmlns = item.getAttributeNode("xmlns"); + itemXmlnsA = item.getAttributeNode("xmlns:a"); + name = (Element) item.getChildNodes().item(1); + standard = name.getAttributeNode("a:standard"); + deluxe = name.getAttributeNode("deluxe"); + description = (Element) item.getChildNodes().item(3); + descriptionText1 = (Text) description.getChildNodes().item(0); + descriptionText2 = (CDATASection) description.getChildNodes().item(1); + descriptionText3 = (Text) description.getChildNodes().item(2); + option1 = (Element) item.getChildNodes().item(5); + option2 = (Element) item.getChildNodes().item(7); + option2Reference = option2.getChildNodes().item(0); + wafflemaker = (ProcessingInstruction) item.getChildNodes().item(9); + nutrition = (Element) item.getChildNodes().item(11); + vitamins = (Element) nutrition.getChildNodes().item(1); + vitaminsXmlnsA = vitamins.getAttributeNode("xmlns:a"); + comment = (Comment) vitamins.getChildNodes().item(1); + vitaminc = (Element) vitamins.getChildNodes().item(3); + vitamincText = (Text) vitaminc.getChildNodes().item(0); + + allNodes = new ArrayList<Node>(); + + if (sp != null) { + allNodes.add(sp); + } + if (png != null) { + allNodes.add(png); + } + + allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns, + itemXmlnsA, name, standard, deluxe, description, + descriptionText1, descriptionText2, descriptionText3, option1, + option2, option2Reference, wafflemaker, nutrition, vitamins, + vitaminsXmlnsA, comment, vitaminc, vitamincText)); + } + + /** + * Android's parsed DOM doesn't include entity declarations. These nodes will + * only be tested for implementations that support them. + */ + public void testEntityDeclarations() { + assertNotNull("This implementation does not parse entity declarations", sp); + } + + /** + * Android's parsed DOM doesn't include notations. These nodes will only be + * tested for implementations that support them. + */ + public void testNotations() { + assertNotNull("This implementation does not parse notations", png); + } + + public void testLookupNamespaceURIByPrefix() { + assertEquals(null, doctype.lookupNamespaceURI("a")); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI("a")); + } + if (png != null) { + assertEquals(null, png.lookupNamespaceURI("a")); + } + assertEquals(null, document.lookupNamespaceURI("a")); + assertEquals(null, menu.lookupNamespaceURI("a")); + assertEquals("http://addons", item.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlns.lookupNamespaceURI("a")); + assertEquals("http://addons", itemXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://addons", name.lookupNamespaceURI("a")); + assertEquals("http://addons", standard.lookupNamespaceURI("a")); + assertEquals("http://addons", deluxe.lookupNamespaceURI("a")); + assertEquals("http://addons", description.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText1.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText2.lookupNamespaceURI("a")); + assertEquals("http://addons", descriptionText3.lookupNamespaceURI("a")); + assertEquals("http://addons", option1.lookupNamespaceURI("a")); + assertEquals("http://addons", option2.lookupNamespaceURI("a")); + assertEquals("http://addons", option2Reference.lookupNamespaceURI("a")); + assertEquals("http://addons", wafflemaker.lookupNamespaceURI("a")); + assertEquals("http://addons", nutrition.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamins.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminsXmlnsA.lookupNamespaceURI("a")); + assertEquals("http://usda", comment.lookupNamespaceURI("a")); + assertEquals("http://usda", vitaminc.lookupNamespaceURI("a")); + assertEquals("http://usda", vitamincText.lookupNamespaceURI("a")); + } + + public void testLookupNamespaceURIWithNullPrefix() { + assertEquals(null, document.lookupNamespaceURI(null)); + assertEquals(null, doctype.lookupNamespaceURI(null)); + if (sp != null) { + assertEquals(null, sp.lookupNamespaceURI(null)); + } + if (png != null) { + assertEquals(null, png.lookupNamespaceURI(null)); + } + assertEquals(null, menu.lookupNamespaceURI(null)); + assertEquals("http://food", item.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlns.lookupNamespaceURI(null)); + assertEquals("http://food", itemXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", name.lookupNamespaceURI(null)); + assertEquals("http://food", standard.lookupNamespaceURI(null)); + assertEquals("http://food", deluxe.lookupNamespaceURI(null)); + assertEquals("http://marketing", description.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText1.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText2.lookupNamespaceURI(null)); + assertEquals("http://marketing", descriptionText3.lookupNamespaceURI(null)); + assertEquals("http://food", option1.lookupNamespaceURI(null)); + assertEquals("http://food", option2.lookupNamespaceURI(null)); + assertEquals("http://food", option2Reference.lookupNamespaceURI(null)); + assertEquals("http://food", wafflemaker.lookupNamespaceURI(null)); + assertEquals("http://food", nutrition.lookupNamespaceURI(null)); + assertEquals("http://food", vitamins.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminsXmlnsA.lookupNamespaceURI(null)); + assertEquals("http://food", comment.lookupNamespaceURI(null)); + assertEquals("http://food", vitaminc.lookupNamespaceURI(null)); + assertEquals("http://food", vitamincText.lookupNamespaceURI(null)); + } + + public void testLookupNamespaceURIWithXmlnsPrefix() { + for (Node node : allNodes) { + assertEquals(null, node.lookupNamespaceURI("xmlns")); + } + } + + public void testLookupPrefixWithShadowedUri() { + assertEquals(null, document.lookupPrefix("http://addons")); + assertEquals(null, doctype.lookupPrefix("http://addons")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://addons")); + } + if (png != null) { + assertEquals(null, png.lookupPrefix("http://addons")); + } + assertEquals(null, menu.lookupPrefix("http://addons")); + assertEquals("a", item.lookupPrefix("http://addons")); + assertEquals("a", itemXmlns.lookupPrefix("http://addons")); + assertEquals("a", itemXmlnsA.lookupPrefix("http://addons")); + assertEquals("a", name.lookupPrefix("http://addons")); + assertEquals("a", standard.lookupPrefix("http://addons")); + assertEquals("a", deluxe.lookupPrefix("http://addons")); + assertEquals("a", description.lookupPrefix("http://addons")); + assertEquals("a", descriptionText1.lookupPrefix("http://addons")); + assertEquals("a", descriptionText2.lookupPrefix("http://addons")); + assertEquals("a", descriptionText3.lookupPrefix("http://addons")); + assertEquals("a", option1.lookupPrefix("http://addons")); + assertEquals("a", option2.lookupPrefix("http://addons")); + assertEquals("a", option2Reference.lookupPrefix("http://addons")); + assertEquals("a", wafflemaker.lookupPrefix("http://addons")); + assertEquals("a", nutrition.lookupPrefix("http://addons")); + assertEquals(null, vitamins.lookupPrefix("http://addons")); + assertEquals(null, vitaminsXmlnsA.lookupPrefix("http://addons")); + assertEquals(null, comment.lookupPrefix("http://addons")); + assertEquals(null, vitaminc.lookupPrefix("http://addons")); + assertEquals(null, vitamincText.lookupPrefix("http://addons")); + } + + public void testLookupPrefixWithUnusedUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix("http://unused")); + } + } + + public void testLookupPrefixWithNullUri() { + for (Node node : allNodes) { + assertEquals(null, node.lookupPrefix(null)); + } + } + + public void testLookupPrefixWithShadowingUri() { + assertEquals(null, document.lookupPrefix("http://usda")); + assertEquals(null, doctype.lookupPrefix("http://usda")); + if (sp != null) { + assertEquals(null, sp.lookupPrefix("http://usda")); + } + if (png != null) { + assertEquals(null, png.lookupPrefix("http://usda")); + } + assertEquals(null, menu.lookupPrefix("http://usda")); + assertEquals(null, item.lookupPrefix("http://usda")); + assertEquals(null, itemXmlns.lookupPrefix("http://usda")); + assertEquals(null, itemXmlnsA.lookupPrefix("http://usda")); + assertEquals(null, name.lookupPrefix("http://usda")); + assertEquals(null, standard.lookupPrefix("http://usda")); + assertEquals(null, deluxe.lookupPrefix("http://usda")); + assertEquals(null, description.lookupPrefix("http://usda")); + assertEquals(null, descriptionText1.lookupPrefix("http://usda")); + assertEquals(null, descriptionText2.lookupPrefix("http://usda")); + assertEquals(null, descriptionText3.lookupPrefix("http://usda")); + assertEquals(null, option1.lookupPrefix("http://usda")); + assertEquals(null, option2.lookupPrefix("http://usda")); + assertEquals(null, option2Reference.lookupPrefix("http://usda")); + assertEquals(null, wafflemaker.lookupPrefix("http://usda")); + assertEquals(null, nutrition.lookupPrefix("http://usda")); + assertEquals("a", vitamins.lookupPrefix("http://usda")); + assertEquals("a", vitaminsXmlnsA.lookupPrefix("http://usda")); + assertEquals("a", comment.lookupPrefix("http://usda")); + assertEquals("a", vitaminc.lookupPrefix("http://usda")); + assertEquals("a", vitamincText.lookupPrefix("http://usda")); + } + + public void testIsDefaultNamespace() { + assertFalse(document.isDefaultNamespace("http://food")); + assertFalse(doctype.isDefaultNamespace("http://food")); + if (sp != null) { + assertFalse(sp.isDefaultNamespace("http://food")); + } + if (png != null) { + assertFalse(png.isDefaultNamespace("http://food")); + } + assertFalse(menu.isDefaultNamespace("http://food")); + assertTrue(item.isDefaultNamespace("http://food")); + assertTrue(itemXmlns.isDefaultNamespace("http://food")); + assertTrue(itemXmlnsA.isDefaultNamespace("http://food")); + assertTrue(name.isDefaultNamespace("http://food")); + assertTrue(standard.isDefaultNamespace("http://food")); + assertTrue(deluxe.isDefaultNamespace("http://food")); + assertFalse(description.isDefaultNamespace("http://food")); + assertFalse(descriptionText1.isDefaultNamespace("http://food")); + assertFalse(descriptionText2.isDefaultNamespace("http://food")); + assertFalse(descriptionText3.isDefaultNamespace("http://food")); + assertTrue(option1.isDefaultNamespace("http://food")); + assertTrue(option2.isDefaultNamespace("http://food")); + assertTrue(option2Reference.isDefaultNamespace("http://food")); + assertTrue(wafflemaker.isDefaultNamespace("http://food")); + assertTrue(nutrition.isDefaultNamespace("http://food")); + assertTrue(vitamins.isDefaultNamespace("http://food")); + assertTrue(vitaminsXmlnsA.isDefaultNamespace("http://food")); + assertTrue(comment.isDefaultNamespace("http://food")); + assertTrue(vitaminc.isDefaultNamespace("http://food")); + assertTrue(vitamincText.isDefaultNamespace("http://food")); + } + + /** + * Xerces fails this test. It returns false always for entity, notation, + * document fragment and document type nodes. This contradicts its own + * behaviour on lookupNamespaceURI(null). + */ + public void testIsDefaultNamespaceNull_XercesBugs() { + String message = "isDefaultNamespace() should be consistent with lookupNamespaceURI(null)"; + assertTrue(message, doctype.isDefaultNamespace(null)); + if (sp != null) { + assertTrue(message, sp.isDefaultNamespace(null)); + } + if (png != null) { + assertTrue(message, png.isDefaultNamespace(null)); + } + } + + public void testIsDefaultNamespaceNull() { + assertTrue(document.isDefaultNamespace(null)); + assertTrue(menu.isDefaultNamespace(null)); + assertFalse(item.isDefaultNamespace(null)); + assertFalse(itemXmlns.isDefaultNamespace(null)); + assertFalse(itemXmlnsA.isDefaultNamespace(null)); + assertFalse(name.isDefaultNamespace(null)); + assertFalse(standard.isDefaultNamespace(null)); + assertFalse(deluxe.isDefaultNamespace(null)); + assertFalse(description.isDefaultNamespace(null)); + assertFalse(descriptionText1.isDefaultNamespace(null)); + assertFalse(descriptionText2.isDefaultNamespace(null)); + assertFalse(descriptionText3.isDefaultNamespace(null)); + assertFalse(option1.isDefaultNamespace(null)); + assertFalse(option2.isDefaultNamespace(null)); + assertFalse(option2Reference.isDefaultNamespace(null)); + assertFalse(wafflemaker.isDefaultNamespace(null)); + assertFalse(nutrition.isDefaultNamespace(null)); + assertFalse(vitamins.isDefaultNamespace(null)); + assertFalse(vitaminsXmlnsA.isDefaultNamespace(null)); + assertFalse(comment.isDefaultNamespace(null)); + assertFalse(vitaminc.isDefaultNamespace(null)); + assertFalse(vitamincText.isDefaultNamespace(null)); + } + + public void testDoctypeSetTextContent() throws TransformerException { + String original = domToString(document); + doctype.setTextContent("foobar"); // strangely, this is specified to no-op + assertEquals(original, domToString(document)); + } + + public void testDocumentSetTextContent() throws TransformerException { + String original = domToString(document); + document.setTextContent("foobar"); // strangely, this is specified to no-op + assertEquals(original, domToString(document)); + } + + public void testElementSetTextContent() throws TransformerException { + String original = domToString(document); + nutrition.setTextContent("foobar"); + String expected = original.replaceFirst( + "(?s)<nutrition>.*</nutrition>", "<nutrition>foobar</nutrition>"); + assertEquals(expected, domToString(document)); + } + + public void testEntitySetTextContent() throws TransformerException { + if (sp == null) { + return; + } + try { + sp.setTextContent("foobar"); + fail(); // is this implementation-specific behaviour? + } catch (DOMException e) { + } + } + + public void testNotationSetTextContent() throws TransformerException { + if (png == null) { + return; + } + String original = domToString(document); + png.setTextContent("foobar"); + String expected = original.replace("image/png", "foobar"); + assertEquals(expected, domToString(document)); + } + + /** + * Tests setTextContent on entity references. Although the other tests can + * act on a parsed DOM, this needs to use a programmatically constructed DOM + * because the parser may have replaced the entity reference with the + * corresponding text. + */ + public void testEntityReferenceSetTextContent() throws TransformerException { + document = builder.newDocument(); + Element root = document.createElement("menu"); + document.appendChild(root); + + EntityReference entityReference = document.createEntityReference("sp"); + entityReference.setNodeValue("Maple Syrup"); + root.appendChild(entityReference); + + try { + entityReference.setTextContent("Lite Syrup"); + fail(); + } catch (DOMException e) { + } + } + + public void testAttributeSetTextContent() throws TransformerException { + String original = domToString(document); + standard.setTextContent("foobar"); + String expected = original.replaceFirst( + "standard=\"strawberry\"", "standard=\"foobar\""); + assertEquals(expected, domToString(document)); + } + + public void testTextSetTextContent() throws TransformerException { + String original = domToString(document); + descriptionText1.setTextContent("foobar"); + String expected = original.replace(">Belgian<!", ">foobar<!"); + assertEquals(expected, domToString(document)); + } + + public void testCdataSetTextContent() throws TransformerException { + String original = domToString(document); + descriptionText2.setTextContent("foobar"); + String expected = original.replace( + " waffles & strawberries (< 5g ", "foobar"); + assertEquals(expected, domToString(document)); + } + + public void testProcessingInstructionSetTextContent() throws TransformerException { + String original = domToString(document); + wafflemaker.setTextContent("foobar"); + String expected = original.replace(" square shape?>", " foobar?>"); + assertEquals(expected, domToString(document)); + } + + public void testCommentSetTextContent() throws TransformerException { + String original = domToString(document); + comment.setTextContent("foobar"); + String expected = original.replace("-- add other vitamins? --", "--foobar--"); + assertEquals(expected, domToString(document)); + } + + public void testCoreFeature() { + assertTrue(domImplementation.hasFeature("Core", null)); + assertTrue(domImplementation.hasFeature("Core", "")); + assertTrue(domImplementation.hasFeature("Core", "1.0")); + assertTrue(domImplementation.hasFeature("Core", "2.0")); + assertTrue(domImplementation.hasFeature("Core", "3.0")); + assertTrue(domImplementation.hasFeature("CORE", "3.0")); + assertTrue(domImplementation.hasFeature("+Core", "3.0")); + assertFalse(domImplementation.hasFeature("Core", "4.0")); + } + + public void testXmlFeature() { + assertTrue(domImplementation.hasFeature("XML", null)); + assertTrue(domImplementation.hasFeature("XML", "")); + assertTrue(domImplementation.hasFeature("XML", "1.0")); + assertTrue(domImplementation.hasFeature("XML", "2.0")); + assertTrue(domImplementation.hasFeature("XML", "3.0")); + assertTrue(domImplementation.hasFeature("Xml", "3.0")); + assertTrue(domImplementation.hasFeature("+XML", "3.0")); + assertFalse(domImplementation.hasFeature("XML", "4.0")); + } + + /** + * The RI fails this test. + * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-version + */ + public void testXmlVersionFeature() { + String message = "This implementation does not support the XMLVersion feature"; + assertTrue(message, domImplementation.hasFeature("XMLVersion", null)); + assertTrue(message, domImplementation.hasFeature("XMLVersion", "")); + assertTrue(message, domImplementation.hasFeature("XMLVersion", "1.0")); + assertTrue(message, domImplementation.hasFeature("XMLVersion", "1.1")); + assertTrue(message, domImplementation.hasFeature("XMLVERSION", "1.1")); + assertTrue(message, domImplementation.hasFeature("+XMLVersion", "1.1")); + assertFalse(domImplementation.hasFeature("XMLVersion", "1.2")); + assertFalse(domImplementation.hasFeature("XMLVersion", "2.0")); + assertFalse(domImplementation.hasFeature("XMLVersion", "2.0")); + } + + public void testLsFeature() { + assertTrue("This implementation does not support the LS feature", + domImplementation.hasFeature("LS", "3.0")); + } + + public void testElementTraversalFeature() { + assertTrue("This implementation does not support the ElementTraversal feature", + domImplementation.hasFeature("ElementTraversal", "1.0")); + } + + public void testIsSupported() { + // we don't independently test the features; instead just assume the + // implementation calls through to hasFeature (as tested above) + for (Node node : allNodes) { + assertTrue(node.isSupported("XML", null)); + assertTrue(node.isSupported("XML", "3.0")); + assertFalse(node.isSupported("foo", null)); + assertFalse(node.isSupported("foo", "bar")); + } + } + + public void testGetFeature() { + // we don't independently test the features; instead just assume the + // implementation calls through to hasFeature (as tested above) + for (Node node : allNodes) { + assertSame(node, node.getFeature("XML", null)); + assertSame(node, node.getFeature("XML", "3.0")); + assertNull(node.getFeature("foo", null)); + assertNull(node.getFeature("foo", "bar")); + } + } + + public void testNodeEqualsPositive() throws Exception { + DomTest copy = new DomTest(); + copy.setUp(); + + for (int i = 0; i < allNodes.size(); i++) { + Node a = allNodes.get(i); + Node b = copy.allNodes.get(i); + assertTrue(a.isEqualNode(b)); + } + } + + public void testNodeEqualsNegative() throws Exception { + for (Node a : allNodes) { + for (Node b : allNodes) { + assertEquals(a == b, a.isEqualNode(b)); + } + } + } + + public void testNodeEqualsNegativeRecursive() throws Exception { + DomTest copy = new DomTest(); + copy.setUp(); + copy.vitaminc.setTextContent("55%"); + + // changing anything about a node should break equality for all parents + assertFalse(document.isEqualNode(copy.document)); + assertFalse(menu.isEqualNode(copy.menu)); + assertFalse(item.isEqualNode(copy.item)); + assertFalse(nutrition.isEqualNode(copy.nutrition)); + assertFalse(vitamins.isEqualNode(copy.vitamins)); + assertFalse(vitaminc.isEqualNode(copy.vitaminc)); + + // but not siblings + assertTrue(doctype.isEqualNode(copy.doctype)); + assertTrue(description.isEqualNode(copy.description)); + assertTrue(option1.isEqualNode(copy.option1)); + } + + public void testNodeEqualsNull() { + for (Node node : allNodes) { + try { + node.isEqualNode(null); + fail(); + } catch (NullPointerException e) { + } + } + } + + private String domToString(Document document) + throws TransformerException { + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(document), new StreamResult(writer)); + return writer.toString(); + } +} diff --git a/xml/src/test/java/tests/xml/NodeTest.java b/xml/src/test/java/tests/xml/NodeTest.java new file mode 100644 index 0000000..dc3a333 --- /dev/null +++ b/xml/src/test/java/tests/xml/NodeTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.xml; + +import dalvik.annotation.TestTargetClass; +import junit.framework.TestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import tests.support.resource.Support_Resources; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@TestTargetClass(Node.class) +public class NodeTest extends TestCase { + + /** + * For bug 779: Node#getNextSibling throws IndexOutOfBoundsException. + */ + public void test_getNextSibling() throws Exception { + // Calling getNextSibling when there is no next sibling should return null. + // From http://code.google.com/p/android/issues/detail?id=779. + ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes()); + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); + Node root = document.getDocumentElement(); + assertNull(root.getNextSibling()); + } + + public void testGetBaseUri() throws Exception { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + File file = Support_Resources.resourceToTempFile("/simple.xml"); + Document document = builder.parse(file); + + String baseUri = "file:" + file.getPath(); + assertEquals(baseUri, document.getBaseURI()); + + Element documentElement = document.getDocumentElement(); + for (Node node : flattenSubtree(documentElement)) { + if (node.getNodeType() == Node.ELEMENT_NODE + || node.getNodeType() == Node.DOCUMENT_NODE) { + assertEquals("Unexpected base URI for " + node, baseUri, node.getBaseURI()); + } else { + assertNull("Unexpected base URI for " + node, node.getBaseURI()); + } + } + + // TODO: test other node types + // TODO: test resolution of relative paths + // TODO: test URI santization + } + + private List<Node> flattenSubtree(Node subtree) { + List<Node> result = new ArrayList<Node>(); + traverse(subtree, result); + return result; + } + + private void traverse(Node node, List<Node> sink) { + sink.add(node); + + NodeList children = node.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + traverse(children.item(i), sink); + } + } +} diff --git a/xml/src/test/java/tests/xml/NodeTests.java b/xml/src/test/java/tests/xml/NodeTests.java deleted file mode 100644 index e46e216..0000000 --- a/xml/src/test/java/tests/xml/NodeTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package tests.xml; - -import dalvik.annotation.TestLevel; -import dalvik.annotation.TestTargetNew; -import dalvik.annotation.TestTargetClass; - -import junit.framework.TestCase; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.ByteArrayInputStream; -import javax.xml.parsers.DocumentBuilderFactory; - -@TestTargetClass(Node.class) -public class NodeTests extends TestCase { - @TestTargetNew( - level = TestLevel.PARTIAL, - notes = "Issue #779: org.w3c.dom.Node#getNextSibling throws IndexOutOfBoundsException.", - method = "getNextSibling", - args = {} - ) - public void test_getNextSibling() throws Exception { - // Calling getNextSibling when there is no next sibling should return null. - // From http://code.google.com/p/android/issues/detail?id=779. - ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes()); - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis); - Node root = document.getDocumentElement(); - assertNull(root.getNextSibling()); - } -} |