/** * Removes attribute in embedded mode. * * @param dbms * @param session * @param id * @param ref Attribute identifier (eg. _169_uom). * @return * @throws Exception */ public synchronized Element deleteAttributeEmbedded( Dbms dbms, UserSession session, String id, String ref) throws Exception { String[] token = ref.split("_"); String elementId = token[1]; String attributeName = token[2]; Element result = new Element(Edit.RootChild.NULL, Edit.NAMESPACE); // --- get metadata from session Element md = getMetadataFromSession(session, id); // --- get element to remove EditLib editLib = dataManager.getEditLib(); Element el = editLib.findElement(md, elementId); if (el != null) { Pair<Namespace, String> attInfo = parseAttributeName(attributeName, ":", id, md, dbms, editLib); el.removeAttribute(attInfo.two(), attInfo.one()); } // --- store the metadata in the session again setMetadataIntoSession(session, (Element) md.clone(), id); return result; }
/** * For Ajax Editing : swap element with sibling ([up] and [down] links). * * @param dbms * @param session * @param id * @param ref * @param down * @throws Exception */ public synchronized void swapElementEmbedded( Dbms dbms, UserSession session, String id, String ref, boolean down) throws Exception { dataManager.getMetadataSchema(dbms, id); // --- get metadata from session Element md = getMetadataFromSession(session, id); // --- get element to swap EditLib editLib = dataManager.getEditLib(); Element elSwap = editLib.findElement(md, ref); if (elSwap == null) throw new IllegalStateException(MSG_ELEMENT_NOT_FOUND_AT_REF + ref); // --- swap the elements int iSwapIndex = -1; List list = ((Element) elSwap.getParent()).getChildren(elSwap.getName(), elSwap.getNamespace()); for (int i = 0; i < list.size(); i++) if (list.get(i) == elSwap) { iSwapIndex = i; break; } if (iSwapIndex == -1) throw new IllegalStateException("Index not found for element --> " + elSwap); if (down) swapElements(elSwap, (Element) list.get(iSwapIndex + 1)); else swapElements(elSwap, (Element) list.get(iSwapIndex - 1)); // --- store the metadata in the session again setMetadataIntoSession(session, (Element) md.clone(), id); }
/** * Adds a localised character string to an element. * * @param md metadata record * @param ref current ref of element. All _lang_AB_123 element will be processed. * @param val * @return */ protected static boolean updatedLocalizedTextElement( Element md, String ref, String val, EditLib editLib) { if (ref.startsWith("lang")) { if (val.length() > 0) { String[] ids = ref.split("_"); // --- search element in current metadata record Element parent = editLib.findElement(md, ids[2]); // --- add required attribute parent.setAttribute( "type", "gmd:PT_FreeText_PropertyType", Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")); // --- add new translation Namespace gmd = Namespace.getNamespace("gmd", "http://www.isotc211.org/2005/gmd"); Element langElem = new Element("LocalisedCharacterString", gmd); langElem.setAttribute("locale", "#" + ids[1]); langElem.setText(val); Element freeText = getOrAdd(parent, "PT_FreeText", gmd); Element textGroup = new Element("textGroup", gmd); freeText.addContent(textGroup); textGroup.addContent(langElem); Element refElem = new Element(Edit.RootChild.ELEMENT, Edit.NAMESPACE); refElem.setAttribute(Edit.Element.Attr.REF, ""); textGroup.addContent(refElem); langElem.addContent((Element) refElem.clone()); } return true; } return false; }
/** * For Ajax Editing : retrieves metadata from session and validates it. * * @param session * @param dbms * @param id * @param lang * @return * @throws Exception */ public Element validateMetadataEmbedded(UserSession session, Dbms dbms, String id, String lang) throws Exception { String schema = dataManager.getMetadataSchema(dbms, id); // --- get metadata from session and clone it for validation Element realMd = getMetadataFromSession(session, id); Element md = (Element) realMd.clone(); // --- remove editing info EditLib editLib = dataManager.getEditLib(); editLib.removeEditingInfo(md); editLib.contractElements(md); String parentUuid = null; md = dataManager.updateFixedInfo( schema, id, null, md, parentUuid, DataManager.UpdateDatestamp.no, dbms); boolean workspace = true; // --- do the validation on the metadata return dataManager.doValidate(session, dbms, schema, id, md, lang, false, workspace).one(); }
private Pair<Namespace, String> parseAttributeName( String attributeName, String separator, String id, Element md, Dbms dbms, EditLib editLib) throws Exception { Integer indexColon = attributeName.indexOf(separator); String localname = attributeName; Namespace attrNS = Namespace.NO_NAMESPACE; // ... with qualified name if (indexColon != -1) { String prefix = attributeName.substring(0, indexColon); localname = attributeName.substring(indexColon + separator.length()); String schema = dataManager.getMetadataSchema(dbms, id); String namespace = editLib.getNamespace(prefix + ":" + localname, md, dataManager.getSchema(schema)); attrNS = Namespace.getNamespace(prefix, namespace); } return Pair.write(attrNS, localname); }
/** * For Editing : adds an attribute from a metadata ([add] link). FIXME: Modify and use within Ajax * controls * * @param dbms * @param id * @param ref * @param name * @param currVersion * @return * @throws Exception */ public synchronized boolean addAttribute( Dbms dbms, String id, String ref, String name, String currVersion) throws Exception { Element md = xmlSerializer.select(dbms, "Metadata", id); // --- check if the metadata has been deleted if (md == null) return false; String schema = dataManager.getMetadataSchema(dbms, id); EditLib editLib = dataManager.getEditLib(); editLib.expandElements(schema, md); editLib.enumerateTree(md); // --- get element to add Element el = editLib.findElement(md, ref); if (el == null) Log.error(Geonet.DATA_MANAGER, MSG_ELEMENT_NOT_FOUND_AT_REF + ref); // throw new IllegalStateException("Element not found at ref = " + ref); // --- remove editing info added by previous call editLib.removeEditingInfo(md); if (el != null) { el.setAttribute(new Attribute(name, "")); } editLib.contractElements(md); String parentUuid = null; md = dataManager.updateFixedInfo( schema, id, null, md, parentUuid, DataManager.UpdateDatestamp.no, dbms); String changeDate = null; xmlSerializer.update(dbms, id, md, changeDate, false, context); // Notifies the metadata change to metatada notifier service dataManager.notifyMetadataChange(dbms, md, id); // --- update search criteria boolean workspace = false; dataManager.indexInThreadPoolIfPossible(dbms, id, workspace); return true; }
/** * 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(); }
/** * For Ajax Editing : removes an element from a metadata ([del] link). * * @param dbms * @param session * @param id * @param ref * @param parentRef * @return * @throws Exception */ public synchronized Element deleteElementEmbedded( Dbms dbms, UserSession session, String id, String ref, String parentRef) throws Exception { String schema = dataManager.getMetadataSchema(dbms, id); // --- get metadata from session Element md = getMetadataFromSession(session, id); // --- locate the geonet:info element and clone for later re-use Element info = (Element) (md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE)).clone(); md.removeChild(Edit.RootChild.INFO, Edit.NAMESPACE); // --- get element to remove EditLib editLib = dataManager.getEditLib(); Element el = editLib.findElement(md, ref); if (el == null) throw new IllegalStateException(MSG_ELEMENT_NOT_FOUND_AT_REF + ref); String uName = el.getName(); Namespace ns = el.getNamespace(); Element parent = el.getParentElement(); Element result = null; if (parent != null) { int me = parent.indexOf(el); // --- check and see whether the element to be deleted is the last one of its kind Filter elFilter = new ElementFilter(uName, ns); if (parent.getContent(elFilter).size() == 1) { // --- get geonet child element with attribute name = unqualified name Filter chFilter = new ElementFilter(Edit.RootChild.CHILD, Edit.NAMESPACE); List children = parent.getContent(chFilter); for (int i = 0; i < children.size(); i++) { Element ch = (Element) children.get(i); String name = ch.getAttributeValue("name"); if (name != null && name.equals(uName)) { result = (Element) ch.clone(); break; } } // -- now delete the element as requested parent.removeContent(me); // --- existing geonet child element not present so create it and insert it // --- where the last element was deleted if (result == null) { result = editLib.createElement(schema, el, parent); parent.addContent(me, result); } result.setAttribute(Edit.ChildElem.Attr.PARENT, parentRef); result.addContent(info); } // --- if not the last one then just delete it else { parent.removeContent(me); } } else { throw new IllegalStateException("Element at ref = " + ref + " doesn't have a parent"); } // if we don't need a child then create a geonet:null element if (result == null) { result = new Element(Edit.RootChild.NULL, Edit.NAMESPACE); result.addContent(info); } // --- reattach the info element to the metadata md.addContent((Element) info.clone()); // --- store the metadata in the session again setMetadataIntoSession(session, (Element) md.clone(), id); return result; }
/** * For Ajax Editing : adds an element or an attribute to a metadata element ([add] link). * * @param dbms * @param session * @param id * @param ref * @param name * @param childName * @return * @throws Exception */ public synchronized Element addElementEmbedded( Dbms dbms, UserSession session, String id, String ref, String name, String childName) throws Exception { String schema = dataManager.getMetadataSchema(dbms, id); // --- get metadata from session Element md = getMetadataFromSession(session, id); // --- ref is parent element so find it EditLib editLib = dataManager.getEditLib(); Element el = editLib.findElement(md, ref); if (el == null) throw new IllegalStateException(MSG_ELEMENT_NOT_FOUND_AT_REF + ref); // --- locate the geonet:element and geonet:info elements and clone for // --- later re-use Element refEl = (Element) (el.getChild(Edit.RootChild.ELEMENT, Edit.NAMESPACE)).clone(); Element info = (Element) (md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE)).clone(); md.removeChild(Edit.RootChild.INFO, Edit.NAMESPACE); Element child = null; MetadataSchema mds = dataManager.getSchema(schema); if (childName != null) { if (childName.equals("geonet:attribute")) { String defaultValue = ""; List attributeDefs = el.getChildren(Edit.RootChild.ATTRIBUTE, Edit.NAMESPACE); for (Object a : attributeDefs) { Element attributeDef = (Element) a; if (attributeDef != null && attributeDef.getAttributeValue(Edit.Attribute.Attr.NAME).equals(name)) { Element defaultChild = attributeDef.getChild(Edit.Attribute.Child.DEFAULT, Edit.NAMESPACE); if (defaultChild != null) { defaultValue = defaultChild.getAttributeValue(Edit.Attribute.Attr.VALUE); } } } Pair<Namespace, String> attInfo = parseAttributeName(name, ":", id, md, dbms, editLib); // --- Add new attribute with default value el.setAttribute(new Attribute(attInfo.two(), defaultValue, attInfo.one())); // TODO : add attribute should be false and del true after adding an attribute child = el; } else { // --- normal element child = editLib.addElement(schema, el, name); if (!childName.equals("")) { // --- or element String uChildName = editLib.getUnqualifiedName(childName); String prefix = editLib.getPrefix(childName); String ns = editLib.getNamespace(childName, md, mds); if (prefix.equals("")) { prefix = editLib.getPrefix(el.getName()); ns = editLib.getNamespace(el.getName(), md, mds); } Element orChild = new Element(uChildName, prefix, ns); child.addContent(orChild); // --- add mandatory sub-tags editLib.fillElement(schema, child, orChild); } } } else { child = editLib.addElement(schema, el, name); } // --- now enumerate the new child (if not a simple attribute) if (childName == null || !childName.equals("geonet:attribute")) { // --- now add the geonet:element back again to keep ref number el.addContent(refEl); int iRef = editLib.findMaximumRef(md); editLib.expandElements(schema, child); editLib.enumerateTreeStartingAt(child, iRef + 1, Integer.parseInt(ref)); // --- add editing info to everything from the parent down editLib.expandTree(mds, el); } // --- attach the info element to the child child.addContent(info); // --- attach the info element to the metadata root) md.addContent((Element) info.clone()); // --- store the metadata in the session again setMetadataIntoSession(session, (Element) md.clone(), id); // Return element added return child; }
/** * 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; }