11package app .djk .RestPdfFormFiller .Pdf ;
22
33import app .djk .RestPdfFormFiller .projectExceptions .InvalidXfaFormDataException ;
4- import app .djk .RestPdfFormFiller .projectExceptions .InvalidXfaFormException ;
5- import com .fasterxml .jackson .core .JsonProcessingException ;
6- import com .fasterxml .jackson .databind .JsonNode ;
7- import com .fasterxml .jackson .databind .ObjectMapper ;
8- import com .fasterxml .jackson .databind .node .JsonNodeType ;
9- import com .fasterxml .jackson .dataformat .xml .XmlMapper ;
4+ import tools .jackson .databind .JsonNode ;
5+ import tools .jackson .databind .ObjectMapper ;
6+ import tools .jackson .databind .node .JsonNodeType ;
7+ import tools .jackson .dataformat .xml .XmlMapper ;
108import org .jetbrains .annotations .NotNull ;
119import org .w3c .dom .Document ;
1210
1917import java .io .StringWriter ;
2018
2119public class DataFormatter {
22- private DataFormatter () { throw new IllegalStateException ("Utility class" ); }
20+ private DataFormatter () {
21+ throw new IllegalStateException ("Utility class" );
22+ }
2323
24- public static String convertXmlToJsonString (String xml ) throws JsonProcessingException {
24+ public static String convertXmlToJsonString (String xml ) {
2525 return convertXmlToJsonNode (xml ).toPrettyString ();
2626
2727 }
2828
29- private static JsonNode convertXmlToJsonNode (String xml ) throws JsonProcessingException {
29+ private static JsonNode convertXmlToJsonNode (String xml ) {
3030 final var xmlMapper = new XmlMapper ();
3131 return xmlMapper .readTree (xml );
3232 }
3333
3434 /**
3535 * Converts a JSON representation of XFA form data to a String XML representation.
3636 * This method wraps the {@link #convertJsonToXml(String)} method.
37+ *
3738 * @param json The JSON data object.
3839 * @return The XML Document representation of the data in <code>json</code>.
3940 * @throws ParserConfigurationException If there's a problem with creating the XML document.
40- * @throws TransformerException If there's a problem with transforming the XML document into a string.
41- * @throws InvalidXfaFormDataException If a JSON object is not in the correct format for an XFA form.
41+ * @throws TransformerException If there's a problem with transforming the XML document into a string.
42+ * @throws InvalidXfaFormDataException If a JSON object is not in the correct format for an XFA form.
4243 */
4344 public static String convertJsonToXmlString (String json ) throws ParserConfigurationException , TransformerException {
4445 final var xmlDocument = convertJsonToXml (json );
@@ -57,73 +58,78 @@ public static String convertJsonToXmlString(String json) throws ParserConfigurat
5758 * Converts a JSON representation of XFA form data to its XML form.
5859 * The root XML and data elements are hard-coded because they are constant.
5960 * This method recurses through the remaining JSON elements and creates the XML elements.
61+ *
6062 * @param json The JSON data object.
6163 * @return The XML Document representation of the data in <code>json</code>.
6264 * @throws ParserConfigurationException If there's a problem with creating the XML document.
63- * @throws InvalidXfaFormDataException If a JSON object is not in the correct format for an XFA form.
65+ * @throws InvalidXfaFormDataException If a JSON object is not in the correct format for an XFA form.
6466 */
6567 public static Document convertJsonToXml (String json ) throws ParserConfigurationException {
6668 final var xmlDocument = (DocumentBuilderFactory .newInstance ()).newDocumentBuilder ().newDocument ();
6769
68- try {
69- final var rootJsonNode = (new ObjectMapper ()).readTree (json );
70+ final var rootJsonNode = (new ObjectMapper ()).readTree (json );
7071
7172
72- // Creating the root element that an XFA form expects.
73- // This element name is not expected to be in the JSON data object.
74- final var rootElement = xmlDocument .createElement ("xfa:datasets" );
75- rootElement .setAttribute ("xmlns:xfa" , "http://www.xfa.org/schema/xfa-data/1.0/" );
76- xmlDocument .appendChild (rootElement );
73+ // Creating the root element that an XFA form expects.
74+ // This element name is not expected to be in the JSON data object.
75+ final var rootElement = xmlDocument .createElement ("xfa:datasets" );
76+ rootElement .setAttribute ("xmlns:xfa" , "http://www.xfa.org/schema/xfa-data/1.0/" );
77+ xmlDocument .appendChild (rootElement );
7778
78- // The JSON data object should only have one key, "data".
79- if (rootJsonNode .getNodeType () != JsonNodeType .OBJECT || rootJsonNode .size () != 1 ) {
80- throw new InvalidXfaFormDataException ();
81- }
79+ // The JSON data object should only have one key, "data".
80+ if (rootJsonNode .getNodeType () != JsonNodeType .OBJECT || rootJsonNode .size () != 1 ) {
81+ throw new InvalidXfaFormDataException ();
82+ }
8283
83- // Hard-coding the data element because the element name that I give the JSON
84- // object is just "data". The XFA form expects the "xfa:data" element name.
85- final var dataElement = xmlDocument .createElement ("xfa:data" );
86- rootElement .appendChild (dataElement );
84+ // Hard-coding the data element because the element name that I give the JSON
85+ // object is just "data". The XFA form expects the "xfa:data" element name.
86+ final var dataElement = xmlDocument .createElement ("xfa:data" );
87+ rootElement .appendChild (dataElement );
8788
88- // The "data" key should always have a JSON object as its value.
89- final var dataNode = rootJsonNode .get ("data" );
90- if (dataNode .getNodeType () != JsonNodeType .OBJECT ) {
91- throw new InvalidXfaFormDataException ();
92- }
89+ // The "data" key should always have a JSON object as its value.
90+ final var dataNode = rootJsonNode .get ("data" );
91+ if (dataNode .getNodeType () != JsonNodeType .OBJECT ) {
92+ throw new InvalidXfaFormDataException ();
93+ }
9394
94- // Recurses through the data node and creates the XML elements.
95- // This call modifies dataElement, and by extension, xmlDocument.
96- convertJsonNodeToXmlElement (xmlDocument , dataElement , dataNode );
95+ // Recurses through the data node and creates the XML elements.
96+ // This call modifies dataElement, and by extension, xmlDocument.
97+ convertJsonNodeToXmlElement (xmlDocument , dataElement , dataNode );
9798
98- return xmlDocument ;
99- } catch (JsonProcessingException ex ) {
100- throw new InvalidXfaFormException ();
101- }
99+ return xmlDocument ;
102100 }
103101
104102 /**
105103 * Recursively converts a <code>JsonNode</code> to XML elements.
106104 * This method modifies the <code>element</code> parameter by adding child elements to it.
105+ *
107106 * @param xmlDocument The XML document to which the elements will be added.
108- * @param element The XML element to which the child elements will be added.
109- * @param jsonNode The JSON node to be converted. This should be the corresponding JSON value content
110- * for the <code>element</code> parameter.
107+ * @param element The XML element to which the child elements will be added.
108+ * @param jsonNode The JSON node to be converted. This should be the corresponding JSON value content
109+ * for the <code>element</code> parameter.
111110 */
112111 private static void convertJsonNodeToXmlElement (
113112 final @ NotNull Document xmlDocument ,
114113 @ NotNull org .w3c .dom .Element element ,
115114 @ NotNull JsonNode jsonNode ) {
116115
117116 switch (jsonNode .getNodeType ()) {
118- case OBJECT -> jsonNode .fields ().forEachRemaining (entry -> {
119- final var childElement = xmlDocument .createElement (entry .getKey ());
120- element .appendChild (childElement );
121- convertJsonNodeToXmlElement (xmlDocument , childElement , entry .getValue ());
122- });
117+ case OBJECT -> {
118+ for (final String fieldName : jsonNode .propertyNames ()) {
119+ final var childElement = xmlDocument .createElement (fieldName );
120+ element .appendChild (childElement );
121+ convertJsonNodeToXmlElement (xmlDocument , childElement , jsonNode .path (fieldName ));
122+ }
123+ }
123124 case STRING -> {
124- final var textNode = xmlDocument .createTextNode (jsonNode .asText ());
125+ // Jackson 3 deprecates textValue(); stringValue() is the non-deprecated string accessor.
126+ final var textNode = xmlDocument .createTextNode (jsonNode .stringValue ());
125127 element .appendChild (textNode );
126128 }
129+ default -> {
130+ // For now, ignore other node types (numbers, booleans, arrays, null).
131+ // If you need them, add cases and/or schema support.
132+ }
127133 }
128134 }
129135
@@ -139,7 +145,7 @@ private static void convertJsonNodeToXmlElement(
139145 * @param xml The XML data from the form.
140146 * @return A pretty-printed String of a JSON schema object representing the JSON schema version of the form schema.
141147 */
142- public static String generateJsonSchema (final String xml ) throws JsonProcessingException {
148+ public static String generateJsonSchema (final String xml ) {
143149 final var topNode = convertXmlToJsonNode (xml );
144150 return generateJsonSchema (topNode ).toPrettyString ();
145151 }
@@ -165,12 +171,10 @@ public static String generateJsonSchema(final String xml) throws JsonProcessingE
165171 final var schemaObjectProperties = objectMapper .createObjectNode ();
166172 schemaNode .set ("properties" , schemaObjectProperties );
167173
168- // recursing on the child nodes and feeding their schemas into the properties schema node
169- var sourceChildren = sourceNode .fields ();
170- sourceChildren .forEachRemaining (entry -> {
171- var childSchema = generateJsonSchema (entry .getValue ());
172- schemaObjectProperties .set (entry .getKey (), childSchema );
173- });
174+ for (final String fieldName : sourceNode .propertyNames ()) {
175+ var childSchema = generateJsonSchema (sourceNode .path (fieldName ));
176+ schemaObjectProperties .set (fieldName , childSchema );
177+ }
174178 } else {
175179 schemaNode .put ("type" , "string" );
176180 }
0 commit comments