Skip to content

Commit deda74a

Browse files
authored
feat: add xml<-> json transformations with streams (#308)
1 parent 42b9db2 commit deda74a

File tree

7 files changed

+383
-130
lines changed

7 files changed

+383
-130
lines changed

pom.xml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>fr.insee.lunatic</groupId>
77
<artifactId>lunatic-model</artifactId>
8-
<version>2.7.2</version>
8+
<version>2.7.3</version>
99
<packaging>jar</packaging>
1010

1111
<name>Lunatic Model</name>
@@ -56,6 +56,7 @@
5656
</repository>
5757
</distributionManagement>
5858

59+
5960
<dependencies>
6061
<dependency>
6162
<groupId>org.eclipse.persistence</groupId>
@@ -80,11 +81,6 @@
8081
<artifactId>javax.json-api</artifactId>
8182
<version>1.1.4</version>
8283
</dependency>
83-
<dependency>
84-
<groupId>org.glassfish</groupId>
85-
<artifactId>javax.json</artifactId>
86-
<version>1.1.4</version>
87-
</dependency>
8884

8985
<dependency>
9086
<groupId>commons-io</groupId>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package fr.insee.lunatic.conversion;
2+
3+
/**
4+
* Exception indicating a failure during a data format conversion
5+
* (e.g., JSON ⇄ XML) in the Lunatic context.
6+
*/
7+
public class ConversionException extends Exception {
8+
9+
/**
10+
* Constructs a new ConversionException with the specified detail message.
11+
*
12+
* @param message the detail message
13+
*/
14+
public ConversionException(String message) {
15+
super(message);
16+
}
17+
18+
/**
19+
* Constructs a new ConversionException with the specified cause.
20+
*
21+
* @param cause the cause of the exception
22+
*/
23+
public ConversionException(Throwable cause) {
24+
super(cause);
25+
}
26+
27+
/**
28+
* Constructs a new ConversionException with the specified detail message and cause.
29+
*
30+
* @param message the detail message
31+
* @param cause the underlying cause of the exception
32+
*/
33+
public ConversionException(String message, Throwable cause) {
34+
super(message, cause);
35+
}
36+
}

src/main/java/fr/insee/lunatic/conversion/data/JSONLunaticDataToXML.java

Lines changed: 64 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package fr.insee.lunatic.conversion.data;
22

3-
import java.io.ByteArrayInputStream;
4-
import java.io.File;
5-
import java.io.InputStream;
6-
import java.io.OutputStream;
3+
import java.io.*;
74
import java.nio.charset.StandardCharsets;
85
import java.nio.file.Files;
96

7+
import fr.insee.lunatic.conversion.ConversionException;
108
import org.apache.commons.io.FileUtils;
119
import org.slf4j.Logger;
1210
import org.slf4j.LoggerFactory;
@@ -21,71 +19,90 @@
2119
*
2220
*/
2321
public class JSONLunaticDataToXML {
24-
25-
private static XslTransformation saxonService = new XslTransformation();
26-
22+
private static final XslTransformation saxonService = new XslTransformation();
2723
private static final Logger logger = LoggerFactory.getLogger(JSONLunaticDataToXML.class);
2824

29-
public File transform(File input) throws Exception {
30-
25+
/**
26+
*
27+
* @param jsonInputFile json file in lunatic format
28+
* @return xml file in lunatic format
29+
* @throws ConversionException exception occurring during conversion
30+
*/
31+
public File transform(File jsonInputFile) throws Exception {
3132
File outputFile = Files.createTempFile("json2xml", ".xml").toFile();
32-
33-
34-
logger.debug("Output folder : " + outputFile.getAbsolutePath());
35-
36-
String jsonString = FileUtils.readFileToString(input, StandardCharsets.UTF_8);
37-
InputStream inputStream = new ByteArrayInputStream(wrapJsonWithXml(jsonString).getBytes(StandardCharsets.UTF_8));
38-
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
39-
40-
InputStream XSL = XMLLunaticDataToJSON.class.getClassLoader()
41-
.getResourceAsStream(Constants.DATA_TRANSFORMATION_JSON_2_XML);
42-
try {
43-
saxonService.transformWithSimpleXSLSheet(inputStream,outputStream, XSL);
33+
logger.debug("Output folder : {}", outputFile.getAbsolutePath());
34+
String jsonString = FileUtils.readFileToString(jsonInputFile, StandardCharsets.UTF_8);
35+
try(
36+
InputStream inputStream = new ByteArrayInputStream(wrapJsonWithXml(jsonString).getBytes(StandardCharsets.UTF_8));
37+
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
38+
InputStream xslStream = XMLLunaticDataToJSON.class.getClassLoader()
39+
.getResourceAsStream(Constants.DATA_TRANSFORMATION_JSON_2_XML)
40+
) {
41+
saxonService.transformWithSimpleXSLSheet(inputStream,outputStream, xslStream);
4442
}catch(Exception e) {
45-
String errorMessage = "An error was occured during the json to xml transformation. "+e.getMessage();
46-
logger.error(errorMessage);
47-
throw new Exception(errorMessage);
43+
throw new ConversionException("Error when converting json to xml", e);
4844
}
45+
return outputFile;
46+
}
4947

50-
inputStream.close();
51-
outputStream.close();
52-
XSL.close();
48+
/**
49+
* Transformation of a lunatic json data to a lunatic xml data
50+
*
51+
* @param jsonInputStream data in a json format input stream
52+
* @return data in a xml format
53+
* @throws Exception when exceptions occurred
54+
*/
55+
public OutputStream transform(InputStream jsonInputStream) throws Exception {
56+
try (InputStream xslStream = XMLLunaticDataToJSON.class.getClassLoader()
57+
.getResourceAsStream(Constants.DATA_TRANSFORMATION_JSON_2_XML);
58+
InputStream wrappedInput = wrapJsonStreamWithXml(jsonInputStream)) {
5359

54-
return outputFile;
60+
ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
61+
saxonService.transformWithSimpleXSLSheet(wrappedInput, xmlOutputStream, xslStream);
62+
return xmlOutputStream;
63+
} catch (Exception e) {
64+
throw new ConversionException("Error when converting json to xml", e);
65+
}
5566
}
5667

5768
public String transform(String jsonString) throws Exception {
5869

5970
File outputFile = Files.createTempFile("json2xml", ".xml").toFile();
6071

72+
logger.debug("Output folder : {}", outputFile.getAbsolutePath());
6173

62-
logger.debug("Output folder : " + outputFile.getAbsolutePath());
63-
64-
InputStream inputStream = new ByteArrayInputStream(wrapJsonWithXml(jsonString).getBytes(StandardCharsets.UTF_8));
65-
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
66-
67-
InputStream XSL = XMLLunaticDataToJSON.class.getClassLoader()
68-
.getResourceAsStream(Constants.DATA_TRANSFORMATION_JSON_2_XML);
69-
try {
70-
saxonService.transformWithSimpleXSLSheet(inputStream,outputStream, XSL);
74+
try(
75+
InputStream inputStream = new ByteArrayInputStream(wrapJsonWithXml(jsonString)
76+
.getBytes(StandardCharsets.UTF_8));
77+
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
78+
InputStream xslStream = XMLLunaticDataToJSON.class.getClassLoader()
79+
.getResourceAsStream(Constants.DATA_TRANSFORMATION_JSON_2_XML)
80+
) {
81+
saxonService.transformWithSimpleXSLSheet(inputStream,outputStream, xslStream);
7182
}catch(Exception e) {
72-
String errorMessage = "An error was occured during the json to xml transformation. "+e.getMessage();
73-
logger.error(errorMessage);
74-
throw new Exception(errorMessage);
83+
throw new ConversionException("Error when converting json to xml", e);
7584
}
76-
77-
inputStream.close();
78-
outputStream.close();
79-
XSL.close();
80-
8185
return FileUtils.readFileToString(outputFile, StandardCharsets.UTF_8);
8286
}
8387

84-
public String wrapJsonWithXml(String json) {
88+
private String wrapJsonWithXml(String json) {
8589
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Data>"+preProcessJson2XML(json)+"</Data>";
8690
}
91+
92+
/**
93+
* Wraps the content of a JSON InputStream into a valid XML structure.
94+
*
95+
* @param jsonInputStream the original JSON stream
96+
* @return a new InputStream containing the wrapped XML
97+
* @throws IOException if reading the stream fails
98+
*/
99+
private InputStream wrapJsonStreamWithXml(InputStream jsonInputStream) throws IOException {
100+
String json = new String(jsonInputStream.readAllBytes(), StandardCharsets.UTF_8);
101+
String xml = wrapJsonWithXml(json);
102+
return new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
103+
}
87104

88-
public String preProcessJson2XML(String json) {
105+
private String preProcessJson2XML(String json) {
89106
return json.replaceAll("&", "&amp;")
90107
.replaceAll("<", "&lt;")
91108
.replaceAll(">", "&gt;");
Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package fr.insee.lunatic.conversion.data;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.io.File;
45
import java.io.InputStream;
56
import java.io.OutputStream;
67
import java.nio.file.Files;
78

9+
import fr.insee.lunatic.conversion.ConversionException;
810
import org.apache.commons.io.FileUtils;
911
import org.slf4j.Logger;
1012
import org.slf4j.LoggerFactory;
@@ -16,33 +18,43 @@
1618
public class XMLLunaticDataToJSON {
1719

1820
private static XslTransformation saxonService = new XslTransformation();
19-
2021
private static final Logger logger = LoggerFactory.getLogger(XMLLunaticDataToJSON.class);
2122

2223

2324
public File transform(File input) throws Exception {
2425

2526
File outputFile = Files.createTempFile("xml2json", ".json").toFile();
2627

27-
logger.debug("Output folder : " + outputFile.getAbsolutePath());
28-
29-
InputStream inputStream = FileUtils.openInputStream(input);
30-
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
31-
32-
InputStream XSL = XMLLunaticDataToJSON.class.getClassLoader()
33-
.getResourceAsStream(Constants.DATA_TRANSFORMATION_XML_2_JSON);
34-
try {
35-
saxonService.transformXMLLunaticDataToJSON(inputStream,outputStream, XSL);
36-
}catch(Exception e) {
37-
String errorMessage = "An error was occured during the xml to json transformation. "+e.getMessage();
38-
logger.error(errorMessage);
39-
throw new Exception(errorMessage);
28+
logger.debug("Output folder : {}", outputFile.getAbsolutePath());
29+
30+
try (
31+
InputStream inputStream = FileUtils.openInputStream(input);
32+
OutputStream outputStream = FileUtils.openOutputStream(outputFile);
33+
InputStream xslStream = XMLLunaticDataToJSON.class.getClassLoader()
34+
.getResourceAsStream(Constants.DATA_TRANSFORMATION_XML_2_JSON)
35+
) {
36+
saxonService.transformXMLLunaticDataToJSON(inputStream,outputStream, xslStream);
37+
} catch(Exception e) {
38+
throw new ConversionException("Error when converting xml to json", e);
4039
}
41-
42-
inputStream.close();
43-
outputStream.close();
44-
XSL.close();
45-
4640
return outputFile;
4741
}
42+
43+
/**
44+
* Transform a xml lunatic data (InputStream) to JSON lunatic data (OutputStream) with xslt
45+
*
46+
* @param xmlInputStream xml lunatic data
47+
* @throws Exception when exception occurs
48+
*
49+
* @return the outputstream data in json format
50+
*/
51+
public OutputStream transform(InputStream xmlInputStream) throws Exception {
52+
try (InputStream xslStream = getClass().getClassLoader().getResourceAsStream(Constants.DATA_TRANSFORMATION_XML_2_JSON)) {
53+
ByteArrayOutputStream jsonOutputStream = new ByteArrayOutputStream();
54+
saxonService.transformXMLLunaticDataToJSON(xmlInputStream, jsonOutputStream, xslStream);
55+
return jsonOutputStream;
56+
} catch (Exception e) {
57+
throw new ConversionException("Error when converting xml to json", e);
58+
}
59+
}
4860
}

0 commit comments

Comments
 (0)