Json2XmlMappedConverter.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.xml2json;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.json.AbstractUtils;
import org.openspcoop2.utils.json.JSONUtils;
import org.openspcoop2.utils.resources.FileSystemUtilities;
import org.openspcoop2.utils.xml.XMLUtils;
import org.w3c.dom.Node;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Bussu Giovanni (bussu@link.it)
* @author $Author$
* @version $Rev$, $Date$
*
*/
public class Json2XmlMappedConverter extends AbstractMappedConverter {
private String rootElement_localName = "Root";
private String rootElement_namespace = null;
private List<String> attributes = new ArrayList<>();
public Json2XmlMappedConverter() {
this.forceReorder = true; // viene effettuato il riordinamento per ogni operazione di modifica dei nomi, attribute... e' possibile disabilitarlo se si usa il riordinamento manuale
}
// -- RootElement
public void setRootElement(String rootElement) {
this.rootElement_localName = rootElement;
}
public void setRootElement(String rootElement, String namespace) {
this.rootElement_localName = rootElement;
this.rootElement_namespace = namespace;
}
// -- Attributes
public void addAttributeMapping(String path) throws UtilsException {
this.attributes.add(path);
}
public void readAttributeMappingFromFile(String path) throws UtilsException {
this.readAttributeMappingFromFile(new File(path));
}
public void readAttributeMappingFromFile(File path) throws UtilsException {
if(path.exists()==false) {
throw new UtilsException("File ["+path.getAbsolutePath()+"] not exists");
}
if(path.canRead()==false) {
throw new UtilsException("File ["+path.getAbsolutePath()+"] cannot read");
}
byte [] r = null;
try {
r = FileSystemUtilities.readBytesFromFile(path);
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
this.readAttributeMappingFromFile(r);
}
public void readAttributeMappingFromFile(byte[] resource) throws UtilsException {
readFileConfig(resource, this.attributes);
}
// -- Convert
public String convert(String json) throws UtilsException {
JSONUtils utils = JSONUtils.getInstance(false);
JsonNode node = utils.getAsNode(json);
return convert(node);
}
public String convert(JsonNode node) throws UtilsException {
JSONUtils utils = JSONUtils.getInstance(false);
List<String> attributes_renamed = this.attributes;
List<String> arrays_renamed = this.arrays;
List<String> reorderChildren_renamed = this.reorderChildren.keys();
if(!this.renameFields.isEmpty()) {
List<String> keys = this.renameFields.keys();
Collections.sort(keys, Comparator.reverseOrder());
for (String path : keys) {
String newName = this.renameFields.get(path);
//System.out.println("RENAME ["+path+"] in ["+newName+"]");
boolean forceReorder = false;
if(this.attributes.contains(path)) {
//System.out.println("RENAME ATTRIBUTE ["+newName+"]");
this.attributes.remove(path);
newName = "@"+newName;
}
else {
forceReorder = this.forceReorder;
}
//System.out.println("FORCE REORDER: "+forceReorder);
utils.renameFieldByPath(node, path, newName, forceReorder, false); // non e' obbligatoria la presenza
}
// sistemo path negli attributi
if(!attributes_renamed.isEmpty()) {
attributes_renamed = correctPath("attributes",attributes_renamed);
}
// sistemo path nell'array
if(!arrays_renamed.isEmpty()) {
arrays_renamed = correctPath("arrays", arrays_renamed);
}
// sistemo path nelle istruzioni di reorder
if(!reorderChildren_renamed.isEmpty()) {
reorderChildren_renamed = correctPath("reorder", reorderChildren_renamed);
}
}
if(!attributes_renamed.isEmpty()) {
for (String path : attributes_renamed) {
@SuppressWarnings("unused")
String parentPath = getParentPath(path);
String attrName = getLastNamePath(path);
//System.out.println("ATTRIBUTE ["+path+"] ["+attrName+"]");
if(this.camelCase) {
attrName = AbstractUtils.camelCase(attrName, this.camelCase_firstLower);
}
utils.renameFieldByPath(node, path, "@"+attrName, false); // non e' obbligatoria la presenza
}
}
if(!arrays_renamed.isEmpty()) {
for (String path : arrays_renamed) {
//System.out.println("ARRAY ["+path+"]");
utils.convertFieldToArrayByPath(node, path, this.forceReorder, false); // non e' obbligatoria la presenza
}
}
if(!reorderChildren_renamed.isEmpty()) {
for (String path : reorderChildren_renamed) {
String [] children = this.reorderChildren.get(path);
//System.out.println("REORDER ["+path+"] ["+children.length+"] ["+java.util.Arrays.asList(children)+"]");
utils.reorderFieldChildrenByPath(node, path, false, // non e' obbligatoria la presenza
children);
}
}
// lasciare come ultimo visto che modifica i nomi
if(this.camelCase) {
boolean forceReorder = true; // per mantenere ordine, questo serve sempre
utils.renameFieldInCamelCase(node, this.camelCase_firstLower, forceReorder);
}
// Fix: se il nodo json è formato da più elementi, viene convertito solo il primo. Aggiungo un root Element
JsonNode rootNode = node;
Map<String, String> map = new HashMap<>();
if(this.rootElement_localName!=null) {
rootNode = utils.newObjectNode();
if(this.rootElement_namespace!=null) {
((ObjectNode)rootNode).set("NS."+this.rootElement_localName, node);
map.put(this.rootElement_namespace,"NS");
}
else {
((ObjectNode)rootNode).set(this.rootElement_localName, node);
}
}
String json = utils.toString(rootNode);
//System.out.println("JSON: "+json);
IJson2Xml json2xml = Xml2JsonFactory.getJson2XmlMapped(map);
String xml = json2xml.json2xml(json);
//System.out.println("XML: "+xml);
if(this.prettyPrint) {
try {
Node n = XMLUtils.getInstance().newDocument(xml.getBytes());
return org.openspcoop2.utils.xml.PrettyPrintXMLUtils.prettyPrintWithTrAX(n, true);
}catch(Exception e) {
throw new UtilsException(e.getMessage(),e);
}
}
return xml;
}
}