org.dspace.app.xmlui.aspect.discovery.BrowseFacet.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.app.xmlui.aspect.discovery.BrowseFacet.java

Source

/**
 * $Id: BrowseFacet.java 5161 2010-07-02 11:34:56Z KevinVandeVelde $
 * $URL: http://scm.dspace.org/svn/repo/modules/dspace-discovery/trunk/block/src/main/java/org/dspace/app/xmlui/aspect/discovery/BrowseFacet.java $
 * *************************************************************************
 * Copyright (c) 2002-2009, DuraSpace.  All rights reserved
 * Licensed under the DuraSpace License.
 *
 * A copy of the DuraSpace License has been included in this
 * distribution and is available at: http://scm.dspace.org/svn/repo/licenses/LICENSE.txt
 */
package org.dspace.app.xmlui.aspect.discovery;

import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.utils.DSpaceValidity;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.element.*;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Community;
import org.dspace.content.Collection;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.util.HashUtil;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.excalibur.source.SourceValidity;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.params.FacetParams;
import org.apache.log4j.Logger;
import org.dspace.discovery.*;
import org.dspace.services.ConfigurationService;
import org.dspace.utils.DSpace;
import org.xml.sax.SAXException;

import java.io.Serializable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.*;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.net.URLEncoder;
import java.util.List;
//import org.dspace.sort.SortException;
//import org.dspace.sort.SortOption;

/**
 * User: mdiggory
 * Date: Sep 25, 2009
 * Time: 11:54:11 PM
 */
public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableProcessingComponent {

    private static final Logger log = Logger.getLogger(BrowseFacet.class);

    private static final Message T_dspace_home = message("xmlui.general.dspace_home");

    private final static Message T_go = message("xmlui.general.go");

    private final static Message T_update = message("xmlui.general.update");

    private final static Message T_starts_with = message(
            "xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with");

    private final static Message T_starts_with_help = message(
            "xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with_help");

    //    private final static Message T_choose_year = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_year");

    private final static Message T_jump_year = message(
            "xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year");

    private final static Message T_jump_year_help = message(
            "xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year_help");

    //    private final static Message T_jump_select = message("xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_select");

    private final static Message T_jump_century_head = message("xmlui.Discovery.BrowseFacet.browse_century_head");
    private final static Message T_jump_century = message("xmlui.Discovery.BrowseFacet.browse_century");

    //    private static final Message T_sort_by_relevance = message("xmlui.ArtifactBrowser.AbstractSearch.sort_by.relevance");
    //    private final static Message T_sort_by = message("xmlui.ArtifactBrowser.AbstractSearch.sort_by");

    private final static Message T_order = message("xmlui.ArtifactBrowser.AbstractSearch.order");
    private final static Message T_order_asc = message("xmlui.ArtifactBrowser.AbstractSearch.order.asc");
    private final static Message T_order_desc = message("xmlui.ArtifactBrowser.AbstractSearch.order.desc");

    private final static Message T_rpp = message("xmlui.ArtifactBrowser.AbstractSearch.rpp");

    private final static Message T_view = message("xmlui.ArtifactBrowser.AbstractSearch.view");

    /**
     * The options for results per page
     */
    private static final int[] RESULTS_PER_PAGE_PROGRESSION = { 10, 20, 50, 100 };

    /**
     * The types of view
     */
    private static final String[] VIEW_TYPES = { "list", "cloud" };

    /**
     * The cache of recently submitted items
     */
    protected QueryResponse queryResults;

    /**
     * Cached validity object
     */
    protected SourceValidity validity;

    /**
     * Cached query arguments
     */
    protected SolrQuery queryArgs;

    private int DEFAULT_PAGE_SIZE = 50;
    //private String DEFAULT_ORDER = SortOption.ASCENDING;
    private SolrQuery.ORDER DEFAULT_ORDER = SolrQuery.ORDER.asc;
    private String DEFAULT_SORT_BY = "lex";

    //    public static final String OFFSET = "offset";
    public static final String FACET_FIELD = "field";
    final static String STARTS_WITH = "starts_with";
    final static String PAGE = "page";
    final static String ORDER = "order";
    final static String RESULTS_PER_PAGE = "rpp";
    final static String SORT_BY = "sort_by";
    final static String VIEW = "view";

    public static final String BROWSE_URL_BASE = "browse";

    private ConfigurationService config = null;

    private SearchService searchService = null;

    public BrowseFacet() {

        DSpace dspace = new DSpace();
        config = dspace.getConfigurationService();
        searchService = dspace.getServiceManager().getServiceByName(SearchService.class.getName(),
                SearchService.class);

    }

    /**
     * Generate the unique caching key.
     * This key must be unique inside the space of this component.
     */
    @Override
    public Serializable getKey() {
        try {
            DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

            if (dso == null) {
                return "0";
            }

            return HashUtil.hash(dso.getHandle());
        } catch (SQLException sqle) {
            // Ignore all errors and just return that the component is not
            // cachable.
            return "0";
        }
    }

    /**
     * Generate the cache validity object.
     * <p/>
     * The validity object will include the collection being viewed and
     * all recently submitted items. This does not include the community / collection
     * hierarch, when this changes they will not be reflected in the cache.
     */
    @Override
    public SourceValidity getValidity() {
        if (this.validity == null) {

            try {
                DSpaceValidity validity = new DSpaceValidity();

                DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

                if (dso != null) {
                    // Add the actual collection;
                    validity.add(dso);
                }

                // add reciently submitted items, serialize solr query contents.
                QueryResponse response = getQueryResponse(dso);

                validity.add("numFound:" + response.getResults().getNumFound());

                //                for (SolrDocument doc : response.getResults()) {
                //                    validity.add(doc.toString());
                //                }

                for (SolrDocument doc : response.getResults()) {
                    validity.add(doc.toString());
                }

                for (FacetField field : response.getFacetFields()) {
                    validity.add(field.getName());

                    for (FacetField.Count count : field.getValues()) {
                        validity.add(count.getName() + "#" + count.getCount());
                    }
                }

                this.validity = validity.complete();
            } catch (Exception e) {
                // Just ignore all errors and return an invalid cache.
            }

            //TODO: dependent on tags as well :)
        }
        return this.validity;
    }

    /**
     * Get the recently submitted items for the given community or collection.
     *
     * @param scope The collection.
     */
    protected QueryResponse getQueryResponse(DSpaceObject scope) {

        Request request = ObjectModelHelper.getRequest(objectModel);

        if (queryResults != null) {
            return queryResults;
        }

        queryArgs = new SolrQuery();

        //Make sure we add our default filters
        queryArgs.addFilterQuery(SearchUtils.getDefaultFilters(BROWSE_URL_BASE));

        queryArgs.setQuery("search.resourcetype: " + Constants.ITEM
                + ((request.getParameter("query") != null && !"".equals(request.getParameter("query")))
                        ? " AND (" + request.getParameter("query") + ")"
                        : ""));
        //        queryArgs.setQuery("search.resourcetype:" + Constants.ITEM);

        queryArgs.setRows(0);

        queryArgs.setSortField(ConfigurationManager.getProperty("recent.submissions.sort-option"),
                getParameterOrder());

        queryArgs.addFilterQuery(getParameterFacetQueries());

        queryArgs.setFacet(true);

        //Set the default limit to 11
        //query.setFacetLimit(11);
        queryArgs.setFacetMinCount(1);

        //sort
        //TODO: why this kind of sorting ? Should the sort not be on how many times the value appears like we do in the filter by sidebar ?
        queryArgs.setFacetSort(getParameterSortBy());

        String facetField = getParameterField();

        int page = getParameterPage();
        int rpp = getParameterRpp();

        // FIXME: Have to retrieve everything, since there is no way of getting total facets in order to do masked pagination.
        //        queryArgs.setParam(FacetParams.FACET_OFFSET, String.valueOf((page - 1) * rpp));
        //        queryArgs.setFacetLimit(rpp);//setParam(FacetParams.FACET_LIMIT, String.valueOf(rpp));
        queryArgs.setFacetLimit(-1);

        //        int offset = RequestUtils.getIntParameter(request, OFFSET);
        //        if (offset == -1) {
        //            offset = 0;
        //        }
        //        if (facetField != null && facetField.endsWith(".year")) {
        //            queryArgs.setParam(FacetParams.FACET_OFFSET, "0");
        //            queryArgs.setParam(FacetParams.FACET_LIMIT, "1000000");
        //            facetField = facetField.replace(".year", "");
        //        } else {
        //            queryArgs.setParam(FacetParams.FACET_OFFSET, String.valueOf(offset));
        //We add +1 so we can use the extra one to make sure that we need to show the next page
        //            queryArgs.setParam(FacetParams.FACET_LIMIT, String.valueOf(rpp));
        //        }

        if (scope != null) /* top level search / community */ {
            if (scope instanceof Community) {
                //queryArgs.setFilterQueries("location:m" + scope.getID());
                queryArgs.addFilterQuery("location:m" + scope.getID());
            } else if (scope instanceof Collection) {
                //queryArgs.setFilterQueries("location:l" + scope.getID());
                queryArgs.addFilterQuery("location:l" + scope.getID());
            }
        }

        boolean isDate = false;
        if (facetField != null && facetField.endsWith("_dt")) {
            facetField = facetField.split("_")[0];
            isDate = true;
        }

        if (isDate) {

            queryArgs.setParam(FacetParams.FACET_DATE, new String[] { facetField });
            queryArgs.setParam(FacetParams.FACET_DATE_GAP, "+1YEAR");

            Date lowestDate = getLowestDateValue(queryArgs.getQuery(), facetField, queryArgs.getFilterQueries());
            int thisYear = Calendar.getInstance().get(Calendar.YEAR);

            DateFormat formatter = new SimpleDateFormat("yyyy");
            int maxEndYear = Integer.parseInt(formatter.format(lowestDate));

            //Since we have a date, we need to find the last year
            String startDate = "NOW/YEAR-" + SearchUtils.getConfig().getString("solr.date.gap", "10") + "YEARS";
            String endDate = "NOW";
            //            int startYear = thisYear - (offset + DEFAULT_PAGE_SIZE);
            int startYear = thisYear - ((page - 1) * rpp);
            // We shouldn't go lower then our max bottom year
            // Make sure to substract one so the bottom year is also counted !
            if (startYear < maxEndYear) {
                startYear = maxEndYear - 1;
            }

            //            if (0 < offset) {
            if (page > 1) {
                //Say that we have an offset of 10 years
                //we need to go back 10 years (2010 - (2010 - 10))
                //(add one to compensate for the NOW in the start)
                //                int endYear = thisYear - offset + 1;
                int endYear = thisYear - ((page - 1) * rpp) + 1;

                endDate = "NOW/YEAR-" + (thisYear - endYear) + "YEARS";
                //Add one to the startyear to get one more result
                //When we select NOW, the current year is also used (so auto+1)
            }
            startDate = "NOW/YEAR-" + (thisYear - startYear) + "YEARS";

            queryArgs.setParam(FacetParams.FACET_DATE_START, startDate);
            queryArgs.setParam(FacetParams.FACET_DATE_END, endDate);

            queryArgs.setFacetMinCount(1);

            System.out.println(startDate);
            System.out.println(endDate);

        } else {
            queryArgs.addFacetField(new String[] { facetField });
        }

        //        log.debug("queryArgs: " + queryArgs.toString());

        String startsWith = getParameterStartsWith();
        if (startsWith != null) {
            queryArgs.setFacetPrefix(facetField, startsWith);
        }

        try {
            queryResults = searchService.search(queryArgs);
        } catch (SearchServiceException e) {
            log.error(e.getMessage(), e);
        }

        return queryResults;
    }

    /**
     * Retrieves the lowest date value in the given field
     * @param query a solr query
     * @param dateField the field for which we want to retrieve our date
     * @param filterquery the filterqueries
     * @return the lowest date found, in a date object
     */
    private Date getLowestDateValue(String query, String dateField, String... filterquery) {

        try {
            SolrQuery solrQuery = new SolrQuery();
            solrQuery.setQuery(query);
            solrQuery.setFields(dateField);
            solrQuery.setRows(1);
            solrQuery.setSortField(dateField, SolrQuery.ORDER.asc);
            solrQuery.setFilterQueries(filterquery);

            QueryResponse rsp = searchService.search(solrQuery);
            if (0 < rsp.getResults().getNumFound()) {
                return (Date) rsp.getResults().get(0).getFieldValue(dateField);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Add the basic navigational options:
     *
     * Search - advanced search
     *
     * browse - browse by Titles - browse by Authors - browse by Dates
     *
     * language FIXME: add languages
     *
     * context no context options are added.
     *
     * action no action options are added.
     */
    @Override
    public void addOptions(Options options)
            throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException {
        //        DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

        //List test = options.addList("browse");

        //        DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

        //        List test = options.addList("browse");

        //        org.dspace.app.xmlui.wing.element.List browse = options.addList("browse");

        //        browse.setHead(T_head_browse);
        /*
                List browseGlobal = browse.addList("global");
                List browseContext = browse.addList("context");
            
                browseGlobal.setHead(T_head_all_of_dspace);
            
            
                if (dso != null)
                {
        if (dso instanceof Collection)
        {
            browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Al" + dso.getID(), T_head_this_collection );
        }
        if (dso instanceof Community)
        {
            browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Am" + dso.getID(), T_head_this_community );
        }
                }
                browseGlobal.addItem().addXref(contextPath + "/community-list", T_head_all_of_dspace );
            */

    }

    /**
     * Add a page title and trail links.
     */
    @Override
    public void addPageMeta(PageMeta pageMeta)
            throws SAXException, WingException, SQLException, IOException, AuthorizeException {
        //        Request request = ObjectModelHelper.getRequest(objectModel);
        String facetField = getParameterField();

        pageMeta.addMetadata("title")
                .addContent(message("xmlui.ArtifactBrowser.AbstractSearch.type_" + facetField + "_browse"));

        pageMeta.addTrailLink(contextPath + "/", T_dspace_home);

        DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
        if ((dso instanceof Collection) || (dso instanceof Community)) {
            HandleUtil.buildHandleTrail(dso, pageMeta, contextPath);
        }

        pageMeta.addTrail()
                .addContent(message("xmlui.ArtifactBrowser.AbstractSearch.type_" + facetField + "_browse"));
    }

    @Override
    public void addBody(Body body)
            throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException {

        Request request = ObjectModelHelper.getRequest(objectModel);
        DSpaceObject dso = HandleUtil.obtainHandle(objectModel);
        java.util.List fqs = Arrays.asList(getParameterFacetQueries());

        //Make sure we get our results
        //        log.debug("query results 1: " + queryResults.toString());
        queryResults = getQueryResponse(dso);

        if (this.queryResults != null) {
            log.debug("query results 2: " + queryResults.toString());

            java.util.List<FacetField> facetFields = this.queryResults.getFacetFields();
            if (facetFields == null) {
                facetFields = new ArrayList<FacetField>();
            }

            facetFields.addAll(this.queryResults.getFacetDates());

            log.debug("facetFields: " + facetFields.toString());

            if (facetFields.size() > 0) {
                FacetField field = facetFields.get(0);
                java.util.List<FacetField.Count> values = field.getValues();
                if (field.getGap() != null || field.getName().endsWith(".year")) {
                    //We are dealing with dates so flip em, top date comes first
                    DEFAULT_ORDER = SolrQuery.ORDER.desc;
                } else {
                    DEFAULT_ORDER = SolrQuery.ORDER.asc;
                }

                // Build the DRI Body
                Division div = body.addDivision("browse-by-" + field.getName(), "primary");
                div.setHead(
                        message("xmlui.ArtifactBrowser.AbstractSearch.type_" + getParameterField() + "_browse"));

                // Build the internal navigation (jump lists)
                addBrowseJumpNavigation(div, field, request);

                // Build the sort and display controls
                addBrowseControls(div, field, request);

                if (values != null && 0 < values.size()) {
                    if (getParameterOrder().equals(SolrQuery.ORDER.desc)) {
                        Collections.reverse(values);
                    }

                    //                    Division results = body.addDivision("browse-by-" + field.getName() + "-results", "primary");
                    Division results = div.addDivision("browse-by-" + field.getName() + "-results",
                            this.getParameterView());

                    //results.setHead(message("xmlui.ArtifactBrowser.AbstractSearch.type_" + getParameterField() + "_browse"));

                    // Find our faceting offset
                    /*
                    int offSet = 0;
                    try {
                    offSet = Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET));
                    } catch (NumberFormatException e) {
                    //Ignore
                    }
                        
                    //Only show the nextpageurl if we have at least one result following our current results
                    String nextPageUrl = null;
                    if (field.getName().endsWith(".year")) {
                    offSet = Util.getIntParameter(request, "offset");
                    offSet = offSet == -1 ? 0 : offSet;
                        
                    if ((offSet + DEFAULT_PAGE_SIZE) < values.size()) {
                        nextPageUrl = getNextPageURL(request);
                    }
                    } else {
                    if (values.size() == (DEFAULT_PAGE_SIZE + 1)) {
                        nextPageUrl = getNextPageURL(request);
                    }
                    }
                        
                    int shownItemsMax;
                        
                    if (field.getName().endsWith(".year")) {
                    if ((values.size() - offSet) < DEFAULT_PAGE_SIZE) {
                        shownItemsMax = values.size();
                    } else {
                        shownItemsMax = DEFAULT_PAGE_SIZE;
                    }
                    } else {
                    shownItemsMax = offSet + (DEFAULT_PAGE_SIZE < values.size() ? values.size() - 1 : values.size());
                        
                    }
                    */

                    //                    results.setSimplePagination((int) queryResults.getResults().getNumFound(), offSet + 1,
                    //                            shownItemsMax, getPreviousPageURL(request), nextPageUrl);

                    //// Switching to masked pagination.
                    // Pagination variables.
                    //                    int itemsTotal = (int) solrResults.getNumFound();
                    //                    int firstItemIndex = (int) solrResults.getStart() + 1;
                    //                    int lastItemIndex = (int) solrResults.getStart() + solrResults.size();
                    //                    //if (itemsTotal < lastItemIndex)
                    //                    //    lastItemIndex = itemsTotal;
                    //                    int currentPage = (int) (solrResults.getStart() / this.queryArgs.getFacetLimit()) + 1;
                    //                    int pagesTotal = (int) ((solrResults.getNumFound() - 1) / this.queryArgs.getFacetLimit()) + 1;

                    int itemsTotal = values.size();
                    int firstItemIndex = (getParameterPage() - 1) * getParameterRpp() + 1;
                    //                    int firstItemIndex = Integer.parseInt(queryArgs.get(FacetParams.FACET_OFFSET,
                    //                            String.valueOf((getParameterPage() - 1) * queryArgs.getFacetLimit())));
                    int lastItemIndex = firstItemIndex + getParameterRpp() - 1;
                    if (lastItemIndex > itemsTotal)
                        lastItemIndex = itemsTotal;
                    //if (itemsTotal < lastItemIndex)
                    //    lastItemIndex = itemsTotal;
                    int currentPage = getParameterPage(); //(int) (firstItemIndex / getParameterRpp()) + 1;
                    int pagesTotal = (int) ((itemsTotal - 1) / getParameterRpp()) + 1;

                    Map<String, String> parameters = new HashMap<String, String>();
                    parameters.put("page", "{pageNum}");
                    String pageURLMask = generateURL(parameters);

                    results.setMaskedPagination(itemsTotal, firstItemIndex, lastItemIndex, currentPage, pagesTotal,
                            pageURLMask);
                    ////

                    Table singleTable = results.addTable("browse-by-" + field.getName() + "-results",
                            lastItemIndex - firstItemIndex + 1, 1);
                    List<String> filterQueries = new ArrayList<String>();

                    //                    if (request.getParameterValues("fq") != null) {
                    //                        filterQueries = Arrays.asList(request.getParameterValues("fq"));
                    //                    }
                    filterQueries = Arrays.asList(getParameterFacetQueries());

                    if (field.getName().endsWith(".year")) {
                        for (int i = firstItemIndex - 1; i < lastItemIndex; i++) {
                            FacetField.Count value = values.get(i);
                            renderFacetField(request, dso, field, singleTable, filterQueries, value);
                        }
                        //TODO
                        //                        int start = (values.size() - 1) - this.queryArgs.getFacetLimit();
                        //                        int end = start - getParameterRpp();
                        //                        if (end < 0) {
                        //                            end = 0;
                        //                        } else {
                        //                            end++;
                        //                        }
                        //                        for (int i = start; end <= i; i--) {
                        //                            FacetField.Count value = values.get(i);
                        //                            renderFacetField(request, dso, field, singleTable, filterQueries, value);
                        //                        }
                    } else {
                        //                        int end = values.size();
                        //                        if (getParameterRpp() < end) {
                        //                            end = getParameterRpp();
                        //                        }
                        //
                        //                        for (int i = 0; i < end; i++) {
                        //                            FacetField.Count value = values.get(i);
                        //                            renderFacetField(request, dso, field, singleTable, filterQueries, value);
                        //                        }
                        for (int i = firstItemIndex - 1; i < lastItemIndex; i++) {
                            FacetField.Count value = values.get(i);
                            renderFacetField(request, dso, field, singleTable, filterQueries, value);
                        }
                    }

                }
            }
        }

        //DSpaceObject dso = HandleUtil.obtainHandle(objectModel);

        /*
        if (dso != null)
        {
        if (dso instanceof Collection)
        {
        browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Al" + dso.getID(), T_head_this_collection );
        }
        if (dso instanceof Community)
        {
        browseContext.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2+AND+location%3Am" + dso.getID(), T_head_this_community );
        }
        }
            
        browseGlobal.addItem().addXref(contextPath + "/discovery/?q=search.resourcetype%3A2", T_head_all_of_dspace );
         */
    }

    private void renderFacetField(Request request, DSpaceObject dso, FacetField field, Table singleTable,
            List<String> filterQueries, FacetField.Count value)
            throws SQLException, WingException, UnsupportedEncodingException {
        String displayedValue = value.getName();
        String filterQuery = value.getAsFilterQuery();
        if (field.getName().equals("location.comm") || field.getName().equals("location.coll")) {
            //We have a community/collection, resolve it to a dspaceObject
            //            displayedValue = SolrServiceImpl.locationToName(context, field.getName(), displayedValue);
            int type = field.getName().equals("location.comm") ? Constants.COMMUNITY : Constants.COLLECTION;
            DSpaceObject commColl = DSpaceObject.find(context, type, Integer.parseInt(displayedValue));
            if (commColl != null) {
                displayedValue = commColl.getName() + "TEST";
            }
        }
        if (field.getGap() != null) {
            //We have a date get the year so we can display it
            DateFormat simpleDateformat = new SimpleDateFormat("yyyy");
            displayedValue = simpleDateformat.format(SolrServiceImpl.toDate(displayedValue));
            //displayedValue = displayedValue.substring(0, 4);
            filterQuery = ClientUtils.escapeQueryChars(value.getFacetField().getName()) + ":" + displayedValue
                    + "*";
        }

        Cell cell = singleTable.addRow().addCell();

        //No use in selecting the same filter twice
        if (filterQueries.contains(filterQuery)) {
            //            cell.addContent(displayedValue + " (" + value.getCount() + ")");
            cell.addContent(displayedValue + " (" + value.getCount() + ")");
        } else {
            cell.addXref(contextPath + (dso == null ? "" : "/handle/" + dso.getHandle()) + "/search?" + "&fq="
                    + URLEncoder.encode(filterQuery, "UTF-8")
            //+ (request.getQueryString() != null ? "&" + request.getQueryString() : "")
                    ,
                    //                    displayedValue + " (" + value.getCount() + ")");
                    displayedValue, String.valueOf(value.getCount()));
        }
    }

    /*
        private String getNextPageURL(Request request) {
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put(FACET_FIELD, getParameterField());
    int offSet = Util.getIntParameter(request, "offset");
    if (offSet == -1) {
        offSet = 0;
    }
        
    parameters.put(OFFSET, String.valueOf(offSet + DEFAULT_PAGE_SIZE));
        
    // Add the filter queries
    String url = generateURL(BROWSE_URL_BASE, parameters);
    String[] fqs = getParameterFacetQueries();
    if (fqs != null) {
        for (String fq : fqs) {
            url += "&fq=" + fq;
        }
    }
        
    return url;
        }
    */
    /*
        private String getPreviousPageURL(Request request) {
    //If our offset should be 0 then we shouldn't be able to view a previous page url
        
    if ("0".equals(queryArgs.get(FacetParams.FACET_OFFSET)) && Util.getIntParameter(request, "offset") == -1) {
        return null;
    }
        
    int offset = Util.getIntParameter(request, "offset");
    if (offset == -1 || offset == 0) {
        return null;
    }
        
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put(FACET_FIELD, getParameterField());
    parameters.put(OFFSET, String.valueOf(offset - DEFAULT_PAGE_SIZE));
        
    // Add the filter queries
    String url = generateURL(BROWSE_URL_BASE, parameters);
    String[] fqs = getParameterFacetQueries();
    if (fqs != null) {
        for (String fq : fqs) {
            url += "&fq=" + fq;
        }
    }
        
    return url;
        }
    */
    /**
     * Generate a url to the simple search url.
     */
    protected String generateURL(Map<String, String> parameters) throws UIException {
        //        String query = getQuery();
        //        if (!"".equals(query)) {
        //            parameters.put("query", URLEncode(query));
        //        }
        parameters.put(FACET_FIELD, getParameterField());

        if (parameters.get(PAGE) == null) {
            parameters.put(PAGE, String.valueOf(getParameterPage()));
        }

        if (parameters.get(VIEW) == null) {
            parameters.put(VIEW, String.valueOf(getParameterView()));
        }

        if (parameters.get(RESULTS_PER_PAGE) == null) {
            parameters.put(RESULTS_PER_PAGE, String.valueOf(getParameterRpp()));
        }

        //        if (parameters.get("group_by") == null) {
        //            parameters.put("group_by", String.valueOf(this.getParameterGroup()));
        //        }

        if (parameters.get(SORT_BY) == null) {
            parameters.put(SORT_BY, String.valueOf(getParameterSortBy()));
        }

        if (parameters.get(ORDER) == null) {
            parameters.put(ORDER, String.valueOf(getParameterOrder()));
        }

        if (parameters.get(STARTS_WITH) == null) {
            parameters.put(STARTS_WITH, String.valueOf(getParameterStartsWith()));
        }

        // Add the filter queries
        String url = super.generateURL(BROWSE_URL_BASE, parameters);
        String[] fqs = getParameterFacetQueries();
        if (fqs != null) {
            for (String fq : fqs) {
                url += "&fq=" + fq;
            }
        }

        return url;
    }

    /**
     * Makes the jump-list navigation for the results
     *
     * @param div
     * @param info
     * @param params
     * @throws WingException
     */
    private void addBrowseJumpNavigation(Division div, FacetField field, Request request) throws WingException {
        // Get the name of the index
        String type = field.getName();

        // Prepare a Map of query parameters required for all links
        //        Map<String, String> queryParamsGET = new HashMap<String, String>();
        //        queryParamsGET.putAll(params.getCommonParametersEncoded());
        //        queryParamsGET.putAll(params.getControlParameters());
        //
        //        Map<String, String> queryParamsPOST = new HashMap<String, String>();
        //        queryParamsPOST.putAll(params.getCommonParameters());
        //        queryParamsPOST.putAll(params.getControlParameters());

        // Navigation aid (really this is a poor version of pagination)
        Division jump = div.addInteractiveDivision("browse-navigation", BROWSE_URL_BASE, Division.METHOD_POST,
                "secondary navigation");

        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put(FACET_FIELD, getParameterField());
        //parameters.put(OFFSET, "0");
        parameters.put(PAGE, Integer.toString(getParameterPage()));

        parameters.put(SORT_BY, getParameterSortBy());
        parameters.put(ORDER, getParameterOrder().toString());
        parameters.put(RESULTS_PER_PAGE, Integer.toString(getParameterRpp()));
        parameters.put(VIEW, getParameterView());

        // Add all the query parameters as hidden fields on the form
        for (String key : parameters.keySet())
            jump.addHidden(key).setValue(parameters.get(key));

        // Remove 'page' parameter from jump list
        parameters.remove(PAGE);

        // If this is a date based browse, render the date navigation
        if (type != null && type.startsWith("date")) {
            org.dspace.app.xmlui.wing.element.List jumpList = jump.addList("jump-list",
                    org.dspace.app.xmlui.wing.element.List.TYPE_SIMPLE, "centuries");
            jumpList.setHead(T_jump_century_head);

            for (int i = 2100; i >= 1500; i -= 100) {
                //                parameters.put(STARTS_WITH, Character.toString(c));
                parameters.put("fq", type + ":[" + (i - 99) + "+TO+" + (i) + "]");
                // Add the filter queries
                String url = generateURL(BROWSE_URL_BASE, parameters);
                String[] fqs = getParameterFacetQueries();
                if (fqs != null) {
                    for (String fq : fqs) {
                        if (!fq.startsWith(type))
                            url += "&fq=" + fq;
                    }
                }
                int cent = (i / 100);
                jumpList.addItemXref(url, T_jump_century.parameterize(cent));
            }

            // Create a free text entry box for the year
            Para jumpForm = jump.addPara();
            jumpForm.addContent(T_jump_year);
            jumpForm.addText(STARTS_WITH).setHelp(T_jump_year_help);

            jumpForm.addButton("submit").setValue(T_go);
        } else {
            // Create a clickable list of the alphabet
            org.dspace.app.xmlui.wing.element.List jumpList = jump.addList("jump-list",
                    org.dspace.app.xmlui.wing.element.List.TYPE_SIMPLE, "alphabet");

            // browse params for each letter are all the query params
            // WITHOUT the second-stage browse value, and add STARTS_WITH.
            //            Map<String, String> letterQuery = new HashMap<String, String>(queryParamsGET);
            //            for (String valueKey : BrowseParams.FILTER_VALUE)
            //            {
            //                letterQuery.remove(valueKey);
            //            }
            parameters.put(STARTS_WITH, "0");
            String url = generateURL(BROWSE_URL_BASE, parameters);
            String[] fqs = getParameterFacetQueries();
            if (fqs != null) {
                for (String fq : fqs) {
                    url += "&fq=" + fq;
                }
            }
            jumpList.addItemXref(url, "0-9");
            //jumpList.addItemXref(super.generateURL(BROWSE_URL_BASE, letterQuery), "0-9");

            for (char c = 'A'; c <= 'Z'; c++) {
                parameters.put(STARTS_WITH, Character.toString(c));
                // Add the filter queries
                url = generateURL(BROWSE_URL_BASE, parameters);
                fqs = getParameterFacetQueries();
                if (fqs != null) {
                    for (String fq : fqs) {
                        url += "&fq=" + fq;
                    }
                }
                jumpList.addItemXref(url, Character.toString(c));
            }

            // Create a free text field for the initial characters
            Para jumpForm = jump.addPara();
            jumpForm.addContent(T_starts_with);
            jumpForm.addText(STARTS_WITH).setHelp(T_starts_with_help);

            jumpForm.addButton("submit").setValue(T_go);
        }

    }

    /**
     * Add the controls to changing sorting and display options.
     *
     * @param div
     * @param info
     * @param params
     * @throws WingException
     */
    private void addBrowseControls(Division div, FacetField field, Request request) throws WingException {
        // Prepare a Map of query parameters required for all links
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put(FACET_FIELD, getParameterField());
        //parameters.put(OFFSET, getParameterOffset());

        Division controlsDiv = div.addInteractiveDivision("browse-controls", BROWSE_URL_BASE, Division.METHOD_GET,
                "secondary search");

        for (String par : parameters.keySet())
            controlsDiv.addHidden(par).setValue(parameters.get(par));

        Table controlsTable = controlsDiv.addTable("browse-controls", 1, 3);
        //Table controlsTable = controlsDiv.addTable("browse-controls", 1, 4);
        Row controlsRow = controlsTable.addRow(Row.ROLE_DATA);

        // Create a control for the type of view to display
        Cell viewCell = controlsRow.addCell();
        try {
            viewCell.addContent(T_view);
            Select viewSelect = viewCell.addSelect("view");
            for (String v : VIEW_TYPES) {
                viewSelect.addOption((v.equals(getParameterView())), v,
                        message("xmlui.ArtifactBrowser.AbstractSearch.view." + v));
            }
        } catch (Exception e) {
            throw new WingException("Unable to get view options", e);
        }

        // Create a control for the number of records to display
        Cell rppCell = controlsRow.addCell();
        rppCell.addContent(T_rpp);
        Select rppSelect = rppCell.addSelect("rpp");
        for (int i : RESULTS_PER_PAGE_PROGRESSION) {
            rppSelect.addOption((i == getParameterRpp()), i, Integer.toString(i));
        }

        /*
        Cell groupCell = controlsRow.addCell();
        try {
        // Create a drop down of the different sort columns available
        groupCell.addContent(T_group_by);
        Select groupSelect = groupCell.addSelect("group_by");
        groupSelect.addOption(false, "none", T_group_by_none);
            
            
        String[] groups = {"publication_grp"};
        for (String group : groups) {
            groupSelect.addOption(group.equals(getParameterGroup()), group,
                    message("xmlui.ArtifactBrowser.AbstractSearch.group_by." + group));
        }
            
        }
        catch (Exception se) {
        throw new WingException("Unable to get group options", se);
        }
        */

        // Sorting does not make sense in browsing.
        //        Cell sortCell = controlsRow.addCell();
        //        try {
        //            // Create a drop down of the different sort columns available
        //            sortCell.addContent(T_sort_by);
        //            Select sortSelect = sortCell.addSelect("sort_by");
        //            sortSelect.addOption(false, "score", T_sort_by_relevance);
        //            for (SortOption so : SortOption.getSortOptions()) {
        //                if (so.isVisible()) {
        //                    sortSelect.addOption((so.getMetadata().equals(getParameterSortBy())), so.getMetadata(),
        //                            message("xmlui.ArtifactBrowser.AbstractSearch.sort_by." + so.getName()));
        //                }
        //            }
        //        }
        //        catch (SortException se) {
        //            throw new WingException("Unable to get sort options", se);
        //        }

        // Create a control to changing ascending / descending order
        Cell orderCell = controlsRow.addCell();
        orderCell.addContent(T_order);
        Select orderSelect = orderCell.addSelect("order");
        orderSelect.addOption(SolrQuery.ORDER.asc.equals(getParameterOrder()), SolrQuery.ORDER.asc.toString(),
                T_order_asc);
        orderSelect.addOption(SolrQuery.ORDER.desc.equals(getParameterOrder()), SolrQuery.ORDER.desc.toString(),
                T_order_desc);

        // Create a control for the number of authors per item to display
        // FIXME This is currently disabled, as the supporting functionality
        // is not currently present in xmlui
        //if (isItemBrowse(info))
        //{
        //    controlsForm.addContent(T_etal);
        //    Select etalSelect = controlsForm.addSelect(BrowseParams.ETAL);
        //
        //    etalSelect.addOption((info.getEtAl() < 0), 0, T_etal_all);
        //    etalSelect.addOption(1 == info.getEtAl(), 1, Integer.toString(1));
        //
        //    for (int i = 5; i <= 50; i += 5)
        //    {
        //        etalSelect.addOption(i == info.getEtAl(), i, Integer.toString(i));
        //    }
        //}

        //        controlsForm.addButton("update").setValue(T_update);
        //        query.addPara(null, "button-list").addButton("submit").setValue(T_go);
        controlsDiv.addPara(null, "button-list").addButton("update").setValue(T_update);

    }

    /**
     * Recycle
     */
    @Override
    public void recycle() {
        // Clear out our item's cache.
        this.queryResults = null;
        this.validity = null;
        super.recycle();
    }

    public String getParameterField() {
        Request request = ObjectModelHelper.getRequest(objectModel);
        String facetField = request.getParameter(FACET_FIELD);
        // There is already a configuration option for this: solr.browse.default.filter.
        // Can't make above option work as desired. Rolling back to the option below.
        if (facetField == null) {
            facetField = SearchUtils.getConfig().getString("solr.facets.default", "dc.title");
        }
        return facetField;
    }

    public String[] getParameterFacetQueries() {
        Request request = ObjectModelHelper.getRequest(objectModel);
        return request.getParameterValues("fq") != null ? request.getParameterValues("fq") : new String[0];
    }

    public String getParameterStartsWith() {
        String s = ObjectModelHelper.getRequest(objectModel).getParameter(STARTS_WITH);
        return s != null ? s : "";
    }

    protected String getParameterView() {
        String s = ObjectModelHelper.getRequest(objectModel).getParameter(VIEW);
        return s != null ? s : VIEW_TYPES[0];
    }

    protected int getParameterPage() {
        try {
            int page = Integer.parseInt(ObjectModelHelper.getRequest(objectModel).getParameter(PAGE));
            return page > 0 ? page : 1;
        } catch (Exception e) {
            return 1;
        }
    }

    protected int getParameterRpp() {
        try {
            int rpp = Integer.parseInt(ObjectModelHelper.getRequest(objectModel).getParameter(RESULTS_PER_PAGE));
            return rpp > 0 ? rpp : DEFAULT_PAGE_SIZE;
        } catch (Exception e) {
            return DEFAULT_PAGE_SIZE;
        }
    }

    protected String getParameterSortBy() {
        String s = ObjectModelHelper.getRequest(objectModel).getParameter(SORT_BY);
        //        return s != null ? s : DEFAULT_SORT_BY;
        return config.getPropertyAsType("solr.browse.sort", DEFAULT_SORT_BY);
    }

    //    protected String getParameterGroup() {
    //        String s = ObjectModelHelper.getRequest(objectModel).getParameter("group_by");
    //        return s != null ? s : "none";
    //    }

    protected SolrQuery.ORDER getParameterOrder() {
        String s = ObjectModelHelper.getRequest(objectModel).getParameter(ORDER);
        return s != null ? SolrQuery.ORDER.valueOf(s.toLowerCase()) : DEFAULT_ORDER;
    }

}