Package org.fao.geonet.kernel.search.keyword

Source Code of org.fao.geonet.kernel.search.keyword.KeywordSearchParamsBuilder

package org.fao.geonet.kernel.search.keyword;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.fao.geonet.exceptions.BadInputEx;
import org.fao.geonet.Util;

import org.fao.geonet.kernel.KeywordBean;
import org.fao.geonet.kernel.rdf.QueryBuilder;
import org.fao.geonet.kernel.rdf.Selector;
import org.fao.geonet.kernel.rdf.Selectors;
import org.fao.geonet.kernel.rdf.Where;
import org.fao.geonet.kernel.rdf.Wheres;
import org.fao.geonet.languages.IsoLanguagesMapper;
import org.jdom.Element;

/**
* Represents the parameters for doing a broad keyword search.
*
* @author jeichar
*/
public class KeywordSearchParamsBuilder {
    private IsoLanguagesMapper isoLangMapper;
    private Set<String> thesauriNames = new LinkedHashSet<String>();
    private Set<String> langs = new LinkedHashSet<String>();
    private String thesauriDomainName;
    private int offset = -1;
    private int maxResults = -1;
    private LinkedList<SearchClause> searchClauses = new LinkedList<SearchClause>();
    private LinkedList<Selector> selectClauses = new LinkedList<Selector>();
    private boolean lenient;
    private boolean requireBoundedBy = false;
   
    public KeywordSearchParamsBuilder(IsoLanguagesMapper mapper) {
        this.isoLangMapper = mapper;
    }
    /**
     * Parses an Element object and creates search params from the params.  Each param
     * is a child of the root element and the name of the parameter is the name of the Child element
     * and the value is the text.
     *
     * The params tags that are accepted are as follows are defined in the class {@link XmlParams}
     *
     * @param params the root element containing children with each param.
     * @return A params object ready for searching with
     */
    public static KeywordSearchParamsBuilder createFromElement(IsoLanguagesMapper mapper, Element params) throws BadInputEx {
        KeywordSearchParamsBuilder parsedParams = new KeywordSearchParamsBuilder(mapper).lenient(true);
       
        String keyword = Util.getParam(params, XmlParams.pKeyword, null);
        if(keyword != null) {
            KeywordSearchType searchType = KeywordSearchType.parseString(Util.getParam(params, XmlParams.pTypeSearch, KeywordSearchType.MATCH.name()));
            parsedParams.keyword(keyword, searchType, true);
            parsedParams.uri(keyword);
        }
       
        String uri = Util.getParam(params, XmlParams.pUri, null);
        if(uri != null) {
            parsedParams.uri(uri);
        }
       
        String maxResults = Util.getParam(params, XmlParams.maxResults, null);
        if(maxResults != null) {
            parsedParams.maxResults(Integer.parseInt(maxResults));
        }
       
        String offset = Util.getParam(params, XmlParams.offset, null);
        if(offset != null) {
            parsedParams.offset(Integer.parseInt(offset));
        }
       
        String thesauriDomainName = Util.getParam(params, XmlParams.pType, null);
        if(thesauriDomainName != null) {
            parsedParams.thesauriDomainName(thesauriDomainName);
        }

        @SuppressWarnings("unchecked")
        List<Element> thesauri = params.getChildren(XmlParams.pThesauri);
        for (Element thesaurusName : thesauri) {
            final String text = thesaurusName.getTextTrim();
            if (!text.isEmpty()) {
                parsedParams.addThesaurus(text);
            }
        }
       
        @SuppressWarnings("unchecked")
        List<Element> langs = params.getChildren(XmlParams.pLang);
        for (Element lang : langs) {
            parsedParams.addLang(lang.getTextTrim());
        }
       
        return parsedParams;
    }
    /**
     * if set to true then the params will not throw exceptions when incorrectly configured.
     *
     * This parameter is for backwards compatibility.
     *
     * @param b
     * @return
     */
    public KeywordSearchParamsBuilder lenient(boolean lenient) {
        this.lenient = lenient;
        checkState(true);
        return this;
    }
    /**
     * Add a language to load during the search.  The definition and value of the Keyword both have
     * translations normally
     * 
     * @param lang the three letter language code of the language to load
     *
     * @return this object
     */
    public KeywordSearchParamsBuilder addLang(String lang) {
        this.langs.add(lang);
        checkState(true);       
        return this;
    }
    /**
     * The name/key of a thesaurus to add for searching.  If no thesauri are added then all thesauri are searched.
     *
     * This parameter mutually exclusive with thesauriType.  If both are defined (and lenient is false) an exception will
     * be thrown.
     *
     * @param thesaurusName the name/key of the thesaurus to search
     * @return this object
     */
    public KeywordSearchParamsBuilder addThesaurus(String thesaurusName) {
        this.thesauriNames.add(thesaurusName);
        checkState(true);
        return this;
    }
   
    /**
     * A read-only copy of the thesaurus names
     * @return A read-only copy of the thesaurus names
     */
    public Set<String> getThesauriNames() {
        return Collections.unmodifiableSet(thesauriNames);
    }
    /**
     * Set the thesauriDomainName Domain/category to search.  If the thesauriDomainName is defined then all thesauri in that domain will be
     * searched.
     *
     * This parameter mutually exclusive with thesauriType.  If both are defined (and lenient is false) an exception will
     * be thrown.
     *
     * @param thesauriDomainName
     * @return this
     */
    public KeywordSearchParamsBuilder thesauriDomainName(String thesauriDomainName) {
        this.thesauriDomainName = thesauriDomainName;
        checkState(true);
        return this;
    }
    /**
     * Set the offset from the first record found to return.  IE the number of records to skip before
     * returning a value.  This is for paging primarily.
     *
     * @param offset a value > 0 means to skip records.  <= 0 means start at 0
     *
     * @return this
     */
    public KeywordSearchParamsBuilder offset(int offset) {
        this.offset = offset;
        checkState(true);
        return this;
    }
    /**
     * The maximum number of results to return from in a search.  A value < 1  means return all results  
     * @param maxResults maximum number of results to return from in a search.  A value < 1  means return all results
     * @return this
     */
    public KeywordSearchParamsBuilder maxResults(int maxResults) {
        this.maxResults = maxResults;
        checkState(true);
        return this;
    }
    /**
     * Define a search parameter.  If defined the keyword must exist in one of the languages that are searched for.
     *
     * @param keyword the keyword to search for
     * @param searchType type of search (IE startsWith, contains, matches, etc...)
     * @param ignoreCase whether or not to be a case sensitive search
     *
     * @return this
     */
    public KeywordSearchParamsBuilder keyword(String keyword, KeywordSearchType searchType, boolean ignoreCase) {
        this.searchClauses.add(new KeywordLabelSearchClause(searchType, keyword, ignoreCase));
        checkState(true);
        return this;
    }
    /**
     * Create an immutable params object from this builder
     *
     * @return an immutable params object from this builder
     */
    public KeywordSearchParams build() {
        checkState(false);
        return new KeywordSearchParams(createQuery(), thesauriNames, thesauriDomainName, maxResults);
    }

    private QueryBuilder<KeywordBean> createQuery() {
        Where where = Wheres.NONE;
       
        if(!searchClauses.isEmpty()) {
            for (SearchClause nextClause : searchClauses) {
                where = where.or(nextClause.toWhere(langs));
            }
        }
       
        QueryBuilder<KeywordBean> builder = QueryBuilder.keywordQueryBuilder(isoLangMapper, new ArrayList<String>(langs), requireBoundedBy)
                .offset(offset)
                .where(where);
       
        if(!selectClauses.isEmpty()) {
            for (Selector s : selectClauses) {
                builder.select(s, false);
            }
        }
       
        return builder;
    }
   
    /**
     *
     * @param errorsOnly if true then it is assumed that the params are not finished and therefore only throw exception
     * if there is a state that is illegal currently.  (For example don't throw exception if no languages are defined because
     * they might be defined later).
     */
    private void checkState(boolean errorsOnly) {
        if(!lenient) {
            // errors that can be ignored if lenient
            if(!thesauriNames.isEmpty() && thesauriDomainName != null) {
                throw new IllegalStateException("thesauriNames and thesauriType cannot both be defined");
            }
        }
       
        // errors that can not be ignored when ready to execute
        if(!errorsOnly) {
            if(langs.isEmpty()) {
                throw new IllegalStateException("At least one language must be defined");
            }
           
            if(offset > 0 && thesauriNames.size() != 1) {
                throw new IllegalStateException("Offset can only be used with one thesaurus.  if offest is defined as > 0 then there must be one and only one thesaurus name also defined");
            }
        }
    }

    /**
     * Convert the query to Xml params that are compatible with the old KeywordSearch API
     *
     * @return parameters as Xml
     */
    public Element toXmlParams() {
        Element params = new Element("params");
       
        addXmlParam(params, XmlParams.offset, ""+offset);
        addXmlParam(params, XmlParams.maxResults,""+maxResults);
        if(thesauriNames.isEmpty()) {
            if(thesauriDomainName != null) {
                addXmlParam(params, XmlParams.pType, thesauriDomainName);
            }
        } else {
            for (String name : thesauriNames) {
                addXmlParam(params, XmlParams.pThesauri, name);
            }
        }
       
        for (String lang : langs) {
            addXmlParam(params, XmlParams.pLang, lang);
        }
       
        for (SearchClause search : searchClauses) {
            search.addXmlParams(params);
        }
       
        return params;
    }
    static void addXmlParam(Element params, String paramName, String value) {
        params.addContent(new Element(paramName).setText(value));
    }
    /**
     * Return a read only collection of languages
     * @return a read only collection of languages
     */
    public Set<String> getLangs() {
        return Collections.unmodifiableSet(langs);
    }
    /**
     * Add a where clause that accepts the keywordURI
     *
     * @param keywordURI the uri identifying the keyword to find
     *
     * @return this
     */
    public KeywordSearchParamsBuilder uri(String keywordURI) {
        this.searchClauses.add(new URISearchClause(keywordURI));
        return this;
    }
    public void relationship(String relatedId, KeywordRelation relation, KeywordSearchType searchType, boolean ignoreCase) {
        this.selectClauses.add(Selectors.BROADER);
        this.searchClauses.add(new RelationShipClause(relation, relatedId, searchType, ignoreCase));
       
    }
    public void requireBoundedBy(boolean require) {
        this.requireBoundedBy  = require;
       
    }
}
TOP

Related Classes of org.fao.geonet.kernel.search.keyword.KeywordSearchParamsBuilder

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.