Skip to content

Commit

Permalink
Dependency updates & ChainedMarshaller added (#8)
Browse files Browse the repository at this point in the history
* Dependency updates & ChainedUnmarshaller added
  • Loading branch information
julian-eggers committed Jun 19, 2018
1 parent b38e7e3 commit 9814826
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ pipeline
}
}
}
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Spring XML Unmarshalling with [XOM](http://www.xom.nu/)
<dependency>
<groupId>com.itelg.spring</groupId>
<artifactId>spring-xom-unmarshaller</artifactId>
<version>1.0.0-RELEASE</version>
<version>1.0.1-RELEASE</version>
</dependency>
```

Expand Down
21 changes: 11 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<name>spring-xom-unmarshaller</name>
<description>Spring XML Unmarshalling with XOM</description>
<url>https://github.com/julian-eggers/spring-xom-unmarshaller</url>
<version>1.0.0-RELEASE</version>
<version>1.0.1-RELEASE</version>

<properties>
<!-- System -->
Expand All @@ -14,19 +14,19 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<!-- Testing -->
<jacoco.version>0.8.0</jacoco.version>
<jacoco.version>0.8.1</jacoco.version>
<powermock.version>1.7.3</powermock.version>
<easymock.version>3.5.1</easymock.version>
<easymock.version>3.6</easymock.version>
<!-- Build -->
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version>
<maven-javadoc-plugin.version>3.0.1</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
<maven-surefire-plugin.version>2.20.1</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>2.20.1</maven-failsafe-plugin.version>
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
<coveralls.version>4.3.0</coveralls.version>
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
<maven-scm-provider-gitexe.version>1.9.5</maven-scm-provider-gitexe.version>
<maven-scm-provider-gitexe.version>1.10.0</maven-scm-provider-gitexe.version>
<github-release-plugin.version>1.2.0</github-release-plugin.version>
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
</properties>
Expand All @@ -36,19 +36,20 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
<version>2.0.3.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>5.0.4.RELEASE</version>
<version>5.0.7.RELEASE</version>
</dependency>

<!-- Other -->
<dependency>
<groupId>com.itelg</groupId>
<artifactId>xpath-helper</artifactId>
<version>0.4.7-RELEASE</version>
<version>0.5.0-RELEASE</version>
</dependency>

<!-- Testing -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;

import com.itelg.spring.xom.unmarshaller.parser.Parser;
import com.itelg.spring.xom.unmarshaller.parser.ParserAnalyzer;
Expand All @@ -26,6 +27,8 @@ public class XomUnmarshaller implements Unmarshaller

public XomUnmarshaller(List<Parser<?>> parsers)
{
Assert.notEmpty(parsers, "'parsers' must not be empty");

for (Parser<?> parser : parsers)
{
this.parsers.add(ParserAnalyzer.analyze(parser));
Expand Down Expand Up @@ -63,7 +66,7 @@ public Object unmarshal(Source source) throws IOException, XmlMappingException
}
catch (Exception e)
{
throw new UnmarshallingFailureException(e.getMessage(), e);
throw new UnmarshallingFailureException("Could not unmarshal", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.itelg.spring.xom.unmarshaller.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;

public class ChainedUnmarshaller implements Unmarshaller
{
private List<Unmarshaller> unmarshallers;

public ChainedUnmarshaller(List<Unmarshaller> unmarshallers)
{
Assert.notEmpty(unmarshallers, "'unmarshallers' must not be empty");
this.unmarshallers = unmarshallers;
}

@Override
public boolean supports(Class<?> clazz)
{
for (Unmarshaller unmarshaller : unmarshallers)
{
if (unmarshaller.supports(clazz))
{
return true;
}
}

return false;
}

@Override
public Object unmarshal(Source source) throws IOException, XmlMappingException
{
List<String> errors = new ArrayList<>();
byte[] byteSource = toByteArray(source);

for (Unmarshaller unmarshaller : unmarshallers)
{
try (InputStream inputStream = new ByteArrayInputStream(byteSource))
{
return unmarshaller.unmarshal(new StreamSource(inputStream));
}
catch (RuntimeException e)
{
errors.add(e.getMessage());
}
}

throw new UnmarshallingFailureException("Could not unmarshal (Errors: " + StringUtils.join(errors, ",") + ")");
}

private static byte[] toByteArray(Source source) throws IOException
{
StreamSource streamSource = (StreamSource) source;

try (InputStream inputStream = streamSource.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream())
{
IOUtils.copy(inputStream, outputStream);
return outputStream.toByteArray();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.transform.stream.StreamSource;
Expand Down Expand Up @@ -48,6 +49,34 @@ public void init()
unmarshaller = new XomUnmarshaller(parsers);
}

@Test
public void testConstructorWithNullList()
{
try
{
new XomUnmarshaller(null);
fail("exception expected");
}
catch (IllegalArgumentException e)
{
assertEquals("'parsers' must not be empty", e.getMessage());
}
}

@Test
public void testConstructorWithEmptyList()
{
try
{
new XomUnmarshaller(Collections.emptyList());
fail("exception expected");
}
catch (IllegalArgumentException e)
{
assertEquals("'parsers' must not be empty", e.getMessage());
}
}

@Test
public void testSupports()
{
Expand Down Expand Up @@ -85,7 +114,7 @@ public void testUnmarshallWithUnknownException() throws IOException
catch (Exception e)
{
assertEquals(UnmarshallingFailureException.class, e.getClass());
assertEquals("XML document structures must start and end within the same entity.; nested exception is nu.xom.ParsingException: XML document structures must start and end within the same entity. at line 1, column 7", e.getMessage());
assertEquals("Could not unmarshal; nested exception is nu.xom.ParsingException: XML document structures must start and end within the same entity. at line 1, column 7", e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.itelg.spring.xom.unmarshaller.utils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.junit.Test;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.UnmarshallingFailureException;
import org.springframework.oxm.XmlMappingException;

import com.itelg.spring.xom.unmarshaller.XomUnmarshaller;
import com.itelg.spring.xom.unmarshaller.parser.Parser;
import com.itelg.xpath.helper.XPathHelper;

import nu.xom.Element;

public class ChainedUnmarshallerTest
{
private Unmarshaller stringIntegerUnmarshaller = new ChainedUnmarshaller(Arrays.asList(new StringUnmarshaller(), new IntegerUnmarshaller()));

private Unmarshaller integerStringUnmarshaller = new ChainedUnmarshaller(Arrays.asList(new IntegerUnmarshaller(), new StringUnmarshaller()));

private String stringXml = "<String><value>abc</value></String>";

private String integerXml = "<Integer><value>123</value></Integer>";

@Test
public void testConstructorWithNullList()
{
try
{
new ChainedUnmarshaller(null);
fail("exception expected");
}
catch (IllegalArgumentException e)
{
assertEquals("'unmarshallers' must not be empty", e.getMessage());
}
}

@Test
public void testConstructorWithEmptyList()
{
try
{
new ChainedUnmarshaller(Collections.emptyList());
fail("exception expected");
}
catch (IllegalArgumentException e)
{
assertEquals("'unmarshallers' must not be empty", e.getMessage());
}
}

@Test
public void testSupports()
{
assertFalse(stringIntegerUnmarshaller.supports(Double.class));
assertTrue(stringIntegerUnmarshaller.supports(String.class));
assertTrue(stringIntegerUnmarshaller.supports(Integer.class));

assertFalse(integerStringUnmarshaller.supports(Double.class));
assertTrue(integerStringUnmarshaller.supports(String.class));
assertTrue(integerStringUnmarshaller.supports(Integer.class));
}

@Test
public void testUnmarshal() throws XmlMappingException, IOException
{
assertEquals("abc", stringIntegerUnmarshaller.unmarshal(createSource(stringXml)));
assertEquals("abc", integerStringUnmarshaller.unmarshal(createSource(stringXml)));
assertEquals(Integer.valueOf(123), stringIntegerUnmarshaller.unmarshal(createSource(integerXml)));
assertEquals(Integer.valueOf(123), integerStringUnmarshaller.unmarshal(createSource(integerXml)));
}

@Test
public void testUnmarshalWithException() throws XmlMappingException, IOException
{
try
{
stringIntegerUnmarshaller.unmarshal(createSource("123"));
fail("exception expected");
}
catch (UnmarshallingFailureException e)
{
assertEquals("Could not unmarshal (Errors: Could not unmarshal; nested exception is nu.xom.ParsingException: Content is not allowed in prolog. at line 1, column 1,Could not unmarshal; nested exception is nu.xom.ParsingException: Content is not allowed in prolog. at line 1, column 1)", e.getMessage());
}
}

private static Source createSource(String xml)
{
return new StreamSource(new ByteArrayInputStream(xml.getBytes()));
}

private static class StringUnmarshaller extends XomUnmarshaller
{
public StringUnmarshaller()
{
super(Collections.singletonList(new StringParser()));
}
}

private static class StringParser implements Parser<String>
{
@Override
public String parse(Element rootElement)
{
return XPathHelper.getString("value", rootElement);
}
}

private static class IntegerUnmarshaller extends XomUnmarshaller
{
public IntegerUnmarshaller()
{
super(Collections.singletonList(new IntegerParser()));
}
}

private static class IntegerParser implements Parser<Integer>
{
@Override
public Integer parse(Element rootElement)
{
return XPathHelper.getInteger("value", rootElement);
}
}
}

0 comments on commit 9814826

Please sign in to comment.