diff --git a/core/src/main/java/org/fao/geonet/kernel/EditLib.java b/core/src/main/java/org/fao/geonet/kernel/EditLib.java
index 873b9c3bcdf..ce3733fdc85 100644
--- a/core/src/main/java/org/fao/geonet/kernel/EditLib.java
+++ b/core/src/main/java/org/fao/geonet/kernel/EditLib.java
@@ -3,7 +3,7 @@
//=== EditLib
//===
//=============================================================================
-//=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
+//=== Copyright (C) 2001-2024 Food and Agriculture Organization of the
//=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
//=== and United Nations Environment Programme (UNEP)
//===
@@ -35,7 +35,6 @@
import java.io.StringReader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.collections.CollectionUtils;
@@ -50,6 +49,7 @@
import org.fao.geonet.kernel.schema.MetadataAttribute;
import org.fao.geonet.kernel.schema.MetadataSchema;
import org.fao.geonet.kernel.schema.MetadataType;
+import org.fao.geonet.kernel.schema.MultilingualSchemaPlugin;
import org.fao.geonet.kernel.schema.SchemaPlugin;
import org.fao.geonet.utils.Xml;
import org.jaxen.JaxenException;
@@ -223,6 +223,47 @@ public Element addElement(MetadataSchema mdSchema, Element el, String qname) thr
return child;
}
+ /**
+ * Creates an element with a name (qname) as child of an element (el).
+ *
+ * If the element to create is multilingual and the related metadata schemas requires to duplicate it,
+ * one child per metadata language is added.
+ *
+ * See {@link org.fao.geonet.kernel.schema.MultilingualSchemaPlugin#duplicateElementsForMultilingual()}
+ *
+ * @param mdSchema Metadata schema
+ * @param el Parent element to add the new element.
+ * @param qname Name of the new element to add.
+ * @param languages Languages to add to the new elements.
+ * @return List of child elements added. For non-multilingual, contains 1 element.
+ * @throws Exception
+ */
+ public List addElements(MetadataSchema mdSchema, Element el,
+ String qname, List languages) throws Exception {
+
+ List result = new ArrayList<>();
+
+ if (mdSchema.getSchemaPlugin() instanceof MultilingualSchemaPlugin) {
+ MultilingualSchemaPlugin multilingualSchemaPlugin = (MultilingualSchemaPlugin) mdSchema.getSchemaPlugin();
+
+ if (!languages.isEmpty() &&
+ multilingualSchemaPlugin.duplicateElementsForMultilingual() &&
+ multilingualSchemaPlugin.isMultilingualElementType(mdSchema.getElementType(qname, el.getName()))) {
+ for(String language : languages) {
+ Element child = addElement(mdSchema, el, qname);
+ ((MultilingualSchemaPlugin) mdSchema.getSchemaPlugin()).addTranslationToElement(child, language, "");
+ result.add(child);
+ }
+ return result;
+ }
+ }
+
+ // If no multilingual management is required, process the single element.
+ result.add(addElement(mdSchema, el, qname));
+
+ return result;
+ }
+
/**
* Adds XML fragment to the metadata record in the last element of the type of the element in
* its parent.
@@ -968,7 +1009,7 @@ public void clearVersion(String id) {
//--------------------------------------------------------------------------
private List filterOnQname(List children, String qname) {
- Vector result = new Vector();
+ Vector result = new Vector<>();
for (Element child : children) {
if (child.getQualifiedName().equals(qname)) {
result.add(child);
@@ -1166,7 +1207,7 @@ public List searchChildren(String chName, Element md, String schema) th
//
boolean hasContent = false;
- Vector holder = new Vector();
+ Vector holder = new Vector<>();
MetadataSchema mdSchema = scm.getSchema(schema);
String chUQname = getUnqualifiedName(chName);
@@ -1222,12 +1263,12 @@ public void expandElements(String schema, Element md) throws Exception {
MetadataType thisType = mdSchema.getTypeInfo(typeName);
if (thisType.hasContainers) {
- Vector holder = new Vector();
+ Vector holder = new Vector<>();
for (String chName: thisType.getAlElements()) {
if (edit_CHOICE_GROUP_SEQUENCE_in(chName)) {
List elems = searchChildren(chName, md, schema);
- if (elems.size() > 0) {
+ if (!elems.isEmpty()) {
holder.addAll(elems);
}
} else {
@@ -1246,7 +1287,7 @@ public void expandElements(String schema, Element md) throws Exception {
* For each container element - descend and collect children.
*/
private Vector
+ */
+ private int getGroupSwapIndex(List list, int swapIndex, List languages) {
+ String elementLanguage = list.get(swapIndex).getAttributeValue("lang", Namespace.XML_NAMESPACE);
+ if (list.size() == 1 || languages.size() == 1 || elementLanguage == null) {
+ return -1;
+ }
+
+ // Consider element are always in order (see update-fixed-info.xsl)
+ // River index = 3, group index = 3 - (en lang index)
+ int indexInGroup = languages.indexOf(elementLanguage);
+ if (indexInGroup == -1) {
+ return swapIndex; // Language not declared?
+ }
+ return swapIndex - indexInGroup;
+ }
+ private static int getElementSwapIndex(List list, Element elSwap) {
+ int i = -1;
+ for (Element element : list) {
+ i++;
+ if (element == elSwap) {
+ return i;
+ }
+ }
+ return i;
}
/**
diff --git a/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java b/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java
index 16aaee8d1d5..0551c66936d 100644
--- a/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java
+++ b/services/src/main/java/org/fao/geonet/api/records/editing/MetadataEditingApi.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001-2016 Food and Agriculture Organization of the
+ * Copyright (C) 2001-2024 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
@@ -42,6 +42,7 @@
import org.fao.geonet.api.records.MetadataUtils;
import org.fao.geonet.api.records.model.Direction;
import org.fao.geonet.api.tools.i18n.LanguageUtils;
+import org.fao.geonet.constants.Edit;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.*;
@@ -558,7 +559,7 @@ public void cancelEdits(@Parameter(description = API_PARAM_RECORD_UUID, required
public void addElement(@Parameter(description = API_PARAM_RECORD_UUID, required = true) @PathVariable String metadataUuid,
@Parameter(description = "Reference of the insertion point.", required = true) @RequestParam String ref,
@Parameter(description = "Name of the element to add (with prefix)", required = true) @RequestParam String name,
- @Parameter(description = "Use geonet:attribute for attributes or child name.", required = false) @RequestParam(required = false) String child,
+ @Parameter(description = "Empty for inserting element, `geonet:attribute` for attributes.", required = false) @RequestParam(required = false) String child,
@Parameter(description = "Should attributes be shown on the editor snippet?", required = false) @RequestParam(defaultValue = "false") boolean displayAttributes,
@Parameter(hidden = true) @RequestParam Map allRequestParams,
HttpServletRequest request, HttpServletResponse response,
@@ -580,11 +581,26 @@ public void addElement(@Parameter(description = API_PARAM_RECORD_UUID, required
// -- Note that the metadata-embedded.xsl stylesheet
// -- only applies the templating to the added element, not to
// -- the entire metadata so performance should not be a big issue
- Element elResp = new AjaxEditUtils(context).addElementEmbedded(ApiUtils.getUserSession(httpSession),
+ List elResp = new AjaxEditUtils(context).addElementEmbedded(ApiUtils.getUserSession(httpSession),
String.valueOf(metadata.getId()), ref, name, child);
- EditLib.tagForDisplay(elResp);
- Element md = (Element) findRoot(elResp).clone();
- EditLib.removeDisplayTag(elResp);
+ Element md = null;
+
+ EditLib editLib = context.getBean(DataManager.class).getEditLib();
+
+ for(Element el: elResp) {
+ if (md == null) {
+ EditLib.tagForDisplay(el);
+ md = (Element) findRoot(el).clone();
+ EditLib.removeDisplayTag(el);
+ } else {
+ Element el2 = editLib.findElement(md, el.getChild("element", Edit.NAMESPACE).getAttribute("ref").getValue());
+ EditLib.tagForDisplay(el2);
+ md = (Element) md.clone();
+ EditLib.removeDisplayTag(el2);
+ }
+
+ }
+
buildEditorForm(allRequestParams.get("currTab"), httpSession, allRequestParams, request, md,
metadata.getDataInfo().getSchemaId(), context, applicationContext, true, true, response);