Package org.fao.geonet.component.csw

Source Code of org.fao.geonet.component.csw.GetDomain

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

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import jeeves.server.context.ServiceContext;

import org.fao.geonet.utils.Log;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DocumentStoredFieldVisitor;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.SlowCompositeReaderWrapper;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.CachingWrapperFilter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.csw.common.Csw;
import org.fao.geonet.csw.common.exceptions.CatalogException;
import org.fao.geonet.csw.common.exceptions.NoApplicableCodeEx;
import org.fao.geonet.csw.common.exceptions.OperationNotSupportedEx;
import org.fao.geonet.kernel.csw.CatalogConfiguration;
import org.fao.geonet.kernel.csw.CatalogService;
import org.fao.geonet.kernel.csw.services.AbstractOperation;
import org.fao.geonet.kernel.csw.services.getrecords.CatalogSearcher;
import org.fao.geonet.kernel.search.IndexAndTaxonomy;
import org.fao.geonet.kernel.search.LuceneConfig;
import org.fao.geonet.kernel.search.LuceneSearcher;
import org.fao.geonet.kernel.search.LuceneUtils;
import org.fao.geonet.kernel.search.SearchManager;
import org.fao.geonet.kernel.search.SummaryComparator;
import org.fao.geonet.kernel.search.SummaryComparator.SortOption;
import org.fao.geonet.kernel.search.SummaryComparator.Type;
import org.fao.geonet.kernel.search.index.GeonetworkMultiReader;
import org.fao.geonet.domain.Pair;
import org.jdom.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import bak.pcj.map.ObjectKeyIntMapIterator;
import bak.pcj.map.ObjectKeyIntOpenHashMap;

//=============================================================================
@Component(CatalogService.BEAN_PREFIX+GetDomain.NAME)
public class GetDomain extends AbstractOperation implements CatalogService
{
  //---------------------------------------------------------------------------
  //---
  //--- Constructor
  //---
  //---------------------------------------------------------------------------

  static final String NAME = "GetDomain";
  @Autowired
    private LuceneConfig _luceneConfig;

    @Autowired
    private ApplicationContext springAppContext;
    @Autowired
    private CatalogConfiguration _catalogConfig;

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

  public String getName() { return NAME; }

  //---------------------------------------------------------------------------

  public Element execute(Element request, ServiceContext context) throws CatalogException
  {
    checkService(request);
    checkVersion(request);
   
    Element response = new Element(getName() +"Response", Csw.NAMESPACE_CSW);
   
    String[] propertyNames = getParameters(request, "PropertyName");
    String[] parameterNames = getParameters(request, "ParameterName");


        String cswServiceSpecificConstraint = request.getChildText(Geonet.Elem.FILTER);

    // PropertyName handled first.
    if (propertyNames != null) {
      List<Element> domainValues;
      try {
                final int maxNumberOfRecordsForPropertyNames = _catalogConfig.getMaxNumberOfRecordsForPropertyNames();
                domainValues = handlePropertyName(_catalogConfig, propertyNames, context, false, maxNumberOfRecordsForPropertyNames,
                        cswServiceSpecificConstraint, _luceneConfig);
            } catch (Exception e) {
              Log.error(Geonet.CSW, "Error getting domain value for specified PropertyName : " + e);
              throw new NoApplicableCodeEx(
                      "Raised exception while getting domain value for specified PropertyName  : " + e);
          }
      response.addContent(domainValues);
      return response;
    }
   
    if (parameterNames != null) {
      List<Element> domainValues = handleParameterName(parameterNames);
      response.addContent(domainValues);
    }
   
    return response;
  }

  //---------------------------------------------------------------------------

  public Element adaptGetRequest(Map<String, String> params)
  {
    String service        = params.get("service");
    String version        = params.get("version");
    String parameterName  = params.get("parametername");
    String propertyName   = params.get("propertyname");
   
    Element request = new Element(getName(), Csw.NAMESPACE_CSW);
   
    setAttrib(request, "service",        service);
    setAttrib(request, "version",        version);
   
    //--- these 2 are in mutual exclusion.
    Element propName  = new Element("PropertyName", Csw.NAMESPACE_CSW).setText(propertyName);
    Element paramName  = new Element("ParameterName", Csw.NAMESPACE_CSW).setText(parameterName);
   
    // Property is handled first.
    if (propertyName != null && !propertyName.equals(""))
      request.addContent(propName);
    else if (parameterName != null && !parameterName.equals(""))
      request.addContent(paramName);

    return request;
  }
 
  //---------------------------------------------------------------------------

  public Element retrieveValues(String parameterName) throws CatalogException {
    return null;
  }

  //---------------------------------------------------------------------------
 
  public static List<Element> handlePropertyName(CatalogConfiguration catalogConfig, String[] propertyNames,
                                                   ServiceContext context, boolean freq, int maxRecords, String cswServiceSpecificConstraint, LuceneConfig luceneConfig) throws Exception {

    List<Element> domainValuesList = new ArrayList<Element>();

        if(Log.isDebugEnabled(Geonet.CSW))
            Log.debug(Geonet.CSW,"Handling property names '"+Arrays.toString(propertyNames)+"' with max records of "+maxRecords);
   
    for (int i=0; i < propertyNames.length; i++) {
     
     
      // Initialize list of values element.
      Element listOfValues = null;
     
      // Generate DomainValues element
      Element domainValues = new Element("DomainValues", Csw.NAMESPACE_CSW);
     
      // FIXME what should be the type ???
      domainValues.setAttribute("type", "csw:Record");
     
      String property = propertyNames[i].trim();
     
      // Set propertyName in any case.
      Element pn = new Element("PropertyName", Csw.NAMESPACE_CSW);
      domainValues.addContent(pn.setText(property));
     
      GeonetContext gc = (GeonetContext) context.getHandlerContext(Geonet.CONTEXT_NAME);
      SearchManager sm = gc.getBean(SearchManager.class);
     

          IndexAndTaxonomy indexAndTaxonomy= sm.getNewIndexReader(null);
      try {
          GeonetworkMultiReader reader = indexAndTaxonomy.indexReader;
        BooleanQuery groupsQuery = (BooleanQuery) CatalogSearcher.getGroupsQuery(context);
                BooleanQuery query = null;

                // Apply CSW service specific constraint
                if (StringUtils.isNotEmpty(cswServiceSpecificConstraint)) {
                    Query constraintQuery = CatalogSearcher.getCswServiceSpecificConstraintQuery(cswServiceSpecificConstraint, luceneConfig);

                    query = new BooleanQuery();

                    BooleanClause.Occur occur = LuceneUtils
                            .convertRequiredAndProhibitedToOccur(true, false);

                    query.add(groupsQuery, occur);
                    query.add(constraintQuery, occur);

                } else {
                    query = groupsQuery;
                }

        List<Pair<String, Boolean>> sortFields = Collections.singletonList(Pair.read(Geonet.SearchResult.SortBy.RELEVANCE, true));
                Sort   sort = LuceneSearcher.makeSort(sortFields, context.getLanguage(), false);
        CachingWrapperFilter filter = null;

        Pair<TopDocs,Element> searchResults = LuceneSearcher.doSearchAndMakeSummary(
            maxRecords, 0, maxRecords, context.getLanguage(),
            null, luceneConfig.getTaxonomyConfiguration(), reader,
            query, filter, sort, null, false, false,
            false, false  // Scoring is useless for GetDomain operation
        );
        TopDocs hits = searchResults.one();
     
        try {
          // Get mapped lucene field in CSW configuration
          String indexField = catalogConfig.getFieldMapping().get(
              property.toLowerCase());
          if (indexField != null)
            property = indexField;
 
          // check if params asked is in the index using getFieldNames ?
          @SuppressWarnings("resource")
                    FieldInfos fi = SlowCompositeReaderWrapper.wrap(reader).getFieldInfos();
          if (fi.fieldInfo(property) == null)
            continue;
         
          boolean isRange = false;
          if (catalogConfig.getGetRecordsRangeFields().contains(
              property))
            isRange = true;
         
          if (isRange)
            listOfValues = new Element("RangeOfValues", Csw.NAMESPACE_CSW);
          else 
            listOfValues = new Element("ListOfValues", Csw.NAMESPACE_CSW);

          Set<String> fields = new HashSet<String>();
          fields.add(property);
          fields.add("_isTemplate");
         
 
          // parse each document in the index
          String[] fieldValues;
                    Collator stringCollator = Collator.getInstance();
                    stringCollator.setStrength(Collator.PRIMARY);
                    SortedSet<String> sortedValues = new TreeSet<String>(stringCollator);
          ObjectKeyIntOpenHashMap duplicateValues = new ObjectKeyIntOpenHashMap();
          for (int j = 0; j < hits.scoreDocs.length; j++) {
              DocumentStoredFieldVisitor selector = new DocumentStoredFieldVisitor(fields);
            reader.document(hits.scoreDocs[j].doc, selector);
            Document doc = selector.getDocument();

            // Skip templates and subTemplates
            String[] isTemplate = doc.getValues("_isTemplate");
            if (isTemplate[0] != null && !isTemplate[0].equals("n"))
              continue;
           
            // Get doc values for specified property
            fieldValues = doc.getValues(property);
            if (fieldValues == null)
              continue;
           
            addtoSortedSet(sortedValues, fieldValues, duplicateValues);
          }
         
          SummaryComparator valuesComparator = new SummaryComparator(SortOption.FREQUENCY, Type.STRING, context.getLanguage(), null);
          TreeSet<SummaryComparator.SummaryElement> sortedValuesFrequency = new TreeSet<SummaryComparator.SummaryElement>(valuesComparator);
                    ObjectKeyIntMapIterator entries = duplicateValues.entries();
                   
                    while(entries.hasNext()) {
                        entries.next();
                        sortedValuesFrequency.add(new SummaryComparator.SummaryElement(entries));
                    }
         
          if (freq)
            return createValuesByFrequency(sortedValuesFrequency);
          else
            listOfValues.addContent(createValuesElement(sortedValues, isRange));
         
        } finally {
          // any children means that the catalog was unable to determine
          // anything about the specified parameter
          if (listOfValues!= null && listOfValues.getChildren().size() != 0)
            domainValues.addContent(listOfValues);
 
          // Add current DomainValues to the list
          domainValuesList.add(domainValues);
        }
      } finally {
        sm.releaseIndexReader(indexAndTaxonomy);
      }
    }
    return domainValuesList;
   
  }
 
  //---------------------------------------------------------------------------
  //---
  //--- Private methods
  //---
  //---------------------------------------------------------------------------
 
  private List<Element> handleParameterName(String[] parameterNames) throws CatalogException {
    Element values;
    List<Element> domainValuesList = null;
   
    for (int i=0; i < parameterNames.length; i++) {
     
      if (i==0) domainValuesList = new ArrayList<Element>();
     
      // Generate DomainValues element
      Element domainValues = new Element("DomainValues", Csw.NAMESPACE_CSW);
     
      // FIXME what should be the type ???
      domainValues.setAttribute("type", "csw:Record");
     
      String paramName = parameterNames[i];
     
      // Set parameterName in any case.
      Element pn = new Element("ParameterName", Csw.NAMESPACE_CSW);
      domainValues.addContent(pn.setText(paramName));
     
      String operationName = paramName.substring(0, paramName.indexOf('.'));
      String parameterName = paramName.substring(paramName.indexOf('.')+1);
     
      CatalogService cs = checkOperation(operationName);
      values = cs.retrieveValues(parameterName);
     
      // values null mean that the catalog was unable to determine
      // anything about the specified parameter
      if (values != null)
        domainValues.addContent(values);
     
      // Add current DomainValues to the list
      domainValuesList.add(domainValues);
     
    }
    return domainValuesList;
  }

  //---------------------------------------------------------------------------
 
  private CatalogService checkOperation(String operationName)
      throws CatalogException {

    CatalogService cs = springAppContext.getBean(CatalogService.BEAN_PREFIX+operationName, CatalogService.class);

    if (cs == null)
      throw new OperationNotSupportedEx(operationName);

    return cs;
  }
 
  //---------------------------------------------------------------------------

  private String[] getParameters(Element request, String parameter) {
    if (request == null)
        return null;
   
    Element paramElt = request.getChild(parameter,Csw.NAMESPACE_CSW);
   
    if (paramElt == null)
      return null;
   
    String parameterName = paramElt.getText();
   
    return parameterName.split(",");
  }

  //---------------------------------------------------------------------------
 
  /**
   * @param sortedValues
   * @param fieldValues
   * @param duplicateValues
   */
  private static void addtoSortedSet(SortedSet<String> sortedValues,
      String[] fieldValues, ObjectKeyIntOpenHashMap duplicateValues) {
    for (String value : fieldValues) {
      sortedValues.add(value);
      if (duplicateValues.containsKey(value)) {
        int nb = duplicateValues.get(value);
        duplicateValues.remove(value);
        duplicateValues.put(value, nb+1);
      } else
        duplicateValues.put(value, 1);
    }
  }
 
  //---------------------------------------------------------------------------

  /**
   * Create value element for each item of the string array
   * @param sortedValues
   * @param isRange
     * @return
   */
  private static List<Element> createValuesElement(SortedSet<String> sortedValues, boolean isRange) {
    List<Element> valuesList = new ArrayList<Element>();
    if (!isRange) {
            for (String value : sortedValues) {
                valuesList.add(new Element("Value", Csw.NAMESPACE_CSW).setText(value));
            }
    } else {
      valuesList.add(new Element("MinValue",Csw.NAMESPACE_CSW).setText(sortedValues.first()));
      valuesList.add(new Element("MaxValue",Csw.NAMESPACE_CSW).setText(sortedValues.last()));
    }
    return valuesList;
  }
 
  //---------------------------------------------------------------------------

  /**
   * @param sortedValuesFrequency
   * @return
   */
  private static List<Element> createValuesByFrequency(TreeSet<SummaryComparator.SummaryElement> sortedValuesFrequency) {
   
    List<Element> values = new ArrayList<Element>();
    Element value;

        for (SummaryComparator.SummaryElement element : sortedValuesFrequency) {
            value = new Element("Value", Csw.NAMESPACE_CSW);
            value.setAttribute("count", Integer.toString(element.count));
            value.setText(element.name);

            values.add(value);
        }
    return values;
  }
 
}

//=============================================================================
TOP

Related Classes of org.fao.geonet.component.csw.GetDomain

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.