Package org.dspace.app.webui.discovery

Source Code of org.dspace.app.webui.discovery.DiscoverUtility

/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.webui.discovery;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.webui.util.UIUtil;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.discovery.DiscoverFacetField;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.DiscoverQuery.SORT_ORDER;
import org.dspace.discovery.DiscoverResult;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SearchUtils;
import org.dspace.discovery.configuration.DiscoveryConfiguration;
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
import org.dspace.discovery.configuration.DiscoverySortConfiguration;
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
import org.dspace.handle.HandleManager;

public class DiscoverUtility
{
    /** log4j category */
    private static Logger log = Logger.getLogger(DiscoverUtility.class);

    public static final int TYPE_FACETS = 1;
    public static final int TYPE_TAGCLOUD = 2;
   
    /**
     * Get the scope of the search using the parameter found in the request.
     *
     * @param context
     * @param request
     * @throws IllegalStateException
     * @throws SQLException
     */
    public static DSpaceObject getSearchScope(Context context,
            HttpServletRequest request) throws IllegalStateException,
            SQLException
    {
        // Get the location parameter, if any
        String location = request.getParameter("location");
        if (location == null)
        {
            if (UIUtil.getCollectionLocation(request) != null)
            {
                return UIUtil.getCollectionLocation(request);
            }
            if (UIUtil.getCommunityLocation(request) != null)
            {
                return UIUtil.getCommunityLocation(request);
            }
            return null;
        }
        DSpaceObject scope = HandleManager.resolveToObject(context, location);
        return scope;
    }

    /**
     * Build a DiscoverQuery object using the parameter in the request
     *
     * @param request
     * @return the query.
     * @throws SearchServiceException
     */
    public static DiscoverQuery getDiscoverQuery(Context context,
            HttpServletRequest request, DSpaceObject scope, boolean enableFacet)
    {
        DiscoverQuery queryArgs = new DiscoverQuery();
        DiscoveryConfiguration discoveryConfiguration = SearchUtils
                .getDiscoveryConfiguration(scope);

        List<String> userFilters = setupBasicQuery(context,
                discoveryConfiguration, request, queryArgs);

        setPagination(request, queryArgs, discoveryConfiguration);

        if (enableFacet
                && !"submit_export_metadata".equals(UIUtil.getSubmitButton(
                        request, "submit")))
        {
            setFacet(context, request, scope, queryArgs,
                    discoveryConfiguration, userFilters, discoveryConfiguration
                    .getSidebarFacets(), TYPE_FACETS);
        }

        return queryArgs;
    }

    /**
     * Build a DiscoverQuery object using the tag cloud parameter in the request
     *
     * @param request
     * @return the query.
     * @throws SearchServiceException
     */
    public static DiscoverQuery getTagCloudDiscoverQuery(Context context,
            HttpServletRequest request, DSpaceObject scope, boolean enableFacet)
    {
        DiscoverQuery queryArgs = new DiscoverQuery();
        DiscoveryConfiguration discoveryConfiguration = SearchUtils
                .getDiscoveryConfiguration(scope);

        List<String> userFilters = setupBasicQuery(context,
                discoveryConfiguration, request, queryArgs);

        setPagination(request, queryArgs, discoveryConfiguration);

        if (enableFacet
                && !"submit_export_metadata".equals(UIUtil.getSubmitButton(
                        request, "submit")))
        {
            setFacet(context, request, scope, queryArgs,
                    discoveryConfiguration, userFilters, discoveryConfiguration
                    .getTagCloudFacetConfiguration().getTagCloudFacets(), TYPE_TAGCLOUD);
        }

        return queryArgs;
    }
   
    /**
     * Build the DiscoverQuery object for an autocomplete search using
     * parameters in the request
     *
     * @param context
     * @param request
     * @param scope
     * @return the query.
     */
    public static DiscoverQuery getDiscoverAutocomplete(Context context,
            HttpServletRequest request, DSpaceObject scope)
    {
        DiscoverQuery queryArgs = new DiscoverQuery();
        DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration();
       
        setupBasicQuery(context, discoveryConfiguration, request, queryArgs);
        String autoIndex = request.getParameter("auto_idx");
        String autoQuery = request.getParameter("auto_query");
        String sort = request.getParameter("auto_sort");
        String autoType = request.getParameter("auto_type");
        if ("contains".equals(autoType) || "notcontains".equals(autoType))
        {
            autoType = DiscoveryConfigurationParameters.TYPE_STANDARD;
        }
        else if ("authority".equals(autoType) || "notauthority".equals(autoType))
        {
            autoType = DiscoveryConfigurationParameters.TYPE_AUTHORITY;
        }
        else
        {
            autoType = DiscoveryConfigurationParameters.TYPE_AC;
        }
        DiscoveryConfigurationParameters.SORT sortBy = DiscoveryConfigurationParameters.SORT.VALUE;
        if (StringUtils.isNotBlank(sort))
        {
            if ("count".equalsIgnoreCase(sort))
            {
                sortBy = DiscoveryConfigurationParameters.SORT.COUNT;
            }
            else
            {
                sortBy = DiscoveryConfigurationParameters.SORT.VALUE;
            }
        }
        // no user choices... default for autocomplete should be alphabetic
        // sorting in all cases except empty query where count is preferable
        else if ("".equals(autoQuery))
        {
           sortBy = DiscoveryConfigurationParameters.SORT.COUNT;
        }
        if (autoIndex == null)
        {
            autoIndex = "all";
        }
        if (autoQuery == null)
        {
            autoQuery = "";
        }
       
        int limit = UIUtil.getIntParameter(request, "autocomplete.limit");
        if (limit == -1)
        {
            limit = 10;
        }
        DiscoverFacetField autocompleteField = new DiscoverFacetField(autoIndex,
                autoType,
                limit, sortBy, autoQuery.toLowerCase());
        queryArgs.addFacetField(autocompleteField);
        queryArgs.setMaxResults(0);
        queryArgs.setFacetMinCount(1);
        return queryArgs;
    }

    /**
     * Setup the basic query arguments: the main query and all the filters
     * (default + user). Return the list of user filter
     *
     * @param context
     * @param request
     * @param queryArgs
     *            the query object to populate
     * @return the list of user filer (as filter query)
     */
    private static List<String> setupBasicQuery(Context context,
            DiscoveryConfiguration discoveryConfiguration,
            HttpServletRequest request, DiscoverQuery queryArgs)
    {
        // Get the query
        String query = request.getParameter("query");
        if (StringUtils.isNotBlank(query))
        {
            queryArgs.setQuery(query);
        }

        List<String> defaultFilterQueries = discoveryConfiguration
                .getDefaultFilterQueries();
        if (defaultFilterQueries != null)
        {
            for (String f : defaultFilterQueries)
            {
                queryArgs.addFacetQuery(f);
            }
        }
        List<String[]> filters = getFilters(request);
        List<String> userFilters = new ArrayList<String>();
        for (String[] f : filters)
        {
            try
            {
            String newFilterQuery = SearchUtils.getSearchService()
                    .toFilterQuery(context, f[0], f[1], f[2])
                    .getFilterQuery();
            if (newFilterQuery != null)
            {
                queryArgs.addFilterQueries(newFilterQuery);
                userFilters.add(newFilterQuery);
            }
            }
            catch (SQLException e)
            {
                log.error(LogManager.getHeader(context,
                        "Error in discovery while setting up user facet query",
                        "filter_field: " + f[0] + ",filter_type:"
                                + f[1] + ",filer_value:"
                                + f[2]), e);
            }

        }

        return userFilters;

    }

    private static void setPagination(HttpServletRequest request,
            DiscoverQuery queryArgs,
            DiscoveryConfiguration discoveryConfiguration)
    {
        int start = UIUtil.getIntParameter(request, "start");
        // can't start earlier than 0 in the results!
        if (start < 0)
        {
            start = 0;
        }

        String sortBy = request.getParameter("sort_by");
        String sortOrder = request.getParameter("order");

        DiscoverySortConfiguration searchSortConfiguration = discoveryConfiguration
                .getSearchSortConfiguration();
        if (sortBy == null)
        {
            // Attempt to find the default one, if none found we use SCORE
            sortBy = "score";
            if (searchSortConfiguration != null)
            {
                for (DiscoverySortFieldConfiguration sortFieldConfiguration : searchSortConfiguration
                        .getSortFields())
                {
                    if (sortFieldConfiguration.equals(searchSortConfiguration
                            .getDefaultSort()))
                    {
                        sortBy = SearchUtils
                                .getSearchService()
                                .toSortFieldIndex(
                                        sortFieldConfiguration
                                                .getMetadataField(),
                                        sortFieldConfiguration.getType());
                    }
                }
            }
        }

        if (sortOrder == null && searchSortConfiguration != null)
        {
            sortOrder = searchSortConfiguration.getDefaultSortOrder()
                    .toString();
        }
        if (sortBy != null)
        {
            if ("asc".equalsIgnoreCase(sortOrder))
            {
                queryArgs.setSortField(sortBy, SORT_ORDER.asc);
            }
            else
            {
                queryArgs.setSortField(sortBy, SORT_ORDER.desc);
            }
        }

        int rpp = UIUtil.getIntParameter(request, "rpp");
        // Override the page setting if exporting metadata
        if ("submit_export_metadata".equals(UIUtil.getSubmitButton(request,
                "submit")))
        {
            queryArgs.setStart(0);
            queryArgs.setMaxResults(Integer.MAX_VALUE);
            // search only for items other objects are not exported
            queryArgs.addFilterQueries("search.resourcetype:2");
        }
        else
        {
            // String groupBy = request.getParameter("group_by");
            //
            // // Enable groupBy collapsing if designated
            // if (groupBy != null && !groupBy.equalsIgnoreCase("none")) {
            // /** Construct a Collapse Field Query */
            // queryArgs.addProperty("collapse.field", groupBy);
            // queryArgs.addProperty("collapse.threshold", "1");
            // queryArgs.addProperty("collapse.includeCollapsedDocs.fl",
            // "handle");
            // queryArgs.addProperty("collapse.facet", "before");
            //
            // //queryArgs.a type:Article^2
            //
            // // TODO: This is a hack to get Publications (Articles) to always
            // be at the top of Groups.
            // // TODO: I think the can be more transparently done in the solr
            // solrconfig.xml with DISMAX and boosting
            // /** sort in groups to get publications to top */
            // queryArgs.setSortField("dc.type", DiscoverQuery.SORT_ORDER.asc);
            //
            // }

            if (rpp > 0)
            {
                queryArgs.setMaxResults(rpp);
            }
            else
            {
                queryArgs.setMaxResults(discoveryConfiguration.getDefaultRpp());
            }
            queryArgs.setStart(start);
        }
    }

    private static void setFacet(Context context, HttpServletRequest request,
            DSpaceObject scope, DiscoverQuery queryArgs,
            DiscoveryConfiguration discoveryConfiguration,
            List<String> userFilters, List<DiscoverySearchFilterFacet> facets, int type)
    {
 
        log.info("facets for scope, " + scope + ": "
                + (facets != null ? facets.size() : null));
        if (facets != null)
        {
            queryArgs.setFacetMinCount(1);
        }

        /** enable faceting of search results */
        if (facets != null)
        {
            queryArgs.setFacetMinCount(1);
            for (DiscoverySearchFilterFacet facet : facets)
            {
                if (facet.getType().equals(
                        DiscoveryConfigurationParameters.TYPE_DATE))
                {
                    String dateFacet = facet.getIndexFieldName() + ".year";
                    List<String> filterQueriesList = queryArgs
                            .getFilterQueries();
                    String[] filterQueries = new String[0];
                    if (filterQueriesList != null)
                    {
                        filterQueries = new String[filterQueries.length];
                        filterQueries = filterQueriesList
                                .toArray(filterQueries);
                    }
                    try
                    {
                        // Get a range query so we can create facet
                        // queries
                        // ranging from out first to our last date
                        // Attempt to determine our oldest & newest year
                        // by
                        // checking for previously selected filters
                        int oldestYear = -1;
                        int newestYear = -1;

                        for (String filterQuery : filterQueries)
                        {
                            if (filterQuery.startsWith(dateFacet + ":"))
                            {
                                // Check for a range
                                Pattern pattern = Pattern
                                        .compile("\\[(.*? TO .*?)\\]");
                                Matcher matcher = pattern.matcher(filterQuery);
                                boolean hasPattern = matcher.find();
                                if (hasPattern)
                                {
                                    filterQuery = matcher.group(0);
                                    // We have a range
                                    // Resolve our range to a first &
                                    // endyear
                                    int tempOldYear = Integer
                                            .parseInt(filterQuery.split(" TO ")[0]
                                                    .replace("[", "").trim());
                                    int tempNewYear = Integer
                                            .parseInt(filterQuery.split(" TO ")[1]
                                                    .replace("]", "").trim());

                                    // Check if we have a further filter
                                    // (or
                                    // a first one found)
                                    if (tempNewYear < newestYear
                                            || oldestYear < tempOldYear
                                            || newestYear == -1)
                                    {
                                        oldestYear = tempOldYear;
                                        newestYear = tempNewYear;
                                    }

                                }
                                else
                                {
                                    if (filterQuery.indexOf(" OR ") != -1)
                                    {
                                        // Should always be the case
                                        filterQuery = filterQuery.split(" OR ")[0];
                                    }
                                    // We should have a single date
                                    oldestYear = Integer.parseInt(filterQuery
                                            .split(":")[1].trim());
                                    newestYear = oldestYear;
                                    // No need to look further
                                    break;
                                }
                            }
                        }
                        // Check if we have found a range, if not then
                        // retrieve our first & last year by using solr
                        if (oldestYear == -1 && newestYear == -1)
                        {

                            DiscoverQuery yearRangeQuery = new DiscoverQuery();
                            yearRangeQuery.setFacetMinCount(1);
                            yearRangeQuery.setMaxResults(1);
                            // Set our query to anything that has this
                            // value
                            yearRangeQuery.addFieldPresentQueries(dateFacet);
                            // Set sorting so our last value will appear
                            // on
                            // top
                            yearRangeQuery.setSortField(dateFacet + "_sort",
                                    DiscoverQuery.SORT_ORDER.asc);
                            yearRangeQuery.addFilterQueries(filterQueries);
                            yearRangeQuery.addSearchField(dateFacet);
                            DiscoverResult lastYearResult = SearchUtils
                                    .getSearchService().search(context, scope,
                                            yearRangeQuery);

                            if (0 < lastYearResult.getDspaceObjects().size())
                            {
                                java.util.List<DiscoverResult.SearchDocument> searchDocuments = lastYearResult
                                        .getSearchDocument(lastYearResult
                                                .getDspaceObjects().get(0));
                                if (0 < searchDocuments.size()
                                        && 0 < searchDocuments
                                                .get(0)
                                                .getSearchFieldValues(dateFacet)
                                                .size())
                                {
                                    oldestYear = Integer
                                            .parseInt(searchDocuments
                                                    .get(0)
                                                    .getSearchFieldValues(
                                                            dateFacet).get(0));
                                }
                            }
                            // Now get the first year
                            yearRangeQuery.setSortField(dateFacet + "_sort",
                                    DiscoverQuery.SORT_ORDER.desc);
                            DiscoverResult firstYearResult = SearchUtils
                                    .getSearchService().search(context, scope,
                                            yearRangeQuery);
                            if (0 < firstYearResult.getDspaceObjects().size())
                            {
                                java.util.List<DiscoverResult.SearchDocument> searchDocuments = firstYearResult
                                        .getSearchDocument(firstYearResult
                                                .getDspaceObjects().get(0));
                                if (0 < searchDocuments.size()
                                        && 0 < searchDocuments
                                                .get(0)
                                                .getSearchFieldValues(dateFacet)
                                                .size())
                                {
                                    newestYear = Integer
                                            .parseInt(searchDocuments
                                                    .get(0)
                                                    .getSearchFieldValues(
                                                            dateFacet).get(0));
                                }
                            }
                            // No values found!
                            if (newestYear == -1 || oldestYear == -1)
                            {
                                continue;
                            }

                        }

                        int gap = 1;
                        // Attempt to retrieve our gap by the algorithm
                        // below
                        int yearDifference = newestYear - oldestYear;
                        if (yearDifference != 0)
                        {
                            while (10 < ((double) yearDifference / gap))
                            {
                                gap *= 10;
                            }
                        }
                        // We need to determine our top year so we can
                        // start
                        // our count from a clean year
                        // Example: 2001 and a gap from 10 we need the
                        // following result: 2010 - 2000 ; 2000 - 1990
                        // hence
                        // the top year
                        int topYear = (int) (Math.ceil((float) (newestYear)
                                / gap) * gap);

                        if (gap == 1)
                        {
                            // We need a list of our years
                            // We have a date range add faceting for our
                            // field
                            // The faceting will automatically be
                            // limited to
                            // the 10 years in our span due to our
                            // filterquery
                            queryArgs.addFacetField(new DiscoverFacetField(
                                    facet.getIndexFieldName(), facet.getType(),
                                    10, facet.getSortOrder()));
                        }
                        else
                        {
                            java.util.List<String> facetQueries = new ArrayList<String>();
                            // Create facet queries but limit then to 11
                            // (11
                            // == when we need to show a show more url)
                            for (int year = topYear; year > oldestYear
                                    && (facetQueries.size() < 11); year -= gap)
                            {
                                // Add a filter to remove the last year
                                // only
                                // if we aren't the last year
                                int bottomYear = year - gap;
                                // Make sure we don't go below our last
                                // year
                                // found
                                if (bottomYear < oldestYear)
                                {
                                    bottomYear = oldestYear;
                                }

                                // Also make sure we don't go above our
                                // newest year
                                int currentTop = year;
                                if ((year == topYear))
                                {
                                    currentTop = newestYear;
                                }
                                else
                                {
                                    // We need to do -1 on this one to
                                    // get a
                                    // better result
                                    currentTop--;
                                }
                                facetQueries.add(dateFacet + ":[" + bottomYear
                                        + " TO " + currentTop + "]");
                            }
                            for (String facetQuery : facetQueries)
                            {
                                queryArgs.addFacetQuery(facetQuery);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        log.error(
                                LogManager
                                        .getHeader(
                                                context,
                                                "Error in discovery while setting up date facet range",
                                                "date facet: " + dateFacet), e);
                    }
                }
                else
                {
                    int facetLimit = type==TYPE_FACETS?facet.getFacetLimit():-1;

                    int facetPage = UIUtil.getIntParameter(request,
                            facet.getIndexFieldName() + "_page");
                    if (facetPage < 0)
                    {
                        facetPage = 0;
                    }
                    // at most all the user filters belong to this facet
                    int alreadySelected = userFilters.size();

                    // Add one to our facet limit to make sure that if
                    // we
                    // have more then the shown facets that we show our
                    // show
                    // more url
                    // add the already selected facet so to have a full
                    // top list
                    // if possible
                    int limit = 0;
                    if (type==TYPE_FACETS){
                      limit = facetLimit + 1 + alreadySelected;
                    }
                    else
                      limit = facetLimit;
                   
                    queryArgs.addFacetField(new DiscoverFacetField(facet
                            .getIndexFieldName(),
                            DiscoveryConfigurationParameters.TYPE_TEXT,
                           limit, facet
                                    .getSortOrder(), facetPage * facetLimit));
                }
            }
        }
    }

    public static List<String[]> getFilters(HttpServletRequest request)
    {
        String submit = UIUtil.getSubmitButton(request, "submit");
        int ignore = -1;
        if (submit.startsWith("submit_filter_remove_"))
        {
            ignore = Integer.parseInt(submit.substring("submit_filter_remove_".length()));
        }
        List<String[]> appliedFilters = new ArrayList<String[]>();
       
        List<String> filterValue = new ArrayList<String>();
        List<String> filterOp = new ArrayList<String>();
        List<String> filterField = new ArrayList<String>();
        for (int idx = 1; ; idx++)
        {
            String op = request.getParameter("filter_type_"+idx);
            if (StringUtils.isBlank(op))
            {
                break;
            }
            else if (idx != ignore)
            {
                filterOp.add(op);
                filterField.add(request.getParameter("filter_field_"+idx));
                filterValue.add(request.getParameter("filter_value_"+idx));
            }
        }
       
        String op = request.getParameter("filtertype");
        if (StringUtils.isNotBlank(op))
        {
            filterOp.add(op);
            filterField.add(request.getParameter("filtername"));
            filterValue.add(request.getParameter("filterquery"));
        }
       
        for (int idx = 0; idx < filterOp.size(); idx++)
        {
            appliedFilters.add(new String[] { filterField.get(idx),
                    filterOp.get(idx), filterValue.get(idx) });
        }
        return appliedFilters;
    }

    // /**
    // * Build the query from the advanced search form
    // *
    // * @param request
    // * @return
    // */
    // public static String buildQuery(HttpServletRequest request)
    // {
    // int num_field = UIUtil.getIntParameter(request, "num_search_field");
    // if (num_field <= 0)
    // {
    // num_field = 3;
    // }
    // StringBuffer query = new StringBuffer();
    // buildQueryPart(query, request.getParameter("field"),
    // request.getParameter("query"), null);
    // for (int i = 1; i < num_field; i++)
    // {
    // buildQueryPart(query, request.getParameter("field" + i),
    // request.getParameter("query" + i),
    // request.getParameter("conjuction" + i));
    // }
    // return query.toString();
    // }
    //
    // private static void buildQueryPart(StringBuffer currQuery, String field,
    // String queryPart, String conjuction)
    // {
    // if (StringUtils.isBlank(queryPart))
    // {
    // return;
    // }
    // else
    // {
    // StringBuffer tmp = new StringBuffer(queryPart);
    // if (StringUtils.isNotBlank(field))
    // {
    // tmp.insert(0, field + ":(").append(")");
    // }
    //
    // if (StringUtils.isNotBlank(conjuction) && currQuery.length() > 0)
    // {
    // currQuery.append(conjuction);
    // }
    // currQuery.append(tmp);
    // }
    // }

}
TOP

Related Classes of org.dspace.app.webui.discovery.DiscoverUtility

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.