297 lines
8.7 KiB
Java
297 lines
8.7 KiB
Java
package org.gcube.portlets.user.geoportaldataentry.server;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
|
|
import org.gcube.application.geoportalcommon.shared.geoportal.config.GcubeProfileDV;
|
|
import org.gcube.portlets.user.geoportaldataentry.shared.GeoNaFormDataObject;
|
|
import org.gcube.portlets.user.geoportaldataentry.shared.Tree_Node;
|
|
import org.gcube.portlets.widgets.mpformbuilder.shared.GenericDatasetBean;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.jayway.jsonpath.Configuration;
|
|
import com.jayway.jsonpath.JsonPath;
|
|
import com.jayway.jsonpath.spi.json.JsonOrgJsonProvider;
|
|
|
|
/**
|
|
* The Class FormDataObjectToJSON.
|
|
*
|
|
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
|
|
*
|
|
* Mar 10, 2022
|
|
*/
|
|
public class FormDataObjectToJSON {
|
|
|
|
public static final String JSON_$_POINTER = "$";
|
|
private static final Logger LOG = LoggerFactory.getLogger(FormDataObjectToJSON.class);
|
|
|
|
/**
|
|
* Convert.
|
|
*
|
|
* @param tree_Node the tree node
|
|
* @param theRootDocument the the root document
|
|
* @return the JSON object
|
|
* @throws JSONException the JSON exception
|
|
*/
|
|
public JSONObject convert(Tree_Node<GeoNaFormDataObject> tree_Node, JSONObject theRootDocument)
|
|
throws JSONException {
|
|
|
|
if (tree_Node == null)
|
|
return theRootDocument;
|
|
|
|
// the root, instancing new json document
|
|
if (tree_Node.isRoot()) {
|
|
theRootDocument = JSONObjecOrdered.instance();
|
|
}
|
|
|
|
Configuration configuration = Configuration.builder().jsonProvider(new JsonOrgJsonProvider()).build();
|
|
|
|
for (Tree_Node<GeoNaFormDataObject> treeNodeChild : tree_Node.getChildren()) {
|
|
|
|
GeoNaFormDataObject gnaFO = treeNodeChild.getData();
|
|
|
|
// Reading data and profile
|
|
List<GenericDatasetBean> listGDB = gnaFO.getListGDB();
|
|
GcubeProfileDV profile = gnaFO.getGcubeProfileDV();
|
|
LOG.debug("The profile is: " + profile);
|
|
|
|
// Building JSON/section full PATH and section name
|
|
String sectionJSONPath = "";
|
|
String parentPathFromProfile = profile.getParentName() == null ? "" : profile.getParentName();
|
|
String theSectionName = profile.getSectionName();
|
|
|
|
if (theSectionName.compareTo(JSON_$_POINTER) == 0 || theSectionName.compareTo(JSON_$_POINTER + ".") == 0) {
|
|
sectionJSONPath = JSON_$_POINTER;
|
|
theSectionName = "";
|
|
} else {
|
|
sectionJSONPath = String.format("%s%s",
|
|
parentPathFromProfile.endsWith(".") ? parentPathFromProfile : parentPathFromProfile + ".", theSectionName);
|
|
}
|
|
LOG.debug("The sectionJSONPath is: " + sectionJSONPath);
|
|
LOG.info("Current document is: " + theRootDocument);
|
|
|
|
// Building Parent PATH
|
|
String parentPath = sectionJSONPath.compareTo(JSON_$_POINTER) == 0 ? JSON_$_POINTER
|
|
: sectionJSONPath.substring(0, sectionJSONPath.lastIndexOf("."));
|
|
JsonPath parentJSONPath = JsonPath.compile(parentPath);
|
|
LOG.info("Putting into parentJSONPath: " + parentJSONPath);
|
|
|
|
List<JSONObject> listJSONObject = toListJonObject(listGDB);
|
|
JSONObject jsonObject = listJSONObject.get(0);
|
|
|
|
// If the maxOccurs is not 1
|
|
if (profile.getMaxOccurs() == 0 || profile.getMaxOccurs() > 1) {
|
|
LOG.debug("maxOccurs is NOT 1");
|
|
// Must be an array
|
|
boolean pathExists = pathExists(theRootDocument, sectionJSONPath + "[*]");
|
|
LOG.debug(sectionJSONPath+ "exists? "+pathExists);
|
|
if (pathExists) {
|
|
theRootDocument = JsonPath.parse(theRootDocument, configuration).add(sectionJSONPath, jsonObject)
|
|
.json();
|
|
} else {
|
|
// Adding as array of object
|
|
JSONArray targetArray = JSONArrayOrdered.instance();
|
|
targetArray.put(jsonObject);
|
|
LOG.debug("JSON array created: " + targetArray);
|
|
theRootDocument = JsonPath.parse(theRootDocument, configuration)
|
|
.put(parentJSONPath, theSectionName, targetArray).json();
|
|
}
|
|
|
|
LOG.debug("theRootDocument as array is: " + theRootDocument);
|
|
|
|
} else {
|
|
LOG.debug("maxOccurs is 1");
|
|
// Merging as direct properties of the JSON root document
|
|
if (theSectionName == null || theSectionName.isEmpty()) {
|
|
deepMerge(jsonObject, theRootDocument);
|
|
} else {
|
|
// Putting as child of the JSON document
|
|
// theRootDocument.put(profile.getSectionName(), jsonObject);
|
|
theRootDocument = JsonPath.parse(theRootDocument, configuration)
|
|
.put(parentJSONPath, theSectionName, jsonObject).json();
|
|
}
|
|
|
|
LOG.debug("theRootDocument as single object is: " + theRootDocument);
|
|
}
|
|
// recursive call...
|
|
theRootDocument = convert(treeNodeChild, theRootDocument);
|
|
}
|
|
|
|
LOG.debug("Partial Root Document is: " + theRootDocument);
|
|
return theRootDocument;
|
|
|
|
}
|
|
|
|
/**
|
|
* Path exists.
|
|
*
|
|
* @param document the document
|
|
* @param pathExp the path exp
|
|
* @return true, if successful
|
|
*/
|
|
public static boolean pathExists(JSONObject document, String pathExp) {
|
|
LOG.debug("pathExists called");
|
|
|
|
try {
|
|
LOG.debug("pathExists finding: " + pathExp + " into node: " + document);
|
|
Object object = JsonPath.read(document.toString(), pathExp);
|
|
if (object != null) {
|
|
LOG.debug("pathExists returning true");
|
|
return true;
|
|
}
|
|
} catch (Exception e) {
|
|
LOG.error("pathExists error", e);
|
|
return false;
|
|
}
|
|
|
|
LOG.debug("pathExists returning false");
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Generic dataset bean to JSON.
|
|
*
|
|
* @param gdb the gdb
|
|
* @return the JSON object
|
|
* @throws JSONException the JSON exception
|
|
*/
|
|
protected JSONObject genericDatasetBeanToJSON(GenericDatasetBean gdb) throws JSONException {
|
|
|
|
JSONObject sectJSONObject = JSONObjecOrdered.instance();
|
|
|
|
LinkedHashMap<String, List<String>> mapFields = gdb.getFormDataEntryFields();
|
|
LOG.debug("Map ordered: " + mapFields);
|
|
for (String key : mapFields.keySet()) {
|
|
List<String> listValues = mapFields.get(key);
|
|
if (listValues == null || listValues.isEmpty()) {
|
|
continue;
|
|
}
|
|
// key/value as string
|
|
if (listValues.size() == 1) {
|
|
sectJSONObject.put(key, listValues.get(0));
|
|
continue;
|
|
}
|
|
// value is a list
|
|
JSONArray array = new JSONArray();
|
|
for (String value : listValues) {
|
|
array.put(value);
|
|
}
|
|
|
|
sectJSONObject.put(key, array);
|
|
}
|
|
|
|
return sectJSONObject;
|
|
}
|
|
|
|
/**
|
|
* To list jon object.
|
|
*
|
|
* @param listGDB the list GDB
|
|
* @return the list
|
|
* @throws JSONException the JSON exception
|
|
*/
|
|
private List<JSONObject> toListJonObject(List<GenericDatasetBean> listGDB) throws JSONException {
|
|
|
|
List<JSONObject> listJSONObject = new ArrayList<JSONObject>();
|
|
|
|
for (GenericDatasetBean gdb : listGDB) {
|
|
JSONObject jsonObject = genericDatasetBeanToJSON(gdb);
|
|
listJSONObject.add(jsonObject);
|
|
}
|
|
|
|
LOG.info("returning : " + listJSONObject);
|
|
return listJSONObject;
|
|
|
|
}
|
|
|
|
/**
|
|
* Merge "source" into "target". If fields have equal name, merge them
|
|
* recursively.
|
|
*
|
|
* @param source the source
|
|
* @param target the target
|
|
* @return the merged object (target).
|
|
* @throws JSONException the JSON exception
|
|
*/
|
|
public static JSONObject deepMerge(JSONObject source, JSONObject target) throws JSONException {
|
|
for (String key : JSONObject.getNames(source)) {
|
|
Object value = source.get(key);
|
|
if (!target.has(key)) {
|
|
// new value for "key":
|
|
target.put(key, value);
|
|
} else {
|
|
// existing value for "key" - recursively deep merge:
|
|
if (value instanceof JSONObject) {
|
|
JSONObject valueJson = (JSONObject) value;
|
|
deepMerge(valueJson, target.getJSONObject(key));
|
|
} else {
|
|
target.put(key, value);
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
|
|
|
|
/**
|
|
* The Class JSONObjecOrdered.
|
|
*
|
|
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
|
|
*
|
|
* Mar 10, 2022
|
|
*/
|
|
public static class JSONObjecOrdered {
|
|
|
|
/**
|
|
* Instance.
|
|
*
|
|
* @return the JSON object
|
|
*/
|
|
public static JSONObject instance() {
|
|
JSONObject jsonObject = new JSONObject();
|
|
try {
|
|
Field changeMap = jsonObject.getClass().getDeclaredField("map");
|
|
changeMap.setAccessible(true);
|
|
changeMap.set(jsonObject, new LinkedHashMap<>());
|
|
changeMap.setAccessible(false);
|
|
} catch (IllegalAccessException | NoSuchFieldException e) {
|
|
}
|
|
return jsonObject;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The Class JSONObjecOrdered.
|
|
*
|
|
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
|
|
*
|
|
* Mar 10, 2022
|
|
*/
|
|
public static class JSONArrayOrdered {
|
|
|
|
/**
|
|
* Instance.
|
|
*
|
|
* @return the JSON object
|
|
*/
|
|
public static JSONArray instance() {
|
|
JSONArray jsonArray = new JSONArray();
|
|
try {
|
|
Field changeMap = jsonArray.getClass().getDeclaredField("map");
|
|
changeMap.setAccessible(true);
|
|
changeMap.set(jsonArray, new LinkedHashMap<>());
|
|
changeMap.setAccessible(false);
|
|
} catch (IllegalAccessException | NoSuchFieldException e) {
|
|
}
|
|
return jsonArray;
|
|
}
|
|
}
|
|
|
|
}
|