public Element serviceSpecificExec(Element params, ServiceContext context) throws Exception { AjaxEditUtils ajaxEditUtils = new AjaxEditUtils(context); ajaxEditUtils.preprocessUpdate(params, context); GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME); DataManager dataMan = gc.getBean(DataManager.class); UserSession session = context.getUserSession(); Dbms dbms = (Dbms) context.getResourceManager().open(Geonet.Res.MAIN_DB); String id = Utils.getIdentifierFromParameters(params, context); String isTemplate = Util.getParam(params, Params.TEMPLATE, "n"); String showValidationErrors = Util.getParam(params, Params.SHOWVALIDATIONERRORS, "false"); String title = params.getChildText(Params.TITLE); String data = params.getChildText(Params.DATA); String minor = Util.getParam(params, Params.MINOREDIT, "false"); boolean finished = config.getValue(Params.FINISHED, "no").equals("yes"); boolean forget = config.getValue(Params.FORGET, "no").equals("yes"); if (!forget) { int iLocalId = Integer.parseInt(id); dataMan.setTemplateExt(dbms, iLocalId, isTemplate, title); // --- use StatusActionsFactory and StatusActions class to possibly // --- change status as a result of this edit (use onEdit method) StatusActionsFactory saf = new StatusActionsFactory(gc.getStatusActionsClass()); StatusActions sa = saf.createStatusActions(context, dbms); saf.onEdit(sa, iLocalId, minor.equals("true")); if (data != null) { Element md = Xml.loadString(data, false); String changeDate = null; boolean validate = showValidationErrors.equals("true"); boolean updateDateStamp = !minor.equals("true"); boolean ufo = true; boolean index = true; if (!dataMan.updateMetadata( context, dbms, id, md, validate, ufo, index, context.getLanguage(), changeDate, updateDateStamp)) { throw new ConcurrentUpdateEx(id); } } else { ajaxEditUtils.updateContent(params, false, true); } } // ----------------------------------------------------------------------- // --- update element and return status Element elResp = new Element(Jeeves.Elem.RESPONSE); elResp.addContent(new Element(Geonet.Elem.ID).setText(id)); elResp.addContent(new Element(Geonet.Elem.SHOWVALIDATIONERRORS).setText(showValidationErrors)); boolean justCreated = Util.getParam(params, Params.JUST_CREATED, null) != null; if (justCreated) { elResp.addContent(new Element(Geonet.Elem.JUSTCREATED).setText("true")); } elResp.addContent(new Element(Params.MINOREDIT).setText(minor)); // --- if finished then remove the XML from the session if (finished) { ajaxEditUtils.removeMetadataEmbedded(session, id); } return elResp; }
/** * 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(); }
/** * TODO javadoc. * * @param dbms * @param id * @param changes * @param currVersion * @return * @throws Exception */ private Element applyChanges(Dbms dbms, String id, Hashtable changes, String currVersion) throws Exception { Lib.resource.checkEditPrivilege(context, id); Element md = xmlSerializer.select(dbms, "Metadata", id, context); // --- check if the metadata has been deleted if (md == null) { return null; } EditLib editLib = dataManager.getEditLib(); String schema = dataManager.getMetadataSchema(dbms, id); editLib.expandElements(schema, md); editLib.enumerateTree(md); // --- check if the metadata has been modified from last time if (currVersion != null && !editLib.getVersion(id).equals(currVersion)) { return null; } // --- update elements for (Enumeration e = changes.keys(); e.hasMoreElements(); ) { String ref = ((String) e.nextElement()).trim(); String val = ((String) changes.get(ref)).trim(); String attr = null; if (updatedLocalizedTextElement(md, ref, val, editLib)) { continue; } int at = ref.indexOf('_'); if (at != -1) { attr = ref.substring(at + 1); ref = ref.substring(0, at); } boolean xmlContent = false; if (ref.startsWith("X")) { ref = ref.substring(1); xmlContent = true; } Element el = editLib.findElement(md, ref); if (el == null) throw new IllegalStateException("Element not found at ref = " + ref); if (attr != null) { // The following work-around decodes any attribute name that has a COLON in it // The : is replaced by the word COLON in the xslt so that it can be processed // by the XML Serializer when an update is submitted - a better solution is // to modify the argument handler in Jeeves to store arguments with their name // as a value rather than as the element itself Integer indexColon = attr.indexOf("COLON"); if (indexColon != -1) { String prefix = attr.substring(0, indexColon); String localname = attr.substring(indexColon + 5); String namespace = editLib.getNamespace(prefix + ":" + localname, md, dataManager.getSchema(schema)); Namespace attrNS = Namespace.getNamespace(prefix, namespace); if (el.getAttribute(localname, attrNS) != null) { el.setAttribute(new Attribute(localname, val, attrNS)); } // End of work-around } else { if (el.getAttribute(attr) != null) el.setAttribute(new Attribute(attr, val)); } } else if (xmlContent) { if (Log.isDebugEnabled(Geonet.EDITOR)) Log.debug(Geonet.EDITOR, "replacing XML content"); el.removeContent(); val = addNamespaceToFragment(val); el.addContent(Xml.loadString(val, false)); } else { 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(val); } } // --- remove editing info added by previous call editLib.removeEditingInfo(md); editLib.contractElements(md); return md; }