/** * Apply a list of changes to the metadata record in current editing session. * * <p>The changes are a list of KVP. A key contains at least the element identifier from the * meta-document. A key starting with an "X" should contain an XML fragment for the value. The * following KVP combinations are allowed: * * <ul> * <li>ElementId=ElementValue * <li>ElementId_AttributeName=AttributeValue * <li>ElementId_AttributeNamespacePrefixCOLONAttributeName=AttributeValue * <li>XElementId=ElementValue * <li>XElementId_ElementName=ElementValue * </ul> * * ElementName MUST contain "{@value #COLON_SEPARATOR}" instead of ":" for prefixed elements. * * <p>When using X key, value could contains many XML fragments (eg. <gmd:keywords * .../>{@value #XML_FRAGMENT_SEPARATOR}<gmd:keywords .../>) separated by {@link * #XML_FRAGMENT_SEPARATOR}. All those fragments are inserted to the last element of this type in * its parent if ElementName is set. If not, the element with ElementId is replaced. * * <p> * * @param dbms * @param id Metadata internal identifier. * @param changes List of changes to apply. * @return The update metadata record * @throws Exception */ protected Element applyChangesEmbedded(Dbms dbms, String id, Hashtable changes) throws Exception { String schema = dataManager.getMetadataSchema(dbms, id); EditLib editLib = dataManager.getEditLib(); // --- get metadata from session Element md = getMetadataFromSession(session, id); // Store XML fragments to be handled after other elements update Map<String, String> xmlInputs = new HashMap<String, String>(); // --- update elements for (Enumeration e = changes.keys(); e.hasMoreElements(); ) { String ref = ((String) e.nextElement()).trim(); String value = ((String) changes.get(ref)).trim(); String attribute = null; // Avoid empty key if (ref.equals("")) { continue; } // Catch element starting with a X to replace XML fragments if (ref.startsWith("X")) { ref = ref.substring(1); xmlInputs.put(ref, value); continue; } if (updatedLocalizedTextElement(md, ref, value, editLib)) { continue; } int at = ref.indexOf('_'); if (at != -1) { attribute = ref.substring(at + 1); ref = ref.substring(0, at); } Element el = editLib.findElement(md, ref); if (el == null) { Log.error(Geonet.EDITOR, MSG_ELEMENT_NOT_FOUND_AT_REF + ref); continue; } // Process attribute if (attribute != null) { Pair<Namespace, String> attInfo = parseAttributeName(attribute, COLON_SEPARATOR, id, md, dbms, editLib); String localname = attInfo.two(); Namespace attrNS = attInfo.one(); if (el.getAttribute(localname, attrNS) != null) { el.setAttribute(new Attribute(localname, value, attrNS)); } } else { // Process element value List content = el.getContent(); for (int i = 0; i < content.size(); i++) { if (content.get(i) instanceof Text) { el.removeContent((Text) content.get(i)); i--; } } el.addContent(value); } } // Deals with XML fragments to insert or update if (!xmlInputs.isEmpty()) { // Loop over each XML fragments to insert or replace for (String ref : xmlInputs.keySet()) { String value = xmlInputs.get(ref); String name = null; int addIndex = ref.indexOf('_'); if (addIndex != -1) { name = ref.substring(addIndex + 1); ref = ref.substring(0, addIndex); } // Get element to fill Element el = editLib.findElement(md, ref); if (el == null) { Log.error(Geonet.EDITOR, MSG_ELEMENT_NOT_FOUND_AT_REF + ref); continue; } if (value != null && !value.equals("")) { String[] fragments = value.split(XML_FRAGMENT_SEPARATOR); for (String fragment : fragments) { if (name != null) { if (Log.isDebugEnabled(Geonet.EDITOR)) Log.debug( Geonet.EDITOR, "Add XML fragment; " + fragment + " to element with ref: " + ref); name = name.replace(COLON_SEPARATOR, ":"); editLib.addFragment(schema, el, name, fragment); } else { if (Log.isDebugEnabled(Geonet.EDITOR)) Log.debug( Geonet.EDITOR, "Add XML fragment; " + fragment + " to element with ref: " + ref + " replacing content."); // clean before update el.removeContent(); fragment = addNamespaceToFragment(fragment); // Add content el.addContent(Xml.loadString(fragment, false)); } } } } } // --- remove editing info editLib.removeEditingInfo(md); editLib.contractElements(md); return (Element) md.detach(); }