diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java index a2aa692..e54cf58 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/GeoPortalDataEntryApp.java @@ -1533,7 +1533,7 @@ public class GeoPortalDataEntryApp implements EntryPoint { // modal3.setHeight("700px"); modal3.setCloseVisible(true); ((Element) modal3.getElement().getChildNodes().getItem(1)) - .addClassName("modal-body-custom"); + .addClassName("modal-body-edit"); int height = Window.getClientHeight() * 70 / 100; int width = Window.getClientWidth() * 70 / 100; @@ -1569,7 +1569,7 @@ public class GeoPortalDataEntryApp implements EntryPoint { // } UpdateRecord ur = new UpdateRecord(appManagerBus, resultDocumentDV.getProfileID(), - resultDocumentDV.getId()); + resultDocumentDV.getId(), height); if (isNotInDRAFT) { ur.noUpdateMode(); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/edit/UpdateRecord.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/edit/UpdateRecord.java index 182a286..b9e2e49 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/edit/UpdateRecord.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/client/ui/edit/UpdateRecord.java @@ -89,7 +89,7 @@ public class UpdateRecord extends Composite { private HandlerManager appManagerBus; - public UpdateRecord(HandlerManager appManagerBus, String profileID, String projectID) { + public UpdateRecord(HandlerManager appManagerBus, String profileID, String projectID, int modalHeight) { initWidget(uiBinder.createAndBindUi(this)); this.appManagerBus = appManagerBus; this.profileID = profileID; @@ -100,7 +100,7 @@ public class UpdateRecord extends Composite { alertHTMLPanel.add(loaderProjectSections); - scrollSectionContent.getElement().getStyle().setProperty("maxHeight", "500px"); + scrollSectionContent.setHeight((modalHeight-300)+"px"); GeoportalDataEntryServiceAsync.Util.getInstance().getProjectEdit(profileID, projectID, new AsyncCallback() { diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java index 1bdf275..e525587 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/GeoportalDataEntryServiceImpl.java @@ -66,6 +66,7 @@ import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendEx import org.gcube.portlets.user.geoportaldataentry.client.GeoportalDataEntryService; import org.gcube.portlets.user.geoportaldataentry.client.ProjectFormCard; import org.gcube.portlets.user.geoportaldataentry.server.json.JsonMerge; +import org.gcube.portlets.user.geoportaldataentry.server.json.JsonMerge.MERGE_OPTION; import org.gcube.portlets.user.geoportaldataentry.shared.CommitReport; import org.gcube.portlets.user.geoportaldataentry.shared.GNADataEntryExtendedConfigProfile; import org.gcube.portlets.user.geoportaldataentry.shared.GeoNaFormDataObject; @@ -269,7 +270,7 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen String srcJ = updatedSectionObject.toString(); String trgJ = targetSectionJObject.toString(); LOG.info("Merging src {} in the target: {}", srcJ, trgJ); - String mergedDoc = JsonMerge.merge(srcJ, trgJ); + String mergedDoc = JsonMerge.merge(srcJ, trgJ, MERGE_OPTION.REPLACE); LOG.info("mergedDoc: {}", mergedDoc); String newDocJson; @@ -292,26 +293,30 @@ public class GeoportalDataEntryServiceImpl extends RemoteServiceServlet implemen Document updatedDocument = Serialization.read(newDocJson.toString(), Document.class); LOG.info("New document is: {}", updatedDocument.toJson()); - Project project = client.updateProject(profileID, projectID, updatedDocument); + //Project project = client.updateProject(profileID, projectID, updatedDocument); + Project project = client.getProjectByID(profileID, projectID); LOG.debug("Medatata Updated with document: {}", project.getTheDocument()); SessionUtil.getCurrentContext(getThreadLocalRequest(), true); - - //Cleaning all the fileset path of the section (defined in the UCD) - for (FilePathDV filePath: listFilePaths) { + if(listFilePaths!=null) { - String filesetFieldName = filePath.getFieldName(); - String filesetPath = sectionPath+"."+filesetFieldName; - //Replacing $.abc with $..abc - filesetPath = filesetPath.replaceFirst("\\.", ".."); - LOG.info("Going to delete fileset path: {}", filesetPath); - //client.deleteFileset(profileID, projectID, filesetPath, true); - } - - List filesUploaded = sectionBean.getFilesUploaded(); - if(filesUploaded!=null && !filesUploaded.isEmpty()) { - replaceFiles(project, sectionPath, section.getGcubeProfileDV(), filesUploaded); + //Cleaning all the fileset path of the section (defined in the UCD) + for (FilePathDV filePath: listFilePaths) { + + String filesetFieldName = filePath.getFieldName(); + String filesetPath = sectionPath+"."+filesetFieldName; + //Replacing $.abc with $..abc + filesetPath = filesetPath.replaceFirst("\\.", ".."); + LOG.info("Going to delete fileset path: {}", filesetPath); + //client.deleteFileset(profileID, projectID, filesetPath, true); + } + + //Registering new files + List filesUploaded = sectionBean.getFilesUploaded(); + if(filesUploaded!=null && !filesUploaded.isEmpty()) { + replaceFiles(project, sectionPath, section.getGcubeProfileDV(), filesUploaded); + } } LOG.info("Project with id " + project.getId() + " updated correclty"); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/json/JsonMerge.java b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/json/JsonMerge.java index 80a1189..c4289a4 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/json/JsonMerge.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataentry/server/json/JsonMerge.java @@ -1,6 +1,7 @@ package org.gcube.portlets.user.geoportaldataentry.server.json; import java.io.IOException; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -10,179 +11,318 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** - * This class provides methods to merge two json of any nested level into a single json. + * This class provides methods to merge two json of any nested level into a + * single json. * * copied from: https://github.com/hemantsonu20/json-merge + * + * @maintainer updated by Francesco Mangiacrapa at ISTI-CNR + * francesco.mangiacrapa@isti.cnr.it + * + * Apr 21, 2023 */ public class JsonMerge { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - /** - * Method to merge two json objects into single json object. - * - *

It merges two json of any nested level into a single json following below logic.

- * - * - *

Examples

- *

Example 1

- *

Source Json

- *
{@code
-     * {
-     *   "name": "json-merge-src"
-     * }
-     * }
- *

Target Json

- *
{@code
-     * {
-     *   "name": "json-merge-target"
-     * }
-     * }
- *

Output

- *
{@code
-     * {
-     *   "name": "json-merge-src"
-     * }
-     * }
- *

Example 2

- *

Source Json

- *
{@code
-     * {
-     *   "level1": {
-     *     "key1": "SrcValue1"
-     *   }
-     * }
-     * }
- *

Target Json

- *
{@code
-     * {
-     *   "level1": {
-     *     "key1": "targetValue1",
-     *     "level2": {
-     *       "key2": "value2"
-     *     }
-     *   }
-     * }
-     * }
- *

Output

- *
{@code
-     * {
-     *   "level1": {
-     *     "key1": "SrcValue1",
-     *     "level2": {
-     *       "key2": "value2"
-     *     }
-     *   }
-     * }
-     * }
- * - * @param srcJsonStr source json string - * @param targetJsonStr target json string - * @return merged json as a string - */ - public static String merge(String srcJsonStr, String targetJsonStr) { + /** + * The Enum MERGE_OPTION. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 21, 2023 + */ + public static enum MERGE_OPTION { + MERGE, REPLACE + } - try { - JsonNode srcNode = OBJECT_MAPPER.readTree(srcJsonStr); - JsonNode targetNode = OBJECT_MAPPER.readTree(targetJsonStr); - JsonNode result = merge(srcNode, targetNode); - return OBJECT_MAPPER.writeValueAsString(result); - } catch (IOException e) { - throw new JsonMergeException("Unable to merge json", e); - } - } + /** + * Method to merge two json objects into single json object. + * + *

+ * It merges two json of any nested level into a single json following below + * logic. + *

+ * + * + *

Examples

+ *

Example 1

+ *

+ * Source Json + *

+ * + *
+	 * {@code
+	 * {
+	 *   "name": "json-merge-src"
+	 * }
+	 * }
+	 * 
+ *

+ * Target Json + *

+ * + *
+	 * {@code
+	 * {
+	 *   "name": "json-merge-target"
+	 * }
+	 * }
+	 * 
+ *

+ * Output + *

+ * + *
+	 * {@code
+	 * {
+	 *   "name": "json-merge-src"
+	 * }
+	 * }
+	 * 
+ * + *

Example 2

+ *

+ * Source Json + *

+ * + *
+	 * {@code
+	 * {
+	 *   "level1": {
+	 *     "key1": "SrcValue1"
+	 *   }
+	 * }
+	 * }
+	 * 
+ *

+ * Target Json + *

+ * + *
+	 * {@code
+	 * {
+	 *   "level1": {
+	 *     "key1": "targetValue1",
+	 *     "level2": {
+	 *       "key2": "value2"
+	 *     }
+	 *   }
+	 * }
+	 * }
+	 * 
+ *

+ * Output + *

+ * + *
+	 * {@code
+	 * {
+	 *   "level1": {
+	 *     "key1": "SrcValue1",
+	 *     "level2": {
+	 *       "key2": "value2"
+	 *     }
+	 *   }
+	 * }
+	 * }
+	 * 
+ * + * @param srcJsonStr source json string + * @param targetJsonStr target json string + * @param option the option + * @return merged json as a string + */ + public static String merge(String srcJsonStr, String targetJsonStr, MERGE_OPTION option) { - public static JsonNode merge(JsonNode srcNode, JsonNode targetNode) { + try { + if (option == null) + option = MERGE_OPTION.MERGE; - // if both nodes are object node, merged object node is returned - if (srcNode.isObject() && targetNode.isObject()) { - return merge((ObjectNode) srcNode, (ObjectNode) targetNode); - } + JsonNode srcNode = OBJECT_MAPPER.readTree(srcJsonStr); + JsonNode targetNode = OBJECT_MAPPER.readTree(targetJsonStr); + JsonNode result = merge(srcNode, targetNode, option); + return OBJECT_MAPPER.writeValueAsString(result); + } catch (IOException e) { + throw new JsonMergeException("Unable to merge json", e); + } + } - // if both nodes are array node, merged array node is returned - if (srcNode.isArray() && targetNode.isArray()) { - return merge((ArrayNode) srcNode, (ArrayNode) targetNode); - } + /** + * Merge. + * + * @param srcNode the src node + * @param targetNode the target node + * @param option the option + * @return the json node + */ + public static JsonNode merge(JsonNode srcNode, JsonNode targetNode, MERGE_OPTION option) { - // special case when src node is null - if (srcNode.isNull()) { - return targetNode; - } + if (option == null) + option = MERGE_OPTION.MERGE; - return srcNode; - } + // if both nodes are object node, merged object node is returned + if (srcNode.isObject() && targetNode.isObject()) { + return merge((ObjectNode) srcNode, (ObjectNode) targetNode, option); + } - public static ObjectNode merge(ObjectNode srcNode, ObjectNode targetNode) { + // if both nodes are array node, merged array node is returned + if (srcNode.isArray() && targetNode.isArray()) { + return mergeArray((ArrayNode) srcNode, (ArrayNode) targetNode, option); + } - ObjectNode result = OBJECT_MAPPER.createObjectNode(); + // special case when src node is null + if (srcNode.isNull()) { + return targetNode; + } - Iterator> srcItr = srcNode.fields(); - while (srcItr.hasNext()) { + return srcNode; + } - Map.Entry entry = srcItr.next(); + /** + * Merge. + * + * @param srcNode the src node + * @param targetNode the target node + * @param option the option + * @return the object node + */ + public static ObjectNode merge(ObjectNode srcNode, ObjectNode targetNode, MERGE_OPTION option) { - // check key in src json exists in target json or not at same level - if (targetNode.has(entry.getKey())) { - result.set(entry.getKey(), merge(entry.getValue(), targetNode.get(entry.getKey()))); - } else { - // if key in src json doesn't exist in target json, just copy the same in result - result.set(entry.getKey(), entry.getValue()); - } - } + ObjectNode result = OBJECT_MAPPER.createObjectNode(); - // copy fields from target json into result which were missing in src json - Iterator> targetItr = targetNode.fields(); - while (targetItr.hasNext()) { - Map.Entry entry = targetItr.next(); - if (!result.has(entry.getKey())) { - result.set(entry.getKey(), entry.getValue()); - } - } - return result; - } + Iterator> srcItr = srcNode.fields(); + while (srcItr.hasNext()) { - public static ArrayNode merge(ArrayNode srcNode, ArrayNode targetNode) { - ArrayNode result = OBJECT_MAPPER.createArrayNode(); - return result.addAll(srcNode).addAll(targetNode); - } + Map.Entry entry = srcItr.next(); + + // check key in src json exists in target json or not at same level + if (targetNode.has(entry.getKey())) { + result.set(entry.getKey(), merge(entry.getValue(), targetNode.get(entry.getKey()), option)); + } else { + // if key in src json doesn't exist in target json, just copy the same in result + result.set(entry.getKey(), entry.getValue()); + } + } + + // copy fields from target json into result which were missing in src json + Iterator> targetItr = targetNode.fields(); + while (targetItr.hasNext()) { + Map.Entry entry = targetItr.next(); + if (!result.has(entry.getKey())) { + result.set(entry.getKey(), entry.getValue()); + } + } + return result; + } + + /** + * Merge. + * + * @param srcNode the src node + * @param targetNode the target node + * @param option the option + * @return the array node + */ + public static ArrayNode mergeArray(ArrayNode srcNode, ArrayNode targetNode, MERGE_OPTION option) { + ArrayNode result = OBJECT_MAPPER.createArrayNode(); + + switch (option) { + case REPLACE: + //Replacing source json value as result + return result.addAll(srcNode); + //return result.addAll(srcNode).addAll(targetNode); + default: + return mergeSet(srcNode, targetNode); + + } + } + + /** + * Added by Francesco Mangiacrapa Merge set. + * + * @param srcNode the src node + * @param targetNode the target node + * @return the array node + */ + public static ArrayNode mergeSet(ArrayNode srcNode, ArrayNode targetNode) { + ArrayNode result = OBJECT_MAPPER.createArrayNode(); + + HashSet set = new HashSet<>(); + + set = toHashSet(set, srcNode); + set = toHashSet(set, targetNode); + + Iterator itr = set.iterator(); + while (itr != null && itr.hasNext()) { + JsonNode arrayValue = itr.next(); + result.add(arrayValue); + } + + return result; + } + + /** + * To hash set. + * + * @param set the set + * @param srcNode the src node + * @return the hash set + */ + public static HashSet toHashSet(HashSet set, ArrayNode srcNode) { + if (srcNode != null) { + Iterator itr = srcNode.elements(); + while (itr != null && itr.hasNext()) { + JsonNode arrayValue = itr.next(); + set.add(arrayValue); + } + } + return set; + } } \ No newline at end of file diff --git a/src/main/webapp/GeoPortalDataEntryApp.css b/src/main/webapp/GeoPortalDataEntryApp.css index e902c8c..58b3e63 100644 --- a/src/main/webapp/GeoPortalDataEntryApp.css +++ b/src/main/webapp/GeoPortalDataEntryApp.css @@ -100,6 +100,9 @@ h1 { max-height: 700px !important; } +.modal-body-edit { + max-height: none !important; +} .disable-div { pointer-events: none; } diff --git a/src/test/java/org/gcube/portlets/user/geoportaldataentry/Complex_Tests.java b/src/test/java/org/gcube/portlets/user/geoportaldataentry/Complex_Tests.java index df9692f..0fd76a6 100644 --- a/src/test/java/org/gcube/portlets/user/geoportaldataentry/Complex_Tests.java +++ b/src/test/java/org/gcube/portlets/user/geoportaldataentry/Complex_Tests.java @@ -5,12 +5,9 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map.Entry; import java.util.Properties; -import java.util.Set; import org.bson.Document; import org.gcube.application.geoportal.client.utils.Serialization; @@ -41,11 +38,11 @@ import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataentry.server.FormDataObjectToJSON; import org.gcube.portlets.user.geoportaldataentry.server.FormDataObjectToJSON.JSONObjectOrdered; import org.gcube.portlets.user.geoportaldataentry.server.json.JsonMerge; +import org.gcube.portlets.user.geoportaldataentry.server.json.JsonMerge.MERGE_OPTION; import org.gcube.portlets.widgets.mpformbuilder.server.MetadataProfileFormBuilderServiceImpl; import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetaDataProfileBean; import org.gcube.portlets.widgets.mpformbuilder.shared.metadata.MetadataFieldWrapper; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; @@ -54,7 +51,6 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.jayway.jsonpath.Configuration; @@ -177,7 +173,7 @@ public class Complex_Tests { targetSectionJObject.put("titolo", "Prova REJECT abstract relazione di scavo 1"); LOG.info("targetSectionJObject: {}", targetSectionJObject.toString()); - String mergedDoc = JsonMerge.merge(targetSectionJObject.toString(), currentSectionJObject.toString()); + String mergedDoc = JsonMerge.merge(targetSectionJObject.toString(), currentSectionJObject.toString(), MERGE_OPTION.REPLACE); LOG.info("output: {}", mergedDoc); String newDocJson; @@ -232,7 +228,7 @@ public class Complex_Tests { // JSONObject mergedSection = FormDataObjectToJSON.deepMerge(sourceSectionObject, // targetSectionJObject); - String output = JsonMerge.merge(targetSectionJObject.toString(), currentSectionJObject.toString()); + String output = JsonMerge.merge(targetSectionJObject.toString(), currentSectionJObject.toString(), MERGE_OPTION.REPLACE); LOG.info("output: {}", output); Gson gson = new Gson();