/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
**/
package org.codice.ddf.parser.xml;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
import javax.xml.bind.util.JAXBSource;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import org.codice.ddf.parser.Parser;
import org.codice.ddf.parser.ParserConfigurator;
import org.codice.ddf.parser.ParserException;
import org.codice.ddf.parser.xml.domain.ChildElement;
import org.codice.ddf.parser.xml.domain.MotherElement;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.google.common.collect.ImmutableList;
public class TestXmlParser {
@Rule
public ExpectedException thrown = ExpectedException.none();
private Parser parser;
private ParserConfigurator configurator;
private MotherElement mother;
private ChildElement luke;
private ChildElement leia;
@Before
public void setUp() throws Exception {
parser = new XmlParser();
List<String> ctxPath = ImmutableList.of(MotherElement.class.getPackage()
.getName());
configurator = parser.configureParser(ctxPath, TestXmlParser.class.getClassLoader());
mother = new MotherElement();
mother.setFirstname("Padme");
mother.setLastname("Skywalker");
mother.setAge(25);
luke = new ChildElement();
luke.setAge(2);
luke.setFirstname("Luke");
luke.setLastname("Skywalker");
leia = new ChildElement();
leia.setAge(2);
leia.setFirstname("Leia");
leia.setLastname("Organa");
mother.getChild()
.add(luke);
mother.getChild()
.add(leia);
}
@Test
public void testConfigureParser() {
assertTrue(configurator.getContextPath()
.contains(MotherElement.class.getPackage()
.getName()));
assertEquals(TestXmlParser.class.getClassLoader(), configurator.getClassLoader());
}
@Test
public void testMarshal() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
parser.marshal(configurator, mother, os);
String outputXml = os.toString();
assertXpathEvaluatesTo("Padme", "/mother/@firstname", outputXml);
assertXpathEvaluatesTo("25", "/mother/@age", outputXml);
assertXpathExists("/mother/child/@firstname", outputXml);
assertXpathExists("/mother/child[@firstname='Luke']", outputXml);
assertXpathNotExists("/mother/child[@firstname='Anakin']", outputXml);
configurator.setHandler(new DefaultValidationEventHandler());
os = new ByteArrayOutputStream();
parser.marshal(configurator, mother, os);
outputXml = os.toString();
assertXpathEvaluatesTo("Padme", "/mother/@firstname", outputXml);
configurator.addProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
os = new ByteArrayOutputStream();
parser.marshal(configurator, mother, os);
outputXml = os.toString();
assertXpathEvaluatesTo("Padme", "/mother/@firstname", outputXml);
}
@Test
public void testUnmarshal() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
parser.marshal(configurator, mother, os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
MotherElement unmarshal = parser.unmarshal(configurator, MotherElement.class, is);
assertEquals(mother.getAge(), unmarshal.getAge());
assertEquals(mother.getFirstname(), unmarshal.getFirstname());
assertEquals(mother.getLastname(), unmarshal.getLastname());
assertEquals(mother.getChild()
.size(),
unmarshal.getChild()
.size());
assertEquals(luke.getFirstname(),
unmarshal.getChild()
.get(0)
.getFirstname());
assertEquals(leia.getAge(),
unmarshal.getChild()
.get(1)
.getAge());
configurator.setHandler(new DefaultValidationEventHandler());
is = new ByteArrayInputStream(os.toByteArray());
unmarshal = parser.unmarshal(configurator, MotherElement.class, is);
assertEquals(mother.getAge(), unmarshal.getAge());
configurator.addProperty("UnknownProperty", Boolean.TRUE);
is = new ByteArrayInputStream(os.toByteArray());
thrown.expect(ParserException.class);
parser.unmarshal(configurator, MotherElement.class, is);
}
@Test
public void testUnmarshalBadCast() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
parser.marshal(configurator, mother, os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
thrown.expect(ClassCastException.class);
ChildElement unmarshal = parser.unmarshal(configurator, ChildElement.class, is);
}
@Test
public void testMarshalNode() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.newDocument();
parser.marshal(configurator, mother, doc);
// check the root
assertEquals(1,
doc.getChildNodes()
.getLength());
assertEquals(3,
doc.getDocumentElement()
.getAttributes()
.getLength());
assertEquals(mother.getAge()
.toString(),
doc.getDocumentElement()
.getAttributes()
.getNamedItem("age")
.getNodeValue());
assertEquals(mother.getFirstname(),
doc.getDocumentElement()
.getAttributes()
.getNamedItem("firstname")
.getNodeValue());
assertEquals(mother.getLastname(),
doc.getDocumentElement()
.getAttributes()
.getNamedItem("lastname")
.getNodeValue());
// check the child nodes
assertEquals(mother.getChild()
.size(),
doc.getFirstChild()
.getChildNodes()
.getLength());
// first child
assertEquals(3,
doc.getDocumentElement()
.getChildNodes()
.item(0)
.getAttributes()
.getLength());
assertEquals(mother.getChild()
.get(0)
.getFirstname(),
doc.getDocumentElement()
.getChildNodes()
.item(0)
.getAttributes()
.getNamedItem("firstname")
.getNodeValue());
assertEquals(mother.getChild()
.get(0)
.getLastname(),
doc.getDocumentElement()
.getChildNodes()
.item(0)
.getAttributes()
.getNamedItem("lastname")
.getNodeValue());
assertEquals(mother.getChild()
.get(0)
.getAge()
.toString(),
doc.getDocumentElement()
.getChildNodes()
.item(0)
.getAttributes()
.getNamedItem("age")
.getNodeValue());
// second child
assertEquals(3,
doc.getDocumentElement()
.getChildNodes()
.item(1)
.getAttributes()
.getLength());
assertEquals(mother.getChild()
.get(1)
.getFirstname(),
doc.getDocumentElement()
.getChildNodes()
.item(1)
.getAttributes()
.getNamedItem("firstname")
.getNodeValue());
assertEquals(mother.getChild()
.get(1)
.getLastname(),
doc.getDocumentElement()
.getChildNodes()
.item(1)
.getAttributes()
.getNamedItem("lastname")
.getNodeValue());
assertEquals(mother.getChild()
.get(1)
.getAge()
.toString(),
doc.getDocumentElement()
.getChildNodes()
.item(1)
.getAttributes()
.getNamedItem("age")
.getNodeValue());
}
@Test
public void testMarshalNodeRunTimeException() throws Exception {
thrown.expect(ParserException.class);
parser.marshal(configurator, mother, (Node) null);
}
@Test
public void testMarshalNodeJAXBException() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.newDocument();
configurator.addProperty("BadKey", "BadValue");
thrown.expect(ParserException.class);
parser.marshal(configurator, mother, doc);
}
@Test
public void testUnmarshalNode() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.newDocument();
parser.marshal(configurator, mother, doc);
MotherElement unmarshal = parser.unmarshal(configurator, MotherElement.class, doc);
assertEquals(mother.getAge(), unmarshal.getAge());
assertEquals(mother.getFirstname(), unmarshal.getFirstname());
assertEquals(mother.getLastname(), unmarshal.getLastname());
assertEquals(mother.getChild()
.size(),
unmarshal.getChild()
.size());
assertEquals(luke.getFirstname(),
unmarshal.getChild()
.get(0)
.getFirstname());
assertEquals(leia.getAge(),
unmarshal.getChild()
.get(1)
.getAge());
}
@Test
public void testUnmarshalNodeRunTimeException() throws Exception {
thrown.expect(ParserException.class);
parser.unmarshal(configurator, MotherElement.class, (Node) null);
}
@Test
public void testUnmarshalNodeJAXBException() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.newDocument();
parser.marshal(configurator, mother, doc);
configurator.addProperty("BadKey", "BadValue");
thrown.expect(ParserException.class);
parser.unmarshal(configurator, MotherElement.class, doc);
}
@Test
public void testUnmarshalSource() throws Exception {
JAXBContext motherContext = JAXBContext.newInstance(MotherElement.class);
@SuppressWarnings("unchecked")
JAXBElement<MotherElement> motherElementJAXBElement = new JAXBElement(new QName("mother"),
MotherElement.class,
mother);
JAXBSource motherSource = new JAXBSource(motherContext, motherElementJAXBElement);
MotherElement unmarshal = parser.unmarshal(configurator, MotherElement.class, motherSource);
assertEquals(mother.getAge(), unmarshal.getAge());
assertEquals(mother.getFirstname(), unmarshal.getFirstname());
assertEquals(mother.getLastname(), unmarshal.getLastname());
assertEquals(mother.getChild()
.size(),
unmarshal.getChild()
.size());
assertEquals(luke.getFirstname(),
unmarshal.getChild()
.get(0)
.getFirstname());
assertEquals(leia.getAge(),
unmarshal.getChild()
.get(1)
.getAge());
}
@Test
public void testUnmarshalSourceRunTimeException() throws Exception {
thrown.expect(ParserException.class);
parser.unmarshal(configurator, MotherElement.class, (Source) null);
}
@Test
public void testUnmarshalSourceJAXBException() throws Exception {
JAXBContext motherContext = JAXBContext.newInstance(MotherElement.class);
@SuppressWarnings("unchecked")
JAXBElement<MotherElement> motherElementJAXBElement = new JAXBElement(new QName("mother"),
MotherElement.class,
mother);
JAXBSource motherSource = new JAXBSource(motherContext, motherElementJAXBElement);
configurator.addProperty("BadKey", "BadValue");
thrown.expect(ParserException.class);
parser.unmarshal(configurator, MotherElement.class, motherSource);
}
@Test
public void testBadContextPath() throws Exception {
configurator.setContextPath(ImmutableList.of(""));
ByteArrayOutputStream os = new ByteArrayOutputStream();
thrown.expect(ParserException.class);
parser.marshal(configurator, mother, os);
}
@Test
public void testBadMarshal() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
thrown.expect(ParserException.class);
parser.marshal(configurator, this, os);
}
@Test
public void testBadUnmarshal() throws Exception {
ByteArrayInputStream is = new ByteArrayInputStream(new byte[] {0, 1, 2});
thrown.expect(ParserException.class);
parser.unmarshal(configurator, ChildElement.class, is);
}
@Test
public void testTypeAdapter() throws Exception {
// TODO RAP 30 Jun 15: Actually need to *test* the type adapter
// configurator.setAdapter(new XmlAdapter() {
// @Override
// public Object unmarshal(Object v) throws Exception {
// return null;
// }
//
// @Override
// public Object marshal(Object v) throws Exception {
// return null;
// }
// });
// parser.marshal(configurator, mother, os);
// String outputXml = os.toString();
//
// assertXpathEvaluatesTo("Padme", "/mother/@firstname", outputXml);
//
// ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
// MotherElement unmarshal = parser.unmarshal(configurator, MotherElement.class, is);
//
// assertEquals(mother.getAge(), unmarshal.getAge());
}
@Test
public void testCacheKey() throws Exception {
XmlParser.CacheKey cacheKey1 = new XmlParser.CacheKey("hello:world",
TestXmlParser.class.getClassLoader());
XmlParser.CacheKey cacheKey2 = new XmlParser.CacheKey("here:now",
TestXmlParser.class.getClassLoader());
XmlParser.CacheKey cacheKey3 = new XmlParser.CacheKey("hello:world",
TestXmlParser.class.getClassLoader());
assertThat(cacheKey1, not(equalTo(cacheKey2)));
assertThat(cacheKey1.hashCode(), not(equalTo(cacheKey2.hashCode())));
assertTrue(cacheKey1.equals(cacheKey3));
assertThat(cacheKey1.hashCode(), equalTo(cacheKey3.hashCode()));
assertThat(cacheKey1, equalTo(cacheKey1));
assertThat(cacheKey1, not(equalTo(null)));
assertEquals(cacheKey1.equals(null), false);
assertEquals(cacheKey1.equals("hello world"), false);
}
}