package marubinotto.util.xml; import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.custommonkey.xmlunit.XMLUnit; import org.junit.Test; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; /** * marubinotto.util.xml.XmlTreeTestBase */ public abstract class XmlTreeTestBase { protected abstract XmlTree createXmlTree() throws Exception; public static Document createDocument(String namespaceURI, String qualifiedName) throws ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); DOMImplementation domImpl = builder.getDOMImplementation(); return domImpl.createDocument(namespaceURI, qualifiedName, null); } // Input @Test public void shouldSetRootViaSetter() throws Exception { Document document = createDocument(null, "root"); XmlTree tree = createXmlTree(); tree.setRoot(document); assertSame(document, tree.getRoot()); } @Test public void shouldReturnOwnerDocumentIfRootIsADocument() throws Exception { Document document = createDocument(null, "root"); XmlTree tree = createXmlTree(); tree.setRoot(document); assertSame(document, tree.getOwnerDocument()); } @Test public void shouldReturnOwnerDocumentIfRootIsAnElement() throws Exception { Document document = DomUtils.buildDocument("<element>value</element>"); XmlTree tree = createXmlTree(); tree.setRoot(document.getDocumentElement()); assertSame(document, tree.getOwnerDocument()); } @Test public void shouldReadXmlFromInputStream() throws Exception { InputStream in = new ByteArrayInputStream("<element>value</element>".getBytes()); XmlTree tree = createXmlTree(); tree.readFrom(in); assertTrue(tree.getRoot() instanceof Document); assertXMLEqual( XMLUnit.buildControlDocument("<element>value</element>"), (Document)tree.getRoot()); } @Test public void shouldBuildTreeFromXmlString() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<element>value</element>"); assertTrue(tree.getRoot() instanceof Document); assertXMLEqual( XMLUnit.buildControlDocument("<element>value</element>"), (Document)tree.getRoot()); } @Test public void shouldBuildTreeFromDomDocument() throws Exception { Document document = createDocument(null, "root"); XmlTree tree = createXmlTree(); tree.fromDom(document); assertSame(document, tree.getRoot()); } @Test public void shouldBuildTreeFromDomElement() throws Exception { Document document = createDocument(null, "root"); Element element = document.createElement("sub"); XmlTree tree = createXmlTree(); tree.fromDom(element); assertSame(element, tree.getRoot()); } // Output @Test public void shouldWriteTreeToOutputStream() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<element>hello</element>"); ByteArrayOutputStream out = new ByteArrayOutputStream(); tree.writeTo(out); assertXMLEqual( "<element>hello</element>", new String(out.toByteArray(), "UTF-8")); } @Test public void shouldReturnTreeAsXmlString() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<element>value</element>"); assertXMLEqual( "<element>value</element>", tree.toXml()); } @Test public void shouldReturnTreeAsDom() throws Exception { Document document = createDocument(null, "root"); XmlTree tree = createXmlTree(); tree.setRoot(document); assertSame(document, tree.toDom()); } // XPath @Test public void shouldSelectSingleNodeByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<element>value</element>"); Node node = tree.selectSingleNode("/element/text()"); assertTrue(node instanceof Text); assertEquals("value", node.getNodeValue()); } @Test public void shouldSelectTheFirstNodeFromSelectableNodesByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub>foo</sub>" + "<sub>bar</sub>" + "<sub>hoge</sub>" + "</root>"); Node node = tree.selectSingleNode("/root/sub/text()"); assertTrue(node instanceof Text); assertEquals("foo", node.getNodeValue()); } @Test public void shouldSelectSingleNodeWithLocaleByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub xml:lang='en'>English</sub>" + "<sub xml:lang='ja'>Japanese</sub>" + "</root>"); Node node = tree.selectSingleNode("/root/sub/text()", Locale.ENGLISH); assertEquals("English", node.getNodeValue()); node = tree.selectSingleNode("/root/sub/text()", Locale.JAPANESE); assertEquals("Japanese", node.getNodeValue()); } @Test public void shouldSelectTheFirstNodeWithLocaleFromSelectableNodesByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub xml:lang='en'>English</sub>" + "<sub xml:lang='ja'>Japanese1</sub>" + "<sub xml:lang='ja'>Japanese2</sub>" + "<sub xml:lang='ja'>Japanese3</sub>" + "</root>"); Node node = tree.selectSingleNode("/root/sub/text()", Locale.JAPANESE); assertEquals("Japanese1", node.getNodeValue()); } @Test public void shouldSelectNodesByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<messages>" + "<message>Hello</message>" + "<message>World</message>" + "</messages>"); List<Node> nodes = tree.selectNodes("/messages/message/text()"); assertEquals(2, nodes.size()); assertEquals("Hello", ((Text)nodes.get(0)).getNodeValue()); assertEquals("World", ((Text)nodes.get(1)).getNodeValue()); } @Test public void shouldSelectSubtreesByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<messages>" + "<message>Hello</message>" + "<message>World</message>" + "</messages>"); List<XmlTree> subtrees = tree.selectSubtrees("/messages/message"); assertEquals(2, subtrees.size()); assertXMLEqual( "<message>Hello</message>", ((XmlTree)subtrees.get(0)).toXml()); assertXMLEqual( "<message>World</message>", ((XmlTree)subtrees.get(1)).toXml()); } @Test public void shouldSelectValuesByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub xml:lang='en'>English</sub>" + "<sub xml:lang='ja'>Japanese</sub>" + "<sub>Hogehoge</sub>" + "<sub/>" + "</root>"); List<String> values = tree.selectValues("/root/sub"); assertEquals(4, values.size()); assertEquals("English", values.get(0)); assertEquals("Japanese", values.get(1)); assertEquals("Hogehoge", values.get(2)); assertNull(values.get(3)); } @Test public void shouldReturnStringValueOfNodeByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<element attribute='foo'>bar</element>"); assertEquals("bar", tree.stringValueOf("/element")); assertEquals("bar", tree.stringValueOf("/element/text()")); assertEquals("foo", tree.stringValueOf("/element/@attribute")); } @Test public void shouldReturnStringValueOfNodeWithLocaleByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub xml:lang='en'>English</sub>" + "<sub xml:lang='ja'>Japanese</sub>" + "</root>"); assertEquals( "English", tree.stringValueOf("/root/sub/text()", Locale.ENGLISH)); assertEquals( "Japanese", tree.stringValueOf("/root/sub/text()", Locale.JAPANESE)); assertNull(tree.stringValueOf("/foo/bar", Locale.JAPANESE)); } @Test public void shouldReturnBooleanValueOfNodeByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub>hoge</sub>" + "<sub/>" + "</root>"); assertTrue(tree.booleanValueOf("/root/sub[1]/text()")); assertTrue(!tree.booleanValueOf("/root/sub[2]/text()")); assertTrue(tree.booleanValueOf("/root")); assertTrue(!tree.booleanValueOf("/notexisting")); } @Test public void shouldReturnNumberValueOfNodeByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub>4649</sub>" + "<sub>0</sub>" + "<sub>-123</sub>" + "<sub>3.14</sub>" + "<sub>hoge</sub>" + "<sub/>" + "</root>"); assertEquals("NaN", tree.numberValueOf("/root/sub[1]/text()").toString()); assertEquals(0, tree.numberValueOf("/root/sub[1]/text()").intValue()); assertEquals(4649, tree.numberValueOf("/root/sub[1]").intValue()); assertEquals(0, tree.numberValueOf("/root/sub[2]").intValue()); assertEquals(-123, tree.numberValueOf("/root/sub[3]").intValue()); assertEquals(3.14f, tree.numberValueOf("/root/sub[4]").floatValue(), 0.01f); assertEquals("NaN", tree.numberValueOf("/root/sub[5]").toString()); assertEquals(0, tree.numberValueOf("/root/sub[5]").intValue()); assertEquals("NaN", tree.numberValueOf("/root/sub[6]").toString()); assertEquals(0, tree.numberValueOf("/root/sub[6]").intValue()); } @Test public void shouldReturnStringValueOfNullByXPath() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<sub/>" + "<sub>hello</sub>" + "</root>"); assertNull(tree.stringValueOf("/root/sub[1]")); assertNull(tree.stringValueOf("/root/sub[1]/text()")); assertNotNull(tree.stringValueOf("/root/sub[2]")); } // XPath mappings @Test public void shouldSupportXpathMappings() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<message>Hello world!</message>"); Map<String, String> xpaths = new HashMap<String, String>(); xpaths.put("message", "/message"); tree.setXpaths(xpaths); assertEquals("/message", tree.getXpath("message")); assertEquals("/message", tree.getXpaths().get("message")); assertEquals("Hello world!", tree.get("message")); assertTrue(tree.set("message", "Updated!")); assertEquals("Updated!", tree.get("message")); assertXMLEqual( "<message>Updated!</message>", tree.toXml()); } @Test public void shouldSupportXpathMappingsWithLocale() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml( "<root>" + "<message xml:lang='en'>English</message>" + "<message xml:lang='ja'>Japanese</message>" + "</root>"); Map<String, String> xpaths = new HashMap<String, String>(); xpaths.put("message", "/root/message"); tree.setXpaths(xpaths); assertEquals("English", tree.get("message")); assertEquals("English", tree.get("message", Locale.ENGLISH)); assertEquals("Japanese", tree.get("message", Locale.JAPANESE)); assertNull(tree.get("message", Locale.FRENCH)); assertTrue(tree.set("message", Locale.ENGLISH, "Updated-English")); assertEquals("Updated-English", tree.get("message", Locale.ENGLISH)); assertEquals("Japanese", tree.get("message", Locale.JAPANESE)); assertTrue(tree.set("message", Locale.JAPANESE, "Updated-Japanese")); assertEquals("Updated-English", tree.get("message", Locale.ENGLISH)); assertEquals("Updated-Japanese", tree.get("message", Locale.JAPANESE)); assertTrue(!tree.set("message", Locale.ITALY, "Updated-Italy")); } @Test(expected=IllegalArgumentException.class) public void shouldThrowExceptionWhenSpecifyInvalidMappingName() throws Exception { XmlTree tree = createXmlTree(); tree.fromXml("<message>Hello world!</message>"); tree.get("foo"); } }