Package org.fao.geonet.services.metadata

Source Code of org.fao.geonet.services.metadata.EditUtils

//=============================================================================
//===  Copyright (C) 2001-2007 Food and Agriculture Organization of the
//===  United Nations (FAO-UN), United Nations World Food Programme (WFP)
//===  and United Nations Environment Programme (UNEP)
//===
//===  This program is free software; you can redistribute it and/or modify
//===  it under the terms of the GNU General Public License as published by
//===  the Free Software Foundation; either version 2 of the License, or (at
//===  your option) any later version.
//===
//===  This program is distributed in the hope that it will be useful, but
//===  WITHOUT ANY WARRANTY; without even the implied warranty of
//===  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//===  General Public License for more details.
//===
//===  You should have received a copy of the GNU General Public License
//===  along with this program; if not, write to the Free Software
//===  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
//===
//===  Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//===  Rome - Italy. email: geonetwork@osgeo.org
//==============================================================================

package org.fao.geonet.services.metadata;

import com.google.common.collect.Lists;
import org.fao.geonet.exceptions.BadParameterEx;

import jeeves.server.UserSession;
import jeeves.server.context.ServiceContext;

import org.fao.geonet.kernel.*;
import org.fao.geonet.kernel.schema.MultilingualSchemaPlugin;
import org.fao.geonet.kernel.schema.SchemaPlugin;
import org.fao.geonet.utils.Log;
import org.fao.geonet.Util;
import org.fao.geonet.utils.Xml;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.constants.Edit;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.Metadata;
import org.fao.geonet.exceptions.ConcurrentUpdateEx;
import org.fao.geonet.lib.Lib;
import org.jdom.*;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
* Utilities.
*/
class EditUtils {

    public EditUtils(ServiceContext context) {
        this.context = context;
        this.gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
        this.dataManager = gc.getBean(DataManager.class);
        this.xmlSerializer = gc.getBean(XmlSerializer.class);
        this.accessMan = gc.getBean(AccessManager.class);
        this.session = context.getUserSession();

    }
    protected ServiceContext context;
    protected DataManager dataManager;
    protected XmlSerializer xmlSerializer;
  protected GeonetContext gc;
  protected AccessManager accessMan;
  protected UserSession session;

  //--------------------------------------------------------------------------
  //---
  //--- API methods
  //---
  //--------------------------------------------------------------------------

    /**
     * Performs common editor preprocessing tasks.
     *
     * @param params
     * @param context
     * @throws Exception
     */
  public void preprocessUpdate(Element params, ServiceContext context) throws Exception {

    String id = Util.getParam(params, Params.ID);

    //-----------------------------------------------------------------------
    //--- handle current tab and position

    Element elCurrTab = params.getChild(Params.CURRTAB);
    Element elCurrPos = params.getChild(Params.POSITION);
    boolean useEditTab = Util.getParam(params, "editTab", false);
        String sessionTabProperty = useEditTab ? Geonet.Session.METADATA_EDITING_TAB : Geonet.Session.METADATA_SHOW;
      
    if (elCurrTab != null) {
      session.setProperty(sessionTabProperty, elCurrTab.getText());
    }
    if (elCurrPos != null)
      session.setProperty(Geonet.Session.METADATA_POSITION, elCurrPos.getText());

    //-----------------------------------------------------------------------
    //--- check access
    int iLocalId = Integer.parseInt(id);

    if (!dataManager.existsMetadata(iLocalId))
      throw new BadParameterEx("id", id);

    if (!accessMan.canEdit(context, id))
        Lib.resource.denyAccess(context);
  }

    /**
     * Updates metadata content.
     *
     * @param params
     * @param validate
     * @throws Exception
     */
  public void updateContent(Element params, boolean validate) throws Exception {
     updateContent(params, validate, false);
  }

    /**
     * TODO javadoc.
     *
     * @param params
     * @param validate
     * @param embedded
     * @throws Exception
     */
  public void updateContent(Element params, boolean validate, boolean embedded) throws Exception {
    String id      = Util.getParam(params, Params.ID);
    String version = Util.getParam(params, Params.VERSION);
        String minor      = Util.getParam(params, Params.MINOREDIT, "false");

    //--- build hashtable with changes
    //--- each change is a couple (pos, value)

    Map<String, String> htChanges = new HashMap<String, String>(100);
    @SuppressWarnings("unchecked")
        List<Element> list = params.getChildren();
    for (Element el : list) {
      String sPos = el.getName();
      String sVal = el.getText();

      if (sPos.startsWith("_")) {
        htChanges.put(sPos.substring(1), sVal);
            }
    }

        //
    // update element and return status
        //

        Metadata result = null;
        // whether to request automatic changes (update-fixed-info)
        boolean ufo = true;
        // whether to index on update
        boolean index = true;
       
        boolean updateDateStamp = !minor.equals("true");
        String changeDate = null;
    if (embedded) {
            Element updatedMetada = new AjaxEditUtils(context).applyChangesEmbedded(id, htChanges, version);
            if(updatedMetada != null) {
                result = dataManager.updateMetadata(context, id, updatedMetada, false, ufo, index, context.getLanguage(), changeDate, updateDateStamp);
            }
       }
        else {
            Element updatedMetada = applyChanges(id, htChanges, version);
            if(updatedMetada != null) {
          result = dataManager.updateMetadata(context, id, updatedMetada, validate, ufo, index, context.getLanguage(), changeDate, updateDateStamp);
            }
    }
    if (result == null) {
      throw new ConcurrentUpdateEx(id);
        }
  }

    /**
     * TODO javadoc.
     *
     * @param id
     * @param changes
     * @param currVersion
     * @return
     * @throws Exception
     */
    private Element applyChanges(String id, Map<String, String> changes, String currVersion) throws Exception {
        Lib.resource.checkEditPrivilege(context, id);
        Element md = xmlSerializer.select(context, id);

    //--- check if the metadata has been deleted
    if (md == null) {
      return null;
        }

        EditLib editLib = dataManager.getEditLib();

        String schema = dataManager.getMetadataSchema(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 (Map.Entry<String, String> entry : changes.entrySet()) {
      String ref = entry.getKey().trim();
      String val = entry.getValue().trim();
      String attr= null;

      if(updatedLocalizedTextElement(md, schema, 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 = EditLib.addNamespaceToFragment(val);
        el.addContent(Xml.loadString(val, false));
            }
      else {
        @SuppressWarnings("unchecked")
                List<Content> content = el.getContent();

        for (Iterator<Content> iterator = content.iterator(); iterator.hasNext();) {
                    Content content2 = iterator.next();
                   
          if (content2 instanceof Text) {
              iterator.remove();
          }
        }
        el.addContent(val);
      }
    }
    //--- remove editing info added by previous call
    editLib.removeEditingInfo(md);

    editLib.contractElements(md);
        return md;
    }

    /**
     * Adds a localised character string to an element for an ISO19139 record.
     *
     * <pre>
     * <gmd:title xsi:type="gmd:PT_FreeText_PropertyType">
     *    <gco:CharacterString>Template for Vector data in ISO19139 (multilingual)</gco:CharacterString>
     *    <gmd:PT_FreeText>
     *        <gmd:textGroup>
     *            <gmd:LocalisedCharacterString locale="#FRE">Modèle de données vectorielles en ISO19139 (multilingue)</gmd:LocalisedCharacterString>
     *        </gmd:textGroup>
     * </pre>
     *
     * @param md metadata record
     * @param ref current ref of element. All _lang_AB_123 element will be processed.
     * @param val
     * @return
     */
    protected boolean updatedLocalizedTextElement(Element md, String schema,
                                                  String ref, String val, EditLib editLib) {
        if (ref.startsWith("lang")) {
            if (val.length() > 0) {

                SchemaPlugin schemaPlugin = SchemaManager.getSchemaPlugin(context, schema);
                if (schemaPlugin instanceof MultilingualSchemaPlugin) {
                    String[] ids = ref.split("_");
                    // --- search element in current parent
                    Element parent = editLib.findElement(md, ids[2]);
                    String language = ids[1];
                    List<Element> elems = ((MultilingualSchemaPlugin) schemaPlugin)
                            .getTranslationForElement(parent, language);

                    // Element exists, set the value
                    if (elems != null  && elems.size() > 0) {
                        elems.get(0).setText(val);
                    } else {
                        ((MultilingualSchemaPlugin) schemaPlugin).addTranslationToElement(
                                parent, language, val
                        );
                        addMissingGeoNetRef(parent);
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Visit all descendants of an element and
     * add an empty geonet:ref element
     * for later use by the editor.
     *
     * @param element
     */
    protected static void addMissingGeoNetRef(Element element) {
        Iterator<Object> descendants = element.getDescendants();
        List<Object> list = Lists.newArrayList(descendants);

        for (Object descendant : list) {
            if (descendant instanceof Element) {
                Element e = (Element) descendant;
                if (e.getName() != Edit.RootChild.ELEMENT
                        && e.getNamespace() != Edit.NAMESPACE) {
                    Element geonetRef = e.getChild(Edit.RootChild.ELEMENT, Edit.NAMESPACE);
                    if (geonetRef == null) {
                        geonetRef = new Element(Edit.RootChild.ELEMENT, Edit.NAMESPACE);
                        geonetRef.setAttribute(Edit.Element.Attr.REF, "");
                        e.addContent(geonetRef);
                    }
                }
            }
        }
    }

    /**
     *
     * @param params
     * @throws Exception
     */
  public void updateContent(Element params) throws Exception {
    updateContent(params, false);
  }

    /**
     * Used for editing : swaps 2 elements.
     *
     * @param el1
     * @param el2
     * @throws Exception
     */
  protected void swapElements(Element el1, Element el2) throws Exception {

    Element parent = el1.getParentElement();
    if (parent == null) {
      throw new IllegalArgumentException("No parent element for swapping");
    }

    int index1 = parent.indexOf(el1);
    if (index1 == -1) {
      throw new IllegalArgumentException("Element 1 not found for swapping");
    }
    int index2 = parent.indexOf(el2);
    if (index2 == -1) {
      throw new IllegalArgumentException("Element 2 not found for swapping");
    }

    Element el1Spare = (Element)el1.clone();

    parent.setContent(index1, (Element)el2.clone());
    parent.setContent(index2, el1Spare);
  }
}
TOP

Related Classes of org.fao.geonet.services.metadata.EditUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.