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. &lt;gmd:keywords
   * .../&gt;{@value #XML_FRAGMENT_SEPARATOR}&lt;gmd:keywords .../&gt;) 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();
  }
Exemple #3
0
  /**
   * 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;
  }