/* * Copyright 2015 Workday, Inc. * * This software is available under the MIT license. * Please see the LICENSE.txt file in this project. */ package com.workday.autoparse.xml.demo; import com.workday.autoparse.xml.context.XmlParserSettings; import com.workday.autoparse.xml.context.XmlParserSettingsBuilder; import com.workday.autoparse.xml.demo.duplicatepartition.DuplicatePartitionedModel; import com.workday.autoparse.xml.demo.partition.PartitionedModel; import com.workday.autoparse.xml.parser.ParseException; import com.workday.autoparse.xml.parser.UnexpectedChildException; import com.workday.autoparse.xml.parser.UnknownElementException; import com.workday.autoparse.xml.parser.XmlStreamParser; import com.workday.autoparse.xml.parser.XmlStreamParserFactory; import com.workday.autoparse.xml.utils.StringTransformer; import org.apache.commons.lang3.StringUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import java.io.BufferedInputStream; import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author nathan.taylor * @since 2013-9-20-14:42 */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class XmlParserTest { static final double DOUBLE_E = 1E-6; static final float FLOAT_E = (float) 1E-6; @Test public void testParse() throws UnknownElementException, ParseException, UnexpectedChildException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("input.xml"); DemoModel model = (DemoModel) parser.parseStream(in); assertTrue(model.myBoxedBoolean); assertTrue(model.myPrimitiveBoolean); assertEquals(new BigDecimal(0.5), model.myBigDecimal); assertEquals(BigInteger.ONE, model.myBigInteger); assertEquals(2, model.myPrimitiveByte); assertEquals(Byte.valueOf((byte) 4), model.myBoxedByte); assertEquals('a', model.myPrimitiveChar); assertEquals(Character.valueOf('b'), model.myBoxedChar); assertEquals(5.5, model.myPrimitiveDouble, DOUBLE_E); assertEquals(Double.valueOf(6.5), model.myBoxedDouble); assertEquals(7.5f, model.myPrimitiveFloat, FLOAT_E); assertEquals(Float.valueOf(8.5f), model.myBoxedFloat); assertEquals(9, model.myPrimitiveInt); assertEquals(Integer.valueOf(10), model.myBoxedInt); assertEquals(11, model.myPrimitiveLong); assertEquals(Long.valueOf(12), model.myBoxedLong); assertEquals(13, model.myPrimitiveShort); assertEquals(Short.valueOf((short) 15), model.myBoxedShort); assertEquals("Bob", model.myString); assertTrue(model.myChildModel != null); assertEquals("My_String_Value", model.myChildModel.myString); assertEquals(5, model.myChildModel.myInt); assertEquals(3, model.repeatedChildModels.size()); assertEquals("a", model.repeatedChildModels.get(0).value); assertEquals("I am some text.", model.repeatedChildModels.get(0).textContent); assertEquals("b", model.repeatedChildModels.get(1).value); assertNull(model.repeatedChildModels.get(1).textContent); assertEquals("c", model.repeatedChildModels.get(2).value); } @Test public void testAlternateAttributes() throws ParseException, UnexpectedChildException, UnknownElementException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("alternate-attribute-input.xml"); RootModel root = (RootModel) parser.parseStream(in); assertEquals(4, root.children.size()); assertEquals(1, ((AlternateAttributeModel) root.children.get(0)).anInt); assertEquals(2, ((AlternateAttributeModel) root.children.get(1)).anInt); assertEquals(3, ((AlternateAttributeModel) root.children.get(2)).anInt); assertEquals(2, ((AlternateAttributeModel) root.children.get(3)).anInt); } @Test public void testSetters() throws ParseException, UnexpectedChildException, UnknownElementException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("setter-input.xml"); SetterModel setterModel = (SetterModel) parser.parseStream(in); assertEquals(5, setterModel.anInt); assertNotNull(setterModel.child); assertEquals(2, setterModel.repeatedChildren.size()); // Pull autoparse includes newlines and whitespace, so get rid of it here. assertEquals("Hello", StringUtils.trim(StringUtils.replace(setterModel.textContent, "\n", " "))); } @Test public void testOtherPackage() throws ParseException, UnexpectedChildException, UnknownElementException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("other-package-input.xml"); ThisPackageModel root = (ThisPackageModel) parser.parseStream(in); assertNotNull(root.otherPackageModel); } @Test public void testPostParse() throws ParseException, UnexpectedChildException, UnknownElementException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("post-parse-input.xml"); PostParseModel model = (PostParseModel) parser.parseStream(in); assertTrue(model.postParseCalled); } @Test public void testIgnoringUnknownElementsDoesNotThrowException() throws ParseException, UnexpectedChildException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.IGNORE) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unknown-elements-input.xml"); RootModel rootModel = null; try { rootModel = (RootModel) parser.parseStream(in); } catch (UnknownElementException e) { fail(String.format("Got an %s: %s", e.getClass().getSimpleName(), e)); } assertEquals(1, rootModel.children.size()); } @Test public void testUnknownElementThrowsException() throws ParseException, UnexpectedChildException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.ERROR) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unknown-elements-input.xml"); try { parser.parseStream(in); fail(String.format("Expected an %s.", UnknownElementException.class.getSimpleName())); } catch (UnknownElementException e) { assertTrue(e.getMessage(), e.getMessage().contains("Unknown_Model")); } } @Test public void testIgnoringUnexpectedChildDoesNotThrowException() throws ParseException, UnknownElementException { XmlParserSettings settings = new XmlParserSettingsBuilder().ignoreUnexpectedChildren(true).build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unexpected-child-input.xml"); ChildModel model = null; try { model = (ChildModel) parser.parseStream(in); } catch (UnexpectedChildException e) { fail(String.format("Got an %s: %s", e.getClass().getSimpleName(), e.getMessage())); } assertEquals(1, model.myInt); } @Test public void testUnexpectedChildThrowsException() throws UnknownElementException, ParseException { XmlParserSettings settings = new XmlParserSettingsBuilder().ignoreUnexpectedChildren(false).build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unexpected-child-input.xml"); try { parser.parseStream(in); fail(String.format("Expected an %s.", UnexpectedChildException.class.getSimpleName())); } catch (UnexpectedChildException e) { assertTrue(e.getMessage(), e.getMessage().contains(RootModel.class.getCanonicalName())); } } @Test public void testUnknownElementCreatesUnknownModel() throws ParseException, UnexpectedChildException, UnknownElementException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.PARSE) .withUnknownElementClass(UnknownModel.class) .ignoreUnexpectedChildren(false) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unknown-elements-input.xml"); RootModel rootModel = (RootModel) parser.parseStream(in); assertEquals(3, rootModel.children.size()); UnknownModel child0 = (UnknownModel) rootModel.children.get(0); assertEquals(2, child0.children.size()); assertTrue("child0.children.get(0) instanceof UnknownModel", child0.children.get(0) instanceof UnknownModel); assertTrue("child0.children.get(1) instanceof ChildModel", child0.children.get(1) instanceof ChildModel); assertTrue("rootModel.children.get(1) instanceof UnknownModel", rootModel.children.get(1) instanceof UnknownModel); assertTrue("rootModel.children.get(2) instanceof ChildModel", rootModel.children.get(2) instanceof ChildModel); } @Test public void testStringFilters() throws ParseException, UnexpectedChildException, UnknownElementException { StringTransformer newLineFilter = new StringTransformer() { @Override public String transform(String input) { return input.replace(" ", "\n"); } }; StringTransformer hFilter = new StringTransformer() { @Override public String transform(String input) { return input.replace('H', 'J'); } }; XmlParserSettings settings = new XmlParserSettingsBuilder().addFilter(newLineFilter).addFilter(hFilter).build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("unfiltered-input.xml"); RepeatedChildModel model = (RepeatedChildModel) parser.parseStream(in); String expected = "Jello\nJello\nJello"; assertEquals(expected, model.value); assertEquals(expected, model.textContent); } @Test public void testMissingAttributesAreNotSet() throws ParseException, UnexpectedChildException, UnknownElementException { XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(); InputStream in = getInputStreamOf("missing-attributes.xml"); DemoModel model = (DemoModel) parser.parseStream(in); assertTrue(model.myBoxedBoolean); assertTrue(model.myPrimitiveBoolean); assertEquals(BigDecimal.ONE, model.myBigDecimal); assertEquals(BigInteger.TEN, model.myBigInteger); assertEquals(-1, model.myPrimitiveByte); assertEquals(Byte.valueOf((byte) -1), model.myBoxedByte); assertEquals('a', model.myPrimitiveChar); assertEquals(Character.valueOf('a'), model.myBoxedChar); assertEquals(-1.0, model.myPrimitiveDouble, DOUBLE_E); assertEquals(Double.valueOf(-1.0), model.myBoxedDouble); assertEquals(-1f, model.myPrimitiveFloat, FLOAT_E); assertEquals(Float.valueOf(-1f), model.myBoxedFloat); assertEquals(-1, model.myPrimitiveInt); assertEquals(Integer.valueOf(-1), model.myBoxedInt); assertEquals(-1, model.myPrimitiveLong); assertEquals(Long.valueOf(-1), model.myBoxedLong); assertEquals(-1, model.myPrimitiveShort); assertEquals(Short.valueOf((short) -1), model.myBoxedShort); assertEquals("default", model.myString); assertEquals("default", model.myTextContent); } @Test public void testPartitionedPackageModelNotFoundWhenNotIncluded() throws ParseException, UnexpectedChildException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.ERROR) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("partitioned-model.xml"); boolean exceptionCaught = false; try { parser.parseStream(in); } catch (UnknownElementException ignored) { exceptionCaught = true; } assertTrue("exception caught", exceptionCaught); } @Test public void testPartitionedPackageModelFoundWhenIncluded() throws ParseException, UnexpectedChildException, UnknownElementException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.ERROR) .withPartitions(PartitionedModel.class.getPackage() .getName()) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("partitioned-model.xml"); PartitionedModel partitionedModel = (PartitionedModel) parser.parseStream(in); assertEquals("a string", partitionedModel.string); } @Test public void testDefaultNotFoundWhenNotIncluded() throws ParseException, UnexpectedChildException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.ERROR) .withPartitions(PartitionedModel.class.getPackage() .getName()) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("input.xml"); boolean exceptionCaught = false; try { parser.parseStream(in); } catch (UnknownElementException ignored) { exceptionCaught = true; } assertTrue("exception caught", exceptionCaught); } @Test public void testMultiplePackages() throws ParseException, UnexpectedChildException, UnknownElementException { XmlParserSettings settings = new XmlParserSettingsBuilder().withUnknownElementHandling(XmlParserSettings .UnknownElementHandling.PARSE) .withUnknownElementClass(UnknownModel.class) .withPartitions(PartitionedModel.class.getPackage() .getName(), XmlParserSettingsBuilder .DEFAULT_PACKAGE) .build(); XmlStreamParser parser = XmlStreamParserFactory.newXmlStreamParser(settings); InputStream in = getInputStreamOf("multiple-partitions.xml"); RootModel rootModel = (RootModel) parser.parseStream(in); assertEquals(3, rootModel.children.size()); assertTrue(rootModel.children.get(0) instanceof ThisPackageModel); assertNotNull(((ThisPackageModel) rootModel.children.get(0)).otherPackageModel); assertTrue(rootModel.children.get(1) instanceof PartitionedModel); assertTrue(rootModel.children.get(2) instanceof UnknownModel); } @Test public void testDuplicateMappingInSeparateRootPackagesThrowsException() { XmlParserSettings settings = new XmlParserSettingsBuilder().withPartitions(PartitionedModel.class.getPackage() .getName(), DuplicatePartitionedModel.class .getPackage().getName()) .build(); boolean exceptionCaught = false; try { XmlStreamParserFactory.newXmlStreamParser(settings); } catch (IllegalArgumentException e) { exceptionCaught = true; } assertTrue("Exception caught.", exceptionCaught); } private InputStream getInputStreamOf(String fileName) { return new BufferedInputStream(XmlParserTest.class.getResourceAsStream(fileName)); } }