Skip to content

Commit 9e6931b

Browse files
Dennis Labordusdlabordus
Dennis Labordus
authored andcommitted
Added Generic JAXb Element Converter + Validation Exception.
Signed-off-by: Dennis Labordus <[email protected]>
1 parent 9563d5c commit 9e6931b

File tree

9 files changed

+252
-9
lines changed

9 files changed

+252
-9
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-FileCopyrightText: 2021 Alliander N.V.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
package org.lfenergy.compas.core.commons;
5+
6+
import org.lfenergy.compas.core.commons.exception.CompasException;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.w3c.dom.Element;
10+
import org.xml.sax.InputSource;
11+
import org.xml.sax.SAXException;
12+
13+
import javax.xml.XMLConstants;
14+
import javax.xml.parsers.DocumentBuilderFactory;
15+
import javax.xml.parsers.ParserConfigurationException;
16+
import javax.xml.transform.OutputKeys;
17+
import javax.xml.transform.TransformerException;
18+
import javax.xml.transform.TransformerFactory;
19+
import javax.xml.transform.dom.DOMSource;
20+
import javax.xml.transform.stream.StreamResult;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.io.StringReader;
24+
import java.io.StringWriter;
25+
26+
import static org.lfenergy.compas.core.commons.exception.CompasErrorCode.CONVERT_TO_ELEMENT_ERROR;
27+
import static org.lfenergy.compas.core.commons.exception.CompasErrorCode.CONVERT_TO_STRING_ERROR;
28+
29+
public class ElementConverter {
30+
private static final Logger LOGGER = LoggerFactory.getLogger(ElementConverter.class);
31+
32+
public String convertToString(Element element) {
33+
return convertToString(element, true);
34+
}
35+
36+
public String convertToString(Element element, boolean omitXmlDeclaration) {
37+
try {
38+
var buffer = new StringWriter();
39+
var factory = TransformerFactory.newInstance();
40+
// Prohibit the use of all protocols by external entities:
41+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
42+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
43+
var transformer = factory.newTransformer();
44+
if (omitXmlDeclaration) {
45+
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
46+
}
47+
48+
transformer.transform(new DOMSource(element), new StreamResult(buffer));
49+
return buffer.toString();
50+
} catch (TransformerException exp) {
51+
LOGGER.error("Converting problem: {}", exp.getLocalizedMessage(), exp);
52+
throw new CompasException(CONVERT_TO_STRING_ERROR, "Error converting to a String!");
53+
}
54+
}
55+
56+
public Element convertToElement(String xml, String rootElementName, String rootElementNS) {
57+
return convertToElement(new InputSource(new StringReader(xml)), rootElementName, rootElementNS);
58+
}
59+
60+
public Element convertToElement(InputStream xml, String rootElementName, String rootElementNS) {
61+
return convertToElement(new InputSource(xml), rootElementName, rootElementNS);
62+
}
63+
64+
private Element convertToElement(InputSource inputSource, String rootElementName, String rootElementNS) {
65+
try {
66+
var factory = DocumentBuilderFactory.newInstance();
67+
factory.setNamespaceAware(true);
68+
factory.setIgnoringElementContentWhitespace(true);
69+
// Prohibit the use of all protocols by external entities:
70+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
71+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
72+
// Create DocumentBuilder with default configuration
73+
var builder = factory.newDocumentBuilder();
74+
75+
// Parse the content to Document object
76+
var doc = builder.parse(inputSource);
77+
return (Element) doc.getElementsByTagNameNS(rootElementNS, rootElementName).item(0);
78+
} catch (ParserConfigurationException | SAXException | IOException exp) {
79+
LOGGER.error("Converting problem: {}", exp.getLocalizedMessage(), exp);
80+
throw new CompasException(CONVERT_TO_ELEMENT_ERROR, "Error converting to a Element!");
81+
}
82+
}
83+
}

commons/src/main/java/org/lfenergy/compas/core/commons/Resources.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ public class Resources {
1616
}
1717

1818
public static Optional<URL> getResource(String resourceName) {
19-
ClassLoader loader = getClassLoader();
20-
URL url = loader.getResource(resourceName);
19+
var loader = getClassLoader();
20+
var url = loader.getResource(resourceName);
2121
return Optional.ofNullable(url);
2222
}
2323

commons/src/main/java/org/lfenergy/compas/core/commons/exception/CompasErrorCode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,7 @@ public class CompasErrorCode {
1616
public static final String UNMARSHAL_ERROR_CODE = "CORE-0006";
1717
public static final String MARSHAL_ERROR_CODE = "CORE-0007";
1818
public static final String INVALID_YML_ERROR_CODE = "CORE-0008";
19+
20+
public static final String CONVERT_TO_STRING_ERROR = "CORE-1000";
21+
public static final String CONVERT_TO_ELEMENT_ERROR = "CORE-1001";
1922
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-FileCopyrightText: 2021 Alliander N.V.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
package org.lfenergy.compas.core.commons.exception;
5+
6+
public class CompasValidationException extends CompasException {
7+
public CompasValidationException(String errorCode, String msg) {
8+
super(errorCode, msg);
9+
}
10+
11+
public CompasValidationException(String errorCode, String msg, Throwable throwable) {
12+
super(errorCode, msg, throwable);
13+
}
14+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-FileCopyrightText: 2021 Alliander N.V.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
package org.lfenergy.compas.core.commons;
5+
6+
import org.junit.jupiter.api.Test;
7+
import org.lfenergy.compas.core.commons.exception.CompasException;
8+
import org.w3c.dom.Element;
9+
10+
import javax.xml.parsers.DocumentBuilderFactory;
11+
import javax.xml.parsers.ParserConfigurationException;
12+
import java.io.ByteArrayInputStream;
13+
import java.nio.charset.StandardCharsets;
14+
15+
import static org.junit.jupiter.api.Assertions.*;
16+
import static org.lfenergy.compas.core.commons.exception.CompasErrorCode.CONVERT_TO_ELEMENT_ERROR;
17+
18+
class ElementConverterTest {
19+
private static final String SIMPLE_SCL_NS = "http://www.iec.ch/61850/2003/SCL";
20+
private static final String SIMPLE_SCL_XML =
21+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
22+
"<SCL xmlns=\"" + SIMPLE_SCL_NS + "\" version=\"2007\" revision=\"B\" release=\"4\">" +
23+
"</SCL>";
24+
25+
private ElementConverter converter = new ElementConverter();
26+
27+
@Test
28+
void convertToString_WhenCalledWithXMLElementWithoutDeclaration_ThenElementConvertedToAString() throws ParserConfigurationException {
29+
var element = createSimpleElement();
30+
31+
var result = converter.convertToString(element);
32+
33+
assertEquals("<root primary=\"true\"/>", result);
34+
}
35+
36+
@Test
37+
void convertToString_WhenCalledWithXMLElementWithDeclaration_ThenElementConvertedToAStringWithDeclaration() throws ParserConfigurationException {
38+
var element = createSimpleElement();
39+
40+
var result = converter.convertToString(element, false);
41+
42+
assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
43+
"<root primary=\"true\"/>", result);
44+
}
45+
46+
@Test
47+
void convertToElement_WhenCalledWithSclXmlAsString_ThenConvertedToXMLElement() {
48+
var element = converter.convertToElement(SIMPLE_SCL_XML, "SCL", SIMPLE_SCL_NS);
49+
50+
assertNotNull(element);
51+
assertEquals("SCL", element.getLocalName());
52+
assertTrue(element.hasAttribute("version"));
53+
assertEquals("2007", element.getAttribute("version"));
54+
}
55+
56+
@Test
57+
void convertToElement_WhenCalledWithSclXmlAsStream_ThenConvertedToXMLElement() {
58+
var element = converter.convertToElement(
59+
new ByteArrayInputStream(SIMPLE_SCL_XML.getBytes(StandardCharsets.UTF_8))
60+
, "SCL", SIMPLE_SCL_NS);
61+
62+
assertNotNull(element);
63+
assertEquals("SCL", element.getLocalName());
64+
assertTrue(element.hasAttribute("version"));
65+
assertEquals("2007", element.getAttribute("version"));
66+
}
67+
68+
@Test
69+
void convertToElement_WhenCalledWithUnknownRootElement_ThenNullReturnedBecauseNoRootElement() {
70+
var randomXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
71+
"<root primary=\"true\"/>";
72+
73+
var element = converter.convertToElement(randomXml, "SCL", SIMPLE_SCL_NS);
74+
75+
assertNull(element);
76+
}
77+
78+
@Test
79+
void convertToElement_WhenCalledWithInvalidXML_ThenExceptionThrown() {
80+
var invalidXml = "<root></invalid>";
81+
82+
var exception = assertThrows(CompasException.class, () -> {
83+
converter.convertToElement(invalidXml, "SCL", SIMPLE_SCL_NS);
84+
});
85+
assertEquals(CONVERT_TO_ELEMENT_ERROR, exception.getErrorCode());
86+
}
87+
88+
private Element createSimpleElement() throws ParserConfigurationException {
89+
var dbf = DocumentBuilderFactory.newInstance();
90+
var builder = dbf.newDocumentBuilder();
91+
var doc = builder.newDocument();
92+
93+
// create the root element node
94+
var element = doc.createElement("root");
95+
element.setAttribute("primary", "true");
96+
doc.appendChild(element);
97+
98+
return element;
99+
}
100+
}

commons/src/test/java/org/lfenergy/compas/core/commons/MarshallerWrapperTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ void marshaller_WhenInitializedWithInvalidXsdPath_ThenExceptionIsThrown() {
8181
}
8282

8383
private XmlElementAPojo createPOJO() {
84-
XmlElementAPojo aPojo = new XmlElementAPojo();
84+
var aPojo = new XmlElementAPojo();
8585
aPojo.setId(UUID.randomUUID().toString());
8686

87-
XmlElementBPojo bPojo = new XmlElementBPojo();
87+
var bPojo = new XmlElementBPojo();
8888
bPojo.setId(UUID.randomUUID().toString());
8989
bPojo.setName("SOMENAME");
9090
aPojo.setOther(bPojo);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.lfenergy.compas.core.commons.exception;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
7+
class CompasErrorCodeTest {
8+
@Test
9+
void constructor_WhenConstructorCalled_ThenShouldThrowExceptionCauseForbidden() {
10+
assertThrows(UnsupportedOperationException.class, CompasErrorCode::new);
11+
}
12+
}

commons/src/test/java/org/lfenergy/compas/core/commons/exception/CompasExceptionTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
class CompasExceptionTest {
1212
@Test
1313
void constructor_WhenCalledWithOnlyMessage_ThenMessageCanBeRetrieved() {
14-
String expectedMessage = "The message";
15-
CompasException exception = new CompasException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage);
14+
var expectedMessage = "The message";
15+
var exception = new CompasException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage);
1616

1717
assertEquals(NO_CLASS_LOADER_ERROR_CODE, exception.getErrorCode());
1818
assertEquals(expectedMessage, exception.getMessage());
1919
}
2020

2121
@Test
2222
void constructor_WhenCalledWithMessageAndThrowable_ThenMessageAndThrowableCanBeRetrieved() {
23-
String expectedMessage = "The message";
24-
Throwable expectedThrowable = new NullPointerException();
25-
CompasException exception = new CompasException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage, expectedThrowable);
23+
var expectedMessage = "The message";
24+
var expectedThrowable = new NullPointerException();
25+
var exception = new CompasException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage, expectedThrowable);
2626

2727
assertEquals(NO_CLASS_LOADER_ERROR_CODE, exception.getErrorCode());
2828
assertEquals(expectedMessage, exception.getMessage());
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-FileCopyrightText: 2021 Alliander N.V.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
package org.lfenergy.compas.core.commons.exception;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.lfenergy.compas.core.commons.exception.CompasErrorCode.NO_CLASS_LOADER_ERROR_CODE;
10+
11+
class CompasValidationExceptionTest {
12+
@Test
13+
void constructor_WhenCalledWithOnlyMessage_ThenMessageCanBeRetrieved() {
14+
var expectedMessage = "The message";
15+
var exception = new CompasValidationException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage);
16+
17+
assertEquals(NO_CLASS_LOADER_ERROR_CODE, exception.getErrorCode());
18+
assertEquals(expectedMessage, exception.getMessage());
19+
}
20+
21+
@Test
22+
void constructor_WhenCalledWithMessageAndThrowable_ThenMessageAndThrowableCanBeRetrieved() {
23+
var expectedMessage = "The message";
24+
var expectedThrowable = new NullPointerException();
25+
var exception = new CompasValidationException(NO_CLASS_LOADER_ERROR_CODE, expectedMessage, expectedThrowable);
26+
27+
assertEquals(NO_CLASS_LOADER_ERROR_CODE, exception.getErrorCode());
28+
assertEquals(expectedMessage, exception.getMessage());
29+
assertEquals(expectedThrowable, exception.getCause());
30+
}
31+
}

0 commit comments

Comments
 (0)