DomTest.java revision 302f069f38e7890594816ceab517c15bcd59a9b7
11ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson/*
21ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Copyright (C) 2010 The Android Open Source Project
31ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
41ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
51ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * you may not use this file except in compliance with the License.
61ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * You may obtain a copy of the License at
71ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
81ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
91ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson *
101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Unless required by applicable law or agreed to in writing, software
111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * See the License for the specific language governing permissions and
141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * limitations under the License.
151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */
161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonpackage tests.xml;
181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
19df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport junit.framework.AssertionFailedError;
201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport junit.framework.TestCase;
211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Attr;
221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.CDATASection;
231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Comment;
24ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.DOMException;
2535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilsonimport org.w3c.dom.DOMImplementation;
261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Document;
271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.DocumentType;
281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Element;
291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Entity;
30ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.EntityReference;
31df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport org.w3c.dom.NamedNodeMap;
321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Node;
33df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport org.w3c.dom.NodeList;
34ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport org.w3c.dom.Notation;
351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.ProcessingInstruction;
361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.w3c.dom.Text;
378b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport org.w3c.dom.UserDataHandler;
381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport org.xml.sax.InputSource;
391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
40ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.parsers.DocumentBuilder;
411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport javax.xml.parsers.DocumentBuilderFactory;
42df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport javax.xml.transform.OutputKeys;
43ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.transform.Transformer;
44ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.transform.TransformerException;
45ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.transform.TransformerFactory;
46ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.transform.dom.DOMSource;
47ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport javax.xml.transform.stream.StreamResult;
48302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilsonimport java.io.File;
49302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilsonimport java.io.FileWriter;
501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport java.io.StringReader;
51ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilsonimport java.io.StringWriter;
521ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport java.util.ArrayList;
531ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport java.util.Arrays;
548b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport java.util.HashSet;
551ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonimport java.util.List;
568b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport java.util.Set;
57df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport java.util.regex.Matcher;
58df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport java.util.regex.Pattern;
598b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
60df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_ADOPTED;
618b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_CLONED;
62df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilsonimport static org.w3c.dom.UserDataHandler.NODE_IMPORTED;
631ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
641ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson/**
651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson * Construct a DOM and then interrogate it.
661ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson */
671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilsonpublic class DomTest extends TestCase {
681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
69ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Transformer transformer;
70ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private DocumentBuilder builder;
7135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    private DOMImplementation domImplementation;
72ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
731ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private final String xml
741ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            = "<!DOCTYPE menu ["
751ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  <!ENTITY sp \"Maple Syrup\">"
76ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            + "  <!NOTATION png SYSTEM \"image/png\">"
771ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "]>"
781ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "<menu>\n"
791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  <item xmlns=\"http://food\" xmlns:a=\"http://addons\">\n"
801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <name a:standard=\"strawberry\" deluxe=\"&sp;\">Waffles</name>\n"
811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <description xmlns=\"http://marketing\">Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)</description>\n"
821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <a:option>Whipped Cream</a:option>\n"
831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <a:option>&sp;</a:option>\n"
841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <?wafflemaker square shape?>\n"
851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    <nutrition>\n"
861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "      <a:vitamins xmlns:a=\"http://usda\">\n"
871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "        <!-- add other vitamins? --> \n"
881ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "        <a:vitaminc>60%</a:vitaminc>\n"
891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "      </a:vitamins>\n"
901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "    </nutrition>\n"
911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "  </item>\n"
921ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            + "</menu>";
931ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
941ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Document document;
951ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private DocumentType doctype;
961ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Entity sp;
97ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Notation png;
981ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element menu;
991ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element item;
1001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr itemXmlns;
1011ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr itemXmlnsA;
1021ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element name;
1031ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr standard;
1041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr deluxe;
1058b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private Text waffles;
1061ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element description;
1071ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text descriptionText1;
1081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private CDATASection descriptionText2;
1091ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text descriptionText3;
1101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element option1;
1111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element option2;
112ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    private Node option2Reference; // resolved to Text on RI, an EntityReference on Dalvik
1131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private ProcessingInstruction wafflemaker;
1141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element nutrition;
1151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element vitamins;
1161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Attr vitaminsXmlnsA;
1171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Comment comment;
1181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Element vitaminc;
1191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private Text vitamincText;
1201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    private List<Node> allNodes;
1211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    @Override protected void setUp() throws Exception {
123ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        transformer = TransformerFactory.newInstance().newTransformer();
124df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
1251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
1261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        factory.setNamespaceAware(true);
127ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        builder = factory.newDocumentBuilder();
12835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        domImplementation = builder.getDOMImplementation();
129ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document = builder.parse(new InputSource(new StringReader(xml)));
1301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        // doctype nodes
1321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        doctype = document.getDoctype();
1331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (doctype.getEntities() != null) {
1341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            sp = (Entity) doctype.getEntities().item(0);
1351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
136ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (doctype.getNotations() != null) {
137ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            png = (Notation) doctype.getNotations().item(0);
138ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
1391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1401ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        // document nodes
1411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        menu = document.getDocumentElement();
1421ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        item = (Element) menu.getChildNodes().item(1);
1431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        itemXmlns = item.getAttributeNode("xmlns");
1441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        itemXmlnsA = item.getAttributeNode("xmlns:a");
1451ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        name = (Element) item.getChildNodes().item(1);
1461ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        standard = name.getAttributeNode("a:standard");
1471ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        deluxe = name.getAttributeNode("deluxe");
1488b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles = (Text) name.getChildNodes().item(0);
1491ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        description = (Element) item.getChildNodes().item(3);
1501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText1 = (Text) description.getChildNodes().item(0);
1511ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText2 = (CDATASection) description.getChildNodes().item(1);
1521ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        descriptionText3 = (Text) description.getChildNodes().item(2);
1531ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option1 = (Element) item.getChildNodes().item(5);
1541ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option2 = (Element) item.getChildNodes().item(7);
1551ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        option2Reference = option2.getChildNodes().item(0);
1561ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        wafflemaker = (ProcessingInstruction) item.getChildNodes().item(9);
1571ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        nutrition = (Element) item.getChildNodes().item(11);
1581ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitamins = (Element) nutrition.getChildNodes().item(1);
1591ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitaminsXmlnsA = vitamins.getAttributeNode("xmlns:a");
1601ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        comment = (Comment) vitamins.getChildNodes().item(1);
1611ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitaminc = (Element) vitamins.getChildNodes().item(3);
1621ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        vitamincText = (Text) vitaminc.getChildNodes().item(0);
1631ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1641ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        allNodes = new ArrayList<Node>();
1651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1661ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
1671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            allNodes.add(sp);
1681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
169ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
170ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            allNodes.add(png);
171ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
1721ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1731ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        allNodes.addAll(Arrays.asList(document, doctype, menu, item, itemXmlns,
1748b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson                itemXmlnsA, name, standard, deluxe, waffles, description,
1751ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                descriptionText1, descriptionText2, descriptionText3, option1,
1761ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                option2, option2Reference, wafflemaker, nutrition, vitamins,
1771ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson                vitaminsXmlnsA, comment, vitaminc, vitamincText));
1781ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
1791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
1801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    /**
1811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     * Android's parsed DOM doesn't include entity declarations. These nodes will
1821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     * only be tested for implementations that support them.
1831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson     */
1841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testEntityDeclarations() {
1851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertNotNull("This implementation does not parse entity declarations", sp);
1861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
1871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
188ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    /**
189ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * Android's parsed DOM doesn't include notations. These nodes will only be
190ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * tested for implementations that support them.
191ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     */
192ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testNotations() {
193ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertNotNull("This implementation does not parse notations", png);
194ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
195ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
1961ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIByPrefix() {
1971ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupNamespaceURI("a"));
1981ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
1991ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupNamespaceURI("a"));
2001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
201ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
202ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupNamespaceURI("a"));
203ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupNamespaceURI("a"));
2051ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupNamespaceURI("a"));
2061ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", item.lookupNamespaceURI("a"));
2071ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", itemXmlns.lookupNamespaceURI("a"));
2081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", itemXmlnsA.lookupNamespaceURI("a"));
2091ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", name.lookupNamespaceURI("a"));
2101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", standard.lookupNamespaceURI("a"));
2111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", deluxe.lookupNamespaceURI("a"));
2121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", description.lookupNamespaceURI("a"));
2131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText1.lookupNamespaceURI("a"));
2141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText2.lookupNamespaceURI("a"));
2151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", descriptionText3.lookupNamespaceURI("a"));
2161ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option1.lookupNamespaceURI("a"));
2171ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option2.lookupNamespaceURI("a"));
2181ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", option2Reference.lookupNamespaceURI("a"));
2191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", wafflemaker.lookupNamespaceURI("a"));
2201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://addons", nutrition.lookupNamespaceURI("a"));
2211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitamins.lookupNamespaceURI("a"));
2221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitaminsXmlnsA.lookupNamespaceURI("a"));
2231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", comment.lookupNamespaceURI("a"));
2241ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitaminc.lookupNamespaceURI("a"));
2251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://usda", vitamincText.lookupNamespaceURI("a"));
2261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIWithNullPrefix() {
2291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupNamespaceURI(null));
2301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupNamespaceURI(null));
2311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
2321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupNamespaceURI(null));
2331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
234ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
235ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupNamespaceURI(null));
236ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupNamespaceURI(null));
2381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", item.lookupNamespaceURI(null));
2391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", itemXmlns.lookupNamespaceURI(null));
2401ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", itemXmlnsA.lookupNamespaceURI(null));
2411ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", name.lookupNamespaceURI(null));
2421ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", standard.lookupNamespaceURI(null));
2431ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", deluxe.lookupNamespaceURI(null));
2441ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", description.lookupNamespaceURI(null));
2451ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText1.lookupNamespaceURI(null));
2461ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText2.lookupNamespaceURI(null));
2471ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://marketing", descriptionText3.lookupNamespaceURI(null));
2481ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option1.lookupNamespaceURI(null));
2491ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option2.lookupNamespaceURI(null));
2501ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", option2Reference.lookupNamespaceURI(null));
2511ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", wafflemaker.lookupNamespaceURI(null));
2521ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", nutrition.lookupNamespaceURI(null));
2531ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitamins.lookupNamespaceURI(null));
2541ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitaminsXmlnsA.lookupNamespaceURI(null));
2551ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", comment.lookupNamespaceURI(null));
2561ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitaminc.lookupNamespaceURI(null));
2571ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("http://food", vitamincText.lookupNamespaceURI(null));
2581ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2591ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2601ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupNamespaceURIWithXmlnsPrefix() {
2611ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
2621ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupNamespaceURI("xmlns"));
2631ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
2641ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2651ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2661ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithShadowedUri() {
2671ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupPrefix("http://addons"));
2681ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupPrefix("http://addons"));
2691ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
2701ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupPrefix("http://addons"));
2711ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
272ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
273ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupPrefix("http://addons"));
274ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
2751ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupPrefix("http://addons"));
2761ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", item.lookupPrefix("http://addons"));
2771ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", itemXmlns.lookupPrefix("http://addons"));
2781ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", itemXmlnsA.lookupPrefix("http://addons"));
2791ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", name.lookupPrefix("http://addons"));
2801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", standard.lookupPrefix("http://addons"));
2811ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", deluxe.lookupPrefix("http://addons"));
2821ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", description.lookupPrefix("http://addons"));
2831ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText1.lookupPrefix("http://addons"));
2841ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText2.lookupPrefix("http://addons"));
2851ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", descriptionText3.lookupPrefix("http://addons"));
2861ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option1.lookupPrefix("http://addons"));
2871ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option2.lookupPrefix("http://addons"));
2881ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", option2Reference.lookupPrefix("http://addons"));
2891ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", wafflemaker.lookupPrefix("http://addons"));
2901ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", nutrition.lookupPrefix("http://addons"));
2911ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitamins.lookupPrefix("http://addons"));
2921ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitaminsXmlnsA.lookupPrefix("http://addons"));
2931ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, comment.lookupPrefix("http://addons"));
2941ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitaminc.lookupPrefix("http://addons"));
2951ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, vitamincText.lookupPrefix("http://addons"));
2961ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
2971ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
2981ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithUnusedUri() {
2991ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
3001ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupPrefix("http://unused"));
3011ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
3021ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
3031ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
3041ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithNullUri() {
3051ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        for (Node node : allNodes) {
3061ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, node.lookupPrefix(null));
3071ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
3081ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
3091ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson
3101ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    public void testLookupPrefixWithShadowingUri() {
3111ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, document.lookupPrefix("http://usda"));
3121ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, doctype.lookupPrefix("http://usda"));
3131ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        if (sp != null) {
3141ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson            assertEquals(null, sp.lookupPrefix("http://usda"));
3151ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        }
316ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png != null) {
317ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            assertEquals(null, png.lookupPrefix("http://usda"));
318ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
3191ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, menu.lookupPrefix("http://usda"));
3201ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, item.lookupPrefix("http://usda"));
3211ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, itemXmlns.lookupPrefix("http://usda"));
3221ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, itemXmlnsA.lookupPrefix("http://usda"));
3231ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, name.lookupPrefix("http://usda"));
3241ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, standard.lookupPrefix("http://usda"));
3251ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, deluxe.lookupPrefix("http://usda"));
3261ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, description.lookupPrefix("http://usda"));
3271ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText1.lookupPrefix("http://usda"));
3281ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText2.lookupPrefix("http://usda"));
3291ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, descriptionText3.lookupPrefix("http://usda"));
3301ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option1.lookupPrefix("http://usda"));
3311ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option2.lookupPrefix("http://usda"));
3321ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, option2Reference.lookupPrefix("http://usda"));
3331ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, wafflemaker.lookupPrefix("http://usda"));
3341ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals(null, nutrition.lookupPrefix("http://usda"));
3351ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitamins.lookupPrefix("http://usda"));
3361ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitaminsXmlnsA.lookupPrefix("http://usda"));
3371ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", comment.lookupPrefix("http://usda"));
3381ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitaminc.lookupPrefix("http://usda"));
3391ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson        assertEquals("a", vitamincText.lookupPrefix("http://usda"));
3401ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson    }
341ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
34235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespace() {
34335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(document.isDefaultNamespace("http://food"));
34435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(doctype.isDefaultNamespace("http://food"));
34535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (sp != null) {
34635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(sp.isDefaultNamespace("http://food"));
34735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
34835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (png != null) {
34935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(png.isDefaultNamespace("http://food"));
35035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
35135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(menu.isDefaultNamespace("http://food"));
35235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(item.isDefaultNamespace("http://food"));
35335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(itemXmlns.isDefaultNamespace("http://food"));
35435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(itemXmlnsA.isDefaultNamespace("http://food"));
35535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(name.isDefaultNamespace("http://food"));
35635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(standard.isDefaultNamespace("http://food"));
35735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(deluxe.isDefaultNamespace("http://food"));
35835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(description.isDefaultNamespace("http://food"));
35935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText1.isDefaultNamespace("http://food"));
36035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText2.isDefaultNamespace("http://food"));
36135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText3.isDefaultNamespace("http://food"));
36235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option1.isDefaultNamespace("http://food"));
36335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option2.isDefaultNamespace("http://food"));
36435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option2Reference.isDefaultNamespace("http://food"));
36535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(wafflemaker.isDefaultNamespace("http://food"));
36635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(nutrition.isDefaultNamespace("http://food"));
36735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitamins.isDefaultNamespace("http://food"));
36835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitaminsXmlnsA.isDefaultNamespace("http://food"));
36935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(comment.isDefaultNamespace("http://food"));
37035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitaminc.isDefaultNamespace("http://food"));
37135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(vitamincText.isDefaultNamespace("http://food"));
37235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
37335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
37435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    /**
37535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * Xerces fails this test. It returns false always for entity, notation,
37635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * document fragment and document type nodes. This contradicts its own
37735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * behaviour on lookupNamespaceURI(null).
37835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     */
37935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespaceNull_XercesBugs() {
38035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        String message = "isDefaultNamespace() should be consistent with lookupNamespaceURI(null)";
38135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, doctype.isDefaultNamespace(null));
38235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (sp != null) {
38335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(message, sp.isDefaultNamespace(null));
38435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
38535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        if (png != null) {
38635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(message, png.isDefaultNamespace(null));
38735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
38835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
38935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
39035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsDefaultNamespaceNull() {
39135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(document.isDefaultNamespace(null));
39235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(menu.isDefaultNamespace(null));
39335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(item.isDefaultNamespace(null));
39435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(itemXmlns.isDefaultNamespace(null));
39535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(itemXmlnsA.isDefaultNamespace(null));
39635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(name.isDefaultNamespace(null));
39735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(standard.isDefaultNamespace(null));
39835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(deluxe.isDefaultNamespace(null));
39935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(description.isDefaultNamespace(null));
40035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText1.isDefaultNamespace(null));
40135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText2.isDefaultNamespace(null));
40235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(descriptionText3.isDefaultNamespace(null));
40335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option1.isDefaultNamespace(null));
40435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option2.isDefaultNamespace(null));
40535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(option2Reference.isDefaultNamespace(null));
40635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(wafflemaker.isDefaultNamespace(null));
40735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(nutrition.isDefaultNamespace(null));
40835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamins.isDefaultNamespace(null));
40935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminsXmlnsA.isDefaultNamespace(null));
41035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(comment.isDefaultNamespace(null));
41135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminc.isDefaultNamespace(null));
41235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamincText.isDefaultNamespace(null));
41335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
41435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
415ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testDoctypeSetTextContent() throws TransformerException {
416ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
417ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        doctype.setTextContent("foobar"); // strangely, this is specified to no-op
418ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(original, domToString(document));
419ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
420ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
421ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testDocumentSetTextContent() throws TransformerException {
422ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
423ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document.setTextContent("foobar"); // strangely, this is specified to no-op
424ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(original, domToString(document));
425ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
426ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
427ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testElementSetTextContent() throws TransformerException {
428ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
429ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        nutrition.setTextContent("foobar");
430ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replaceFirst(
431ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson                "(?s)<nutrition>.*</nutrition>", "<nutrition>foobar</nutrition>");
432ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
433ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
434ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
435ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testEntitySetTextContent() throws TransformerException {
436ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (sp == null) {
437ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            return;
438ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
439ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        try {
440ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            sp.setTextContent("foobar");
441ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            fail(); // is this implementation-specific behaviour?
442ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        } catch (DOMException e) {
443ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
444ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
445ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
446ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testNotationSetTextContent() throws TransformerException {
447ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        if (png == null) {
448ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            return;
449ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
450ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
451ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        png.setTextContent("foobar");
452ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace("image/png", "foobar");
453ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
454ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
455ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
456ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    /**
457ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * Tests setTextContent on entity references. Although the other tests can
458ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * act on a parsed DOM, this needs to use a programmatically constructed DOM
459ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * because the parser may have replaced the entity reference with the
460ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     * corresponding text.
461ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson     */
462ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testEntityReferenceSetTextContent() throws TransformerException {
463ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document = builder.newDocument();
464ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        Element root = document.createElement("menu");
465ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        document.appendChild(root);
466ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
467ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        EntityReference entityReference = document.createEntityReference("sp");
468ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        root.appendChild(entityReference);
469ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
470ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        try {
471ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            entityReference.setTextContent("Lite Syrup");
472ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson            fail();
473ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        } catch (DOMException e) {
474ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        }
475ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
476ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
477ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testAttributeSetTextContent() throws TransformerException {
478ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
479ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        standard.setTextContent("foobar");
480bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace("standard=\"strawberry\"", "standard=\"foobar\"");
481ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
482ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
483ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
484ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testTextSetTextContent() throws TransformerException {
485ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
486ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        descriptionText1.setTextContent("foobar");
487ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(">Belgian<!", ">foobar<!");
488ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
489ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
490ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
491ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testCdataSetTextContent() throws TransformerException {
492ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
493ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        descriptionText2.setTextContent("foobar");
494ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(
495ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson                " waffles & strawberries (< 5g ", "foobar");
496ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
497ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
498ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
499ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testProcessingInstructionSetTextContent() throws TransformerException {
500ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
501ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        wafflemaker.setTextContent("foobar");
502ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace(" square shape?>", " foobar?>");
503ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
504ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
505ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
506ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    public void testCommentSetTextContent() throws TransformerException {
507ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String original = domToString(document);
508ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        comment.setTextContent("foobar");
509ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        String expected = original.replace("-- add other vitamins? --", "--foobar--");
510ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        assertEquals(expected, domToString(document));
511ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
512ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson
51335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testCoreFeature() {
51435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Core", null));
51535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Core", ""));
51635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Core", "1.0"));
51735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Core", "2.0"));
51835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Core", "3.0"));
51935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("CORE", "3.0"));
52035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("+Core", "3.0"));
52135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(domImplementation.hasFeature("Core", "4.0"));
52235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
52335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
52435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testXmlFeature() {
52535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("XML", null));
52635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("XML", ""));
52735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("XML", "1.0"));
52835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("XML", "2.0"));
52935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("XML", "3.0"));
53035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("Xml", "3.0"));
53135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(domImplementation.hasFeature("+XML", "3.0"));
53235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(domImplementation.hasFeature("XML", "4.0"));
53335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
53435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
53535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    /**
53635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * The RI fails this test.
53735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-version
53835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson     */
53935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testXmlVersionFeature() {
54035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        String message = "This implementation does not support the XMLVersion feature";
54135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("XMLVersion", null));
54235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("XMLVersion", ""));
54335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("XMLVersion", "1.0"));
54435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("XMLVersion", "1.1"));
54535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("XMLVERSION", "1.1"));
54635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(message, domImplementation.hasFeature("+XMLVersion", "1.1"));
54735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(domImplementation.hasFeature("XMLVersion", "1.2"));
54835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(domImplementation.hasFeature("XMLVersion", "2.0"));
54935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(domImplementation.hasFeature("XMLVersion", "2.0"));
55035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
55135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
55235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testLsFeature() {
55335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue("This implementation does not support the LS feature",
55435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                domImplementation.hasFeature("LS", "3.0"));
55535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
55635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
55735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testElementTraversalFeature() {
55835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue("This implementation does not support the ElementTraversal feature",
55935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                domImplementation.hasFeature("ElementTraversal", "1.0"));
56035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
56135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
56235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testIsSupported() {
56335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // we don't independently test the features; instead just assume the
56435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // implementation calls through to hasFeature (as tested above)
56535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
56635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(node.isSupported("XML", null));
56735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(node.isSupported("XML", "3.0"));
56835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(node.isSupported("foo", null));
56935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertFalse(node.isSupported("foo", "bar"));
57035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
57135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
57235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
57335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testGetFeature() {
57435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // we don't independently test the features; instead just assume the
57535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // implementation calls through to hasFeature (as tested above)
57635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
57735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertSame(node, node.getFeature("XML", null));
57835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertSame(node, node.getFeature("XML", "3.0"));
57935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertNull(node.getFeature("foo", null));
58035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertNull(node.getFeature("foo", "bar"));
58135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
58235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
58335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
58435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsPositive() throws Exception {
58535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        DomTest copy = new DomTest();
58635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.setUp();
58735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
58835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (int i = 0; i < allNodes.size(); i++) {
58935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            Node a = allNodes.get(i);
59035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            Node b = copy.allNodes.get(i);
59135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            assertTrue(a.isEqualNode(b));
59235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
59335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
59435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
59535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNegative() throws Exception {
59635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node a : allNodes) {
59735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            for (Node b : allNodes) {
59835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                assertEquals(a == b, a.isEqualNode(b));
59935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            }
60035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
60135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
60235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
60335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNegativeRecursive() throws Exception {
60435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        DomTest copy = new DomTest();
60535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.setUp();
60635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        copy.vitaminc.setTextContent("55%");
60735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
60835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // changing anything about a node should break equality for all parents
60935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(document.isEqualNode(copy.document));
61035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(menu.isEqualNode(copy.menu));
61135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(item.isEqualNode(copy.item));
61235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(nutrition.isEqualNode(copy.nutrition));
61335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitamins.isEqualNode(copy.vitamins));
61435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertFalse(vitaminc.isEqualNode(copy.vitaminc));
61535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
61635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        // but not siblings
61735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(doctype.isEqualNode(copy.doctype));
61835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(description.isEqualNode(copy.description));
61935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        assertTrue(option1.isEqualNode(copy.option1));
62035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
62135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
62235d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    public void testNodeEqualsNull() {
62335d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        for (Node node : allNodes) {
62435d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            try {
62535d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                node.isEqualNode(null);
62635d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson                fail();
62735d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            } catch (NullPointerException e) {
62835d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson            }
62935d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson        }
63035d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson    }
63135d7c089bd45f1030407b9b69b46e66f02c03043Jesse Wilson
632bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testIsElementContentWhitespaceWithoutDeclaration() throws Exception {
633bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String xml = "<menu>    <item/>   </menu>";
634bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
635bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
636bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text text = (Text) factory.newDocumentBuilder()
637bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .parse(new InputSource(new StringReader(xml)))
638bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .getDocumentElement().getChildNodes().item(0);
639bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertFalse(text.isElementContentWhitespace());
640bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
641bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
642bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testIsElementContentWhitespaceWithDeclaration() throws Exception {
643bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String xml = "<!DOCTYPE menu [\n"
644bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "  <!ELEMENT menu (item)*>\n"
645bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "  <!ELEMENT item (#PCDATA)>\n"
646bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                + "]><menu>    <item/>   </menu>";
647bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
648bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
649bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text text = (Text) factory.newDocumentBuilder()
650bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .parse(new InputSource(new StringReader(xml)))
651bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                .getDocumentElement().getChildNodes().item(0);
652bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertTrue("This implementation does not recognize element content whitespace",
653bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                text.isElementContentWhitespace());
654bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
655bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
656bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextFirst() {
657bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("Belgian waffles & strawberries (< 5g of fat)",
658bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                descriptionText1.getWholeText());
659bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
660bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
661bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextMiddle() {
662bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't include preceding nodes in getWholeText()",
663bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian waffles & strawberries (< 5g of fat)", descriptionText2.getWholeText());
664bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
665bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
666bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextLast() {
667bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't include preceding nodes in getWholeText()",
668bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian waffles & strawberries (< 5g of fat)", descriptionText3.getWholeText());
669bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
670bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
671bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextOnly() {
672bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("60%", vitamincText.getWholeText());
673bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
674bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
675bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testGetWholeTextWithEntityReference() {
676bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        EntityReference spReference = document.createEntityReference("sp");
677bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        description.insertBefore(spReference, descriptionText2);
678bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
679bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't resolve entity references in getWholeText()",
680bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "BelgianMaple Syrup waffles & strawberries (< 5g of fat)",
681bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                descriptionText1.getWholeText());
682bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
683bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
684bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirst() throws TransformerException {
685bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
686bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText1.replaceWholeText("Eggos");
687bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText1, replacement);
688bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
689bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos");
690bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
691bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
692bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
693bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextMiddle() throws TransformerException {
694bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
695bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText2.replaceWholeText("Eggos");
696bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText2, replacement);
697bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
698bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "<![CDATA[Eggos]]>");
699bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()",
700bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
701bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
702bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
703bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextLast() throws TransformerException {
704bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
705bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = descriptionText3.replaceWholeText("Eggos");
706bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(descriptionText3, replacement);
707bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace(
708bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                "Belgian<![CDATA[ waffles & strawberries (< 5g ]]>of fat)", "Eggos");
709bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove preceding nodes in replaceWholeText()",
710bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
711bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
712bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
713bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextOnly() throws TransformerException {
714bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
715bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        Text replacement = vitamincText.replaceWholeText("70%");
716bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(Node.TEXT_NODE, replacement.getNodeType());
717bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertSame(vitamincText, replacement);
718bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replace("60%", "70%");
719bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
720bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
721bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
722bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirstWithNull() throws TransformerException {
723bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
724bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText1.replaceWholeText(null));
725bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
726bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
727bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
728bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
729bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
730bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextMiddleWithNull() throws TransformerException {
731bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
732bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText2.replaceWholeText(null));
733bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
734bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
735bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
736bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
737bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
738bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextLastWithNull() throws TransformerException {
739bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
740bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText3.replaceWholeText(null));
741bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
742bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
743bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
744bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
745bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
746bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextFirstWithEmptyString() throws TransformerException {
747bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
748bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(descriptionText1.replaceWholeText(""));
749bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</description>", "/>");
750bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals("This implementation doesn't remove adjacent nodes in replaceWholeText(null)",
751bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson                expected, domToString(document));
752bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
753bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
754bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    public void testReplaceWholeTextOnlyWithEmptyString() throws TransformerException {
755bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String original = domToString(document);
756bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertNull(vitamincText.replaceWholeText(""));
757bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        String expected = original.replaceFirst(">.*</a:vitaminc>", "/>");
758bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson        assertEquals(expected, domToString(document));
759bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    }
760bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson
7618b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataAttachments() {
7628b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Object a = new Object();
7638b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Object b = new Object();
7648b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        for (Node node : allNodes) {
7658b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            node.setUserData("a", a, null);
7668b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            node.setUserData("b", b, null);
7678b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7688b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        for (Node node : allNodes) {
7698b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertSame(a, node.getUserData("a"));
7708b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertSame(b, node.getUserData("b"));
7718b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertEquals(null, node.getUserData("c"));
7728b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            assertEquals(null, node.getUserData("A"));
7738b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7748b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
7758b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
7768b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataRejectsNullKey() {
7778b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        try {
7788b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            menu.setUserData(null, "apple", null);
7798b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            fail();
7808b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        } catch (NullPointerException e) {
7818b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7828b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        try {
7838b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            menu.getUserData(null);
7848b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            fail();
7858b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        } catch (NullPointerException e) {
7868b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
7878b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
7888b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
7898b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    /**
7908b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     * A shallow clone requires cloning the attributes but not the child nodes.
7918b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     */
7928b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataHandlerNotifiedOfShallowClones() {
7938b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        RecordingHandler handler = new RecordingHandler();
7948b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("a", "apple", handler);
7958b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("b", "banana", handler);
7968b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        standard.setUserData("c", "cat", handler);
7978b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles.setUserData("d", "dog", handler);
7988b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
7998b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Element clonedName = (Element) name.cloneNode(false);
8008b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Attr clonedStandard = clonedName.getAttributeNode("a:standard");
8018b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8028b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Set<String> expected = new HashSet<String>();
8038b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "a", "apple", name, clonedName));
8048b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "b", "banana", name, clonedName));
8058b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "c", "cat", standard, clonedStandard));
8068b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        assertEquals(expected, handler.calls);
8078b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
8088b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8098b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    /**
8108b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     * A deep clone requires cloning both the attributes and the child nodes.
8118b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson     */
8128b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    public void testUserDataHandlerNotifiedOfDeepClones() {
8138b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        RecordingHandler handler = new RecordingHandler();
8148b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("a", "apple", handler);
8158b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        name.setUserData("b", "banana", handler);
8168b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        standard.setUserData("c", "cat", handler);
8178b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        waffles.setUserData("d", "dog", handler);
8188b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8198b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Element clonedName = (Element) name.cloneNode(true);
8208b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Attr clonedStandard = clonedName.getAttributeNode("a:standard");
8218b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Text clonedWaffles = (Text) clonedName.getChildNodes().item(0);
8228b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
8238b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        Set<String> expected = new HashSet<String>();
8248b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "a", "apple", name, clonedName));
8258b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "b", "banana", name, clonedName));
8268b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "c", "cat", standard, clonedStandard));
8278b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        expected.add(notification(NODE_CLONED, "d", "dog", waffles, clonedWaffles));
8288b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        assertEquals(expected, handler.calls);
8298b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
8308b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
831df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
832df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * A shallow import requires importing the attributes but not the child
833df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * nodes.
834df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
835df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfShallowImports() {
836df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
837df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
838df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
839df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
840df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
841df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
842df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
843df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedName = (Element) newDocument.importNode(name, false);
844df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Attr importedStandard = importedName.getAttributeNode("a:standard");
845df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
846df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
847df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "a", "apple", name, importedName));
848df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "b", "banana", name, importedName));
849df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "c", "cat", standard, importedStandard));
850df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
851df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
852df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
853df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
854df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * A deep import requires cloning both the attributes and the child nodes.
855df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
856df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfDeepImports() {
857df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
858df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
859df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
860df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
861df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
862df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
863df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
864df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedName = (Element) newDocument.importNode(name, true);
865df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Attr importedStandard = importedName.getAttributeNode("a:standard");
866df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Text importedWaffles = (Text) importedName.getChildNodes().item(0);
867df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
868df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
869df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "a", "apple", name, importedName));
870df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "b", "banana", name, importedName));
871df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "c", "cat", standard, importedStandard));
872df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_IMPORTED, "d", "dog", waffles, importedWaffles));
873df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
874df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
875df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
876df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testImportNodeDeep() throws TransformerException {
877df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String original = domToStringStripElementWhitespace(document);
878df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
879df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
880df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedItem = (Element) newDocument.importNode(item, true);
881df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(item.getParentNode(), importedItem);
882df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
883df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(importedItem);
884df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String expected = original.replaceAll("</?menu>", "");
885df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, domToStringStripElementWhitespace(newDocument));
886df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
887df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
888df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testImportNodeShallow() throws TransformerException {
889df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
890df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Element importedItem = (Element) newDocument.importNode(item, false);
891df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(item.getParentNode(), importedItem);
892df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
893df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(importedItem);
894df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals("<item xmlns=\"http://food\" xmlns:a=\"http://addons\"/>",
895df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                domToString(newDocument));
896df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
897df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
898df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testNodeAdoption() throws Exception {
899df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        for (Node node : allNodes) {
900df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            if (node == document || node == doctype || node == sp || node == png) {
901df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                assertNotAdoptable(node);
902df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            } else {
903df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                adoptAndCheck(node);
904df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            }
905df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
906df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
907df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
908df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void assertNotAdoptable(Node node) {
909df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        try {
910df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            builder.newDocument().adoptNode(node);
911df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            fail();
912df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } catch (DOMException e) {
913df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
914df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
915df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
916df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
917df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * Adopts the node into another document, then adopts the root element, and
918df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * then attaches the adopted node in the proper place. The net result should
919df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * be that the document's entire contents have moved to another document.
920df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
921df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void adoptAndCheck(Node node) throws Exception {
922df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String original = domToString(document);
923df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
924df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
925df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // remember where to insert the node in the new document
926df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        boolean isAttribute = node.getNodeType() == Node.ATTRIBUTE_NODE;
927df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Node parent = isAttribute
928df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                ? ((Attr) node).getOwnerElement() : node.getParentNode();
929df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Node nextSibling = node.getNextSibling();
930df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
931df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // move the node and make sure it was detached
932df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(node, newDocument.adoptNode(node));
933df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertDetached(parent, node);
934df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
935df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        // move the rest of the document and wire the adopted back into place
936df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(menu, newDocument.adoptNode(menu));
937df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        newDocument.appendChild(menu);
938df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (isAttribute) {
939df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            ((Element) parent).setAttributeNodeNS((Attr) node);
940df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } else if (nextSibling != null) {
941df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            parent.insertBefore(node, nextSibling);
942df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } else if (parent != document) {
943df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            parent.appendChild(node);
944df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
945df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
946df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(original, domToString(newDocument));
947df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        document = newDocument;
948df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
949df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
950df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private void assertDetached(Node formerParent, Node node) {
951df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertNull(node.getParentNode());
952df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        NodeList children = formerParent.getChildNodes();
953df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        for (int i = 0; i < children.getLength(); i++) {
954df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertTrue(children.item(i) != node);
955df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
956df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
957df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertNull(((Attr) node).getOwnerElement());
958df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            NamedNodeMap attributes = formerParent.getAttributes();
959df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            for (int i = 0; i < attributes.getLength(); i++) {
960df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                assertTrue(attributes.item(i) != node);
961df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            }
962df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
963df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
964df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
965df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testAdoptionImmediatelyAfterParsing() throws Exception {
966df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
967df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        try {
968df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(name, newDocument.adoptNode(name));
969df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, name.getOwnerDocument());
970df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, standard.getOwnerDocument());
971df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            assertSame(newDocument, waffles.getOwnerDocument());
972df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        } catch (Throwable e) {
973df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            AssertionFailedError failure = new AssertionFailedError(
974df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    "This implementation fails to adopt nodes before the "
975df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                            + "document has been traversed");
976df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            failure.initCause(e);
977df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            throw failure;
978df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
979df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
980df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
981df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    /**
982df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * There should be notifications for adopted node itself but none of its
983df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     * children. The DOM spec is vague on this, so we're consistent with the RI.
984df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson     */
985df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    public void testUserDataHandlerNotifiedOfOnlyShallowAdoptions() throws Exception {
986df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        /*
987df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * Force a traversal of the document, otherwise this test may fail for
988df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * an unrelated reason on version 5 of the RI. That behavior is
989df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * exercised by testAdoptionImmediatelyAfterParsing().
990df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         */
991df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        domToString(document);
992df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
993df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        RecordingHandler handler = new RecordingHandler();
994df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("a", "apple", handler);
995df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        name.setUserData("b", "banana", handler);
996df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        standard.setUserData("c", "cat", handler);
997df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        waffles.setUserData("d", "dog", handler);
998df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
999df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Document newDocument = builder.newDocument();
1000df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(name, newDocument.adoptNode(name));
1001df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, name.getOwnerDocument());
1002df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, standard.getOwnerDocument());
1003df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertSame(newDocument, waffles.getOwnerDocument());
1004df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1005df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Set<String> expected = new HashSet<String>();
1006df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_ADOPTED, "a", "apple", name, null));
1007df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        expected.add(notification(NODE_ADOPTED, "b", "banana", name, null));
1008df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        assertEquals(expected, handler.calls);
1009df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1010df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1011302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriRelativeUriResolution() throws Exception {
1012302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        File file = File.createTempFile("DomTest.java", "xml");
1013302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        File parentFile = file.getParentFile();
1014302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        FileWriter writer = new FileWriter(file);
1015302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        writer.write("<a>"
1016302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  <b xml:base=\"b1/b2\">"
1017302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    <c>"
1018302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "      <d xml:base=\"../d1/d2\"><e/></d>"
1019302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    </c>"
1020302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  </b>"
1021302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  <h xml:base=\"h1/h2/\">"
1022302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "    <i xml:base=\"../i1/i2\"/>"
1023302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "  </h>"
1024302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "</a>");
1025302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        writer.close();
1026302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document = builder.parse(file);
1027302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1028302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), document.getBaseURI());
1029302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), document.getDocumentURI());
1030302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element a = document.getDocumentElement();
1031302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals("", file.getPath(), a.getBaseURI());
1032302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1033302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        String message = "This implementation's getBaseURI() doesn't handle relative URIs";
1034302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element b = (Element) a.getChildNodes().item(1);
1035302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element c = (Element) b.getChildNodes().item(1);
1036302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element d = (Element) c.getChildNodes().item(1);
1037302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element e = (Element) d.getChildNodes().item(0);
1038302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element h = (Element) a.getChildNodes().item(3);
1039302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element i = (Element) h.getChildNodes().item(1);
1040302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/b1/b2", b.getBaseURI());
1041302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/b1/b2", c.getBaseURI());
1042302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/d1/d2", d.getBaseURI());
1043302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/d1/d2", e.getBaseURI());
1044302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/h1/h2/", h.getBaseURI());
1045302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertFileUriEquals(message, parentFile + "/h1/i1/i2", i.getBaseURI());
1046302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1047302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1048302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    /**
1049302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * Regrettably both "file:/tmp/foo.txt" and "file:///tmp/foo.txt" are
1050302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * legal URIs, and different implementations emit different forms.
1051302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     */
1052302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    private void assertFileUriEquals(
1053302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            String message, String expectedFile, String actual) {
1054302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (!("file:" + expectedFile).equals(actual)
1055302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                && !("file://" + expectedFile).equals(actual)) {
1056302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            fail("Expected URI for: " + expectedFile
1057302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                    + " but was " + actual + ". " + message);
1058302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1059302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1060302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1061302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    /**
1062302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * According to the <a href="http://www.w3.org/TR/xmlbase/">XML Base</a>
1063302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     * spec, fragments (like "#frag" or "") should not be dereferenced.
1064302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson     */
1065302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriResolutionWithHashes() throws Exception {
1066302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document = builder.parse(new InputSource(new StringReader(
1067302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                "<a xml:base=\"http://a1/a2\">"
1068302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <b xml:base=\"b1#b2\"/>"
1069302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <c xml:base=\"#c1\">"
1070302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "    <d xml:base=\"\"/>"
1071302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  </c>"
1072302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "  <e xml:base=\"\"/>"
1073302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                        + "</a>")));
1074302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element a = document.getDocumentElement();
1075302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://a1/a2", a.getBaseURI());
1076302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1077302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        String message = "This implementation's getBaseURI() doesn't handle "
1078302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson                + "relative URIs with hashes";
1079302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element b = (Element) a.getChildNodes().item(1);
1080302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element c = (Element) a.getChildNodes().item(3);
1081302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element d = (Element) c.getChildNodes().item(1);
1082302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        Element e = (Element) a.getChildNodes().item(5);
1083302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/b1#b2", b.getBaseURI());
1084302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2#c1", c.getBaseURI());
1085302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2#c1", d.getBaseURI());
1086302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals(message, "http://a1/a2", e.getBaseURI());
1087302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1088302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1089302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriInheritedForProcessingInstructions() {
1090302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1091302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://d1/d2", wafflemaker.getBaseURI());
1092302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1093302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1094302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriInheritedForEntities() {
1095302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (sp == null) {
1096302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            return;
1097302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1098302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1099302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertEquals("http://d1/d2", sp.getBaseURI());
1100302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1101302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1102302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForNotations() {
1103302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        if (png == null) {
1104302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson            return;
1105302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        }
1106302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1107302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(png.getBaseURI());
1108302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1109302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1110302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForDoctypes() {
1111302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1112302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(doctype.getBaseURI());
1113302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1114302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1115302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForAttributes() {
1116302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1117302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(itemXmlns.getBaseURI());
1118302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(itemXmlnsA.getBaseURI());
1119302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(standard.getBaseURI());
1120302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(vitaminsXmlnsA.getBaseURI());
1121302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1122302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1123302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForTextsOrCdatas() {
1124302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1125302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText1.getBaseURI());
1126302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText2.getBaseURI());
1127302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(option2Reference.getBaseURI());
1128302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1129302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1130302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForComments() {
1131302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1132302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText1.getBaseURI());
1133302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(descriptionText2.getBaseURI());
1134302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1135302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
1136302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    public void testBaseUriNotInheritedForEntityReferences() {
1137302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        document.setDocumentURI("http://d1/d2");
1138302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson        assertNull(option2Reference.getBaseURI());
1139302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson    }
1140302f069f38e7890594816ceab517c15bcd59a9b7Jesse Wilson
11418b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private class RecordingHandler implements UserDataHandler {
11428b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        final Set<String> calls = new HashSet<String>();
11438b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        public void handle(short operation, String key, Object data, Node src, Node dst) {
11448b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson            calls.add(notification(operation, key, data, src, dst));
11458b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        }
11468b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
11478b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
11488b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    private String notification(short operation, String key, Object data, Node src, Node dst) {
11498b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson        return "op:" + operation + " key:" + key + " data:" + data + " src:" + src + " dst:" + dst;
11508b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson    }
11518b2f7a2b953a0ae4f01f7632fab2f29fe4d14a64Jesse Wilson
1152bda224da00c0372a7752b1304aeda98e2930c4afJesse Wilson    private String domToString(Document document) throws TransformerException {
1153ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        StringWriter writer = new StringWriter();
1154ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson        transformer.transform(new DOMSource(document), new StreamResult(writer));
1155df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        String result = writer.toString();
1156df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1157df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        /*
1158df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * Hack: swap <name>'s a:standard attribute and deluxe attribute if
1159df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * they're out of order. Some document transformations reorder the
1160df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * attributes, which causes pain when we try to use String comparison on
1161df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         * them.
1162df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson         */
1163df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        Matcher attributeMatcher = Pattern.compile(" a:standard=\"[^\"]+\"").matcher(result);
1164df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        if (attributeMatcher.find()) {
1165df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            result = result.substring(0, attributeMatcher.start())
1166df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + result.substring(attributeMatcher.end());
1167df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            int insertionPoint = result.indexOf(" deluxe=\"");
1168df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            result = result.substring(0, insertionPoint)
1169df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + attributeMatcher.group()
1170df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson                    + result.substring(insertionPoint);
1171df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        }
1172df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1173df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        return result;
1174df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    }
1175df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson
1176df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson    private String domToStringStripElementWhitespace(Document document)
1177df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson            throws TransformerException {
1178df138faff880612d97a8e6e3fa344a91ae9d96acJesse Wilson        return domToString(document).replaceAll("(?m)>\\s+<", "><");
1179ea5adee4813216359fda6529e7064c42ccdbc4cdJesse Wilson    }
11801ec94feeb09591c30996c7c0834d6f131e204922Jesse Wilson}
1181