Package org.fao.geonet.kernel

Source Code of org.fao.geonet.kernel.XmlSerializer

//=============================================================================
//===  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.kernel;

import jeeves.server.context.ServiceContext;
import jeeves.xlink.Processor;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.domain.ISODate;
import org.fao.geonet.domain.Metadata;
import org.fao.geonet.domain.Pair;
import org.fao.geonet.domain.ReservedOperation;
import org.fao.geonet.kernel.schema.MetadataSchema;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.repository.MetadataRepository;
import org.fao.geonet.utils.Log;
import org.fao.geonet.utils.Xml;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.springframework.beans.factory.annotation.Autowired;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
* This class is responsible of reading and writing xml on the database.
* It works on tables like (id, data, lastChangeDate).
*/
public abstract class XmlSerializer {
  public static class ThreadLocalConfiguration {
      private boolean forceFilterEditOperation = false;

        public boolean isForceFilterEditOperation() {
            return forceFilterEditOperation;
        }
        public void setForceFilterEditOperation(boolean forceFilterEditOperation) {
            this.forceFilterEditOperation = forceFilterEditOperation;
        }
  }

    @Autowired
    protected SettingManager _settingManager;
    @Autowired
    protected DataManager _dataManager;
    @Autowired
    private MetadataRepository _metadataRepository;

  private static InheritableThreadLocal<ThreadLocalConfiguration> configThreadLocal = new InheritableThreadLocal<XmlSerializer.ThreadLocalConfiguration>();
  public static ThreadLocalConfiguration getThreadLocal(boolean setIfNotPresent) {
      ThreadLocalConfiguration config = configThreadLocal.get();
      if(config == null && setIfNotPresent) {
          config = new ThreadLocalConfiguration();
          configThreadLocal.set(config);
      }
     
      return config;
  }
  public static void clearThreadLocal() {
    configThreadLocal.set(null);
  }

    /**
     *
     * @return
     */
  public boolean resolveXLinks() {
    if (_settingManager == null) { // no initialization, no XLinks
      Log.error(Geonet.DATA_MANAGER,"No settingManager in XmlSerializer, XLink Resolver disabled.");
      return false;
    }

    String xlR = _settingManager.getValue("system/xlinkResolver/enable");
    if (xlR != null) {
      boolean isEnabled = xlR.equals("true");
      if (isEnabled) Log.info(Geonet.DATA_MANAGER,"XLink Resolver enabled.");
      else Log.info(Geonet.DATA_MANAGER,"XLink Resolver disabled.");
      return isEnabled;
    } else {
      Log.error(Geonet.DATA_MANAGER,"XLink resolver setting does not exist! XLink Resolver disabled.");
      return false;
    }
  }

    /**
     * Retrieves the xml element which id matches the given one. The element is read from 'table' and the string read is converted into xml.
     *
     *
     * @param id
     * @param isIndexingTask If true, then withheld elements are not removed.
     * @return
     * @throws Exception
     */
  protected Element internalSelect(String id, boolean isIndexingTask) throws Exception {
        Metadata metadata = _metadataRepository.findOne(id);

    if (metadata == null)
      return null;

    String xmlData = metadata.getData();
    Element metadataXml = Xml.loadString(xmlData, false);

    if (!isIndexingTask) {
            ServiceContext context = ServiceContext.get();
            MetadataSchema mds = _dataManager.getSchema(metadata.getDataInfo().getSchemaId());

            // Check if a filter is defined for this schema
            // for the editing operation ie. user who can not edit
            // will not see those elements.
            Pair<String, Element> editXpathFilter = mds.getOperationFilter(ReservedOperation.editing);
            boolean filterEditOperationElements = editXpathFilter != null;
            List<Namespace> namespaces = mds.getNamespaces();
            if(context != null) {
                GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
                AccessManager am = gc.getBean(AccessManager.class);
                if (editXpathFilter != null) {
                    boolean canEdit = am.canEdit(context, id);
                    if(canEdit) {
                        filterEditOperationElements = false;
                    }
                }
                Pair<String, Element> downloadXpathFilter = mds.getOperationFilter(ReservedOperation.download);
                if (downloadXpathFilter != null) {
                    boolean canDownload = am.canDownload(context, id);
                    if(!canDownload) {
                        removeFilteredElement(metadataXml, downloadXpathFilter, namespaces);
                    }
                }
                Pair<String, Element> dynamicXpathFilter = mds.getOperationFilter(ReservedOperation.dynamic);
                if (dynamicXpathFilter != null) {
                    boolean canDynamic = am.canDynamic(context, id);
                    if(!canDynamic) {
                      removeFilteredElement(metadataXml, dynamicXpathFilter, namespaces);
                    }
                }
        }
        if (filterEditOperationElements || (getThreadLocal(false) != null && getThreadLocal(false).forceFilterEditOperation)) {
                removeFilteredElement(metadataXml, editXpathFilter, namespaces);
            }
    }
    return (Element) metadataXml.detach();
  }

    private void xpath(StringBuilder buffer, Element next) {
    if(next.getParentElement() != null) {
      xpath(buffer, next.getParentElement());
      buffer.append("/");
    }
   
    String name = next.getName();
    Namespace namespace = next.getNamespace();
    buffer.append(namespace.getPrefix()).append(":").append(name);
    if(next.getParentElement() != null) {
      List<?> children = next.getParentElement().getChildren(name, namespace);
      if(children.size() > 1) {
        buffer.append('[').append(children.indexOf(next)+1).append(']');
      }
    }
  }

    public static void removeFilteredElement(Element metadata,
                                             final Pair<String, Element> xPathAndMarkedElement,
                                             List<Namespace> namespaces) throws JDOMException {
        // xPathAndMarkedElement seem can be null in some schemas like dublin core
        if (xPathAndMarkedElement == null) return;

        String xpath = xPathAndMarkedElement.one();
        Element mark = xPathAndMarkedElement.two();

        List<?> nodes = Xml.selectNodes(metadata,
                xpath,
                namespaces);
        for (Object object : nodes) {
            if (object instanceof Element) {
                Element element = (Element) object;
                if(mark != null) {
                    element.removeContent();

                    // Remove attributes
                    @SuppressWarnings("unchecked")
                    List<Attribute> atts = new ArrayList<Attribute>(element.getAttributes());
                    for (Attribute attribute : atts) {
                        attribute.detach();
                    }

                    // Insert attributes or children element of the mark
                    List<Attribute> markAtts = new ArrayList<Attribute>(mark.getAttributes());
                    for (Attribute attribute : markAtts) {
                        element.setAttribute((Attribute) attribute.clone());
                    }
                    for (Object o : mark.getChildren()) {
                        if (o instanceof Element) {
                            Element e = (Element) o;
                            element.setContent((Element) e.clone());
                        }
                    }
                } else {
                    element.detach();
                }
            }
        }
    }

    /**
     * TODO javadoc.
     *
     *
     * @param newMetadata the metadata to insert
     * @param dataXml the data to set on the metadata before saving
     * @param context a service context
     * @return the saved metadata
     * @throws SQLException
     */
  protected Metadata insertDb(final Metadata newMetadata, final Element dataXml,ServiceContext context) throws SQLException {
    if (resolveXLinks()) Processor.removeXLink(dataXml);

        newMetadata.setData(Xml.getString(dataXml));
        Metadata savedMetadata = _metadataRepository.save(newMetadata);
    return savedMetadata;
  }

    /**
     *  Updates an xml element into the database. The new data replaces the old one.
     *
     * @param id
     * @param xml
     * @param changeDate
     * @param updateDateStamp
     * @param uuid null to not update metadata uuid column or the uuid value to be used for the update.
     * @throws SQLException
     */
  protected void updateDb(final String id, final Element xml, final String changeDate, final String root,
                            final boolean updateDateStamp,
                            final String uuid) throws SQLException {

    if (resolveXLinks()) Processor.removeXLink(xml);

        int metadataId = Integer.valueOf(id);
        Metadata md = _metadataRepository.findOne(metadataId);

        md.setDataAndFixCR(xml);

        if (updateDateStamp)  {
            if (changeDate == null)  {
                md.getDataInfo().setChangeDate( new ISODate());
            } else {
                md.getDataInfo().setChangeDate( new ISODate(changeDate));
            }
        }

        if (uuid != null) {
            md.setUuid(uuid);
        }

        _metadataRepository.save(md);
  }

    /**
     * Deletes an xml element given its id.
     *
     *
     * @param id
     * @throws SQLException
     */
  protected void deleteDb(String id) throws Exception {
    // TODO: Ultimately we want to remove any xlinks in this document
    // that aren't already in use from the xlink cache. For now we
    // rely on the admin clearing cache and reindexing regularly
        _metadataRepository.delete(Integer.valueOf(id));

//        Assert.isTrue(!_metadataRepository.exists(Integer.valueOf(id)), "Metadata should have been deleted");

  }

  /* API to be overridden by extensions */

  public abstract void delete(String id, ServiceContext context)
     throws Exception;

  public abstract void update(String id, Element xml,
                                String changeDate, boolean updateDateStamp, String uuid, ServiceContext context)
     throws Exception;

  public abstract Metadata insert(Metadata metadata, Element dataXml, ServiceContext context)
       throws Exception;


    /**
     * Return metadata xml.
     * @param id the metadata id.
     */
  public abstract Element select(ServiceContext context, String id) throws Exception;
  public abstract Element selectNoXLinkResolver(String id, boolean isIndexingTask)
       throws Exception;
TOP

Related Classes of org.fao.geonet.kernel.XmlSerializer

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.