/**
* $Id: SimpleSearch.java 5165 2010-07-02 14:11:04Z KevinVandeVelde $
* $URL: http://scm.dspace.org/svn/repo/modules/dspace-discovery/trunk/block/src/main/java/org/dspace/app/xmlui/aspect/discovery/SimpleSearch.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;
/*
* SimpleSearch.java
*
* Version: $Revision: 5165 $
*
* Date: $Date: 2010-07-02 11:11:04 -0300 (Fri, 02 Jul 2010) $
*
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
* Institute of Technology. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.net.URLEncoder;
import java.util.Collection;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.dspace.app.xmlui.utils.HandleUtil;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.*;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.*;
import org.dspace.core.ConfigurationManager;
import org.dspace.discovery.SearchUtils;
import org.xml.sax.SAXException;
import org.dspace.discovery.SearchServiceException;
import org.dspace.discovery.SolrServiceImpl;
import org.dspace.core.Constants;
/**
* Preform a simple search of the repository. The user provides a simple one
* field query (the url parameter is named query) and the results are processed.
*
* @author mdiggory at atmire.com
* @author kevinvandevelde at atmire.com
*/
public class SimpleSearch extends AbstractSearch implements CacheableProcessingComponent {
private static final Logger log = Logger.getLogger(SimpleSearch.class);
/**
* Language Strings
*/
private static final Message T_title =
message("xmlui.ArtifactBrowser.SimpleSearch.title");
private static final Message T_dspace_home =
message("xmlui.general.dspace_home");
private static final Message T_trail =
message("xmlui.ArtifactBrowser.SimpleSearch.trail");
private static final Message T_head =
message("xmlui.ArtifactBrowser.SimpleSearch.head");
private static final Message T_search_scope =
message("xmlui.ArtifactBrowser.SimpleSearch.search_scope");
private static final Message T_full_text_search =
message("xmlui.ArtifactBrowser.SimpleSearch.full_text_search");
private static final Message T_go =
message("xmlui.general.go");
private static final Message T_FILTER_HELP = message("xmlui.Discovery.SimpleSearch.filter_help");
private static final Message T_FILTER_HEAD = message("xmlui.Discovery.SimpleSearch.filter_head");
/**
* Add Page metadata.
*/
public void addPageMeta(PageMeta pageMeta) throws WingException, SQLException {
pageMeta.addMetadata("title").addContent(T_title);
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(T_trail);
// Add hit highlighting information
//Map<String, Map<String, java.util.List<String>>> hl = queryResults.getHighlighting();
//log.debug("hl: " + hl.toString());
if (queryArgs != null) {
log.debug("queryArgs: " + queryArgs.toString());
//The search url must end with a /
String searchUrl = SearchUtils.getConfig().getString("solr.search.server");
if (searchUrl != null && !searchUrl.endsWith("/")) {
searchUrl += "/";
}
String q = queryArgs.toString();
q = "select?wt=xslt&tr=DRI.xsl&" + q;
pageMeta.addMetadata("search", "hitHighlighting").addContent(searchUrl + q);
log.debug("HL: " + searchUrl + q);
} else {
log.debug("queryArgs == NULL");
}
}
/**
* build the DRI page representing the body of the search query. This
* provides a widget to generate a new query and list of search results if
* present.
*/
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException {
String queryString = getQuery();
// Build the DRI Body
Division search = body.addDivision("search", "primary");
search.setHead(T_head);
//The search url must end with a /
String searchUrl = SearchUtils.getConfig().getString("solr.search.server");
if (searchUrl != null && !searchUrl.endsWith("/")) {
searchUrl += "/";
}
search.addHidden("solr-search-url").setValue(searchUrl);
Request request = ObjectModelHelper.getRequest(objectModel);
java.util.List<String> fqs = new ArrayList<String>();
if (request.getParameterValues("fq") != null) {
fqs.addAll(Arrays.asList(request.getParameterValues("fq")));
}
//Have we added a filter using the UI
// BUG: was "search-filter-controls_add" instead of "submit_search-filter-controls_add".
if (request.getParameter("filter") != null && !"".equals(request.getParameter("filter")) && request.getParameter("submit_search-filter-controls_add") != null) {
fqs.add((request.getParameter("filtertype").equals("*") ? "" : request.getParameter("filtertype") + ":") + request.getParameter("filter"));
}
Division query = search.addInteractiveDivision("general-query",
"search", Division.METHOD_GET, "secondary search");
List queryList = query.addList("search-query", List.TYPE_FORM);
/*
if (variableScope()) {
Select scope = queryList.addItem().addSelect("scope");
scope.setLabel(T_search_scope);
buildScopeList(scope);
}
*/
Text text = queryList.addItem().addText("query");
text.setLabel(T_full_text_search);
text.setValue(queryString);
// queryList.addItem().addContent("Filters");
//If we have any filters, show them
if (fqs.size() > 0) {
//if(filters != null && filters.size() > 0){
Composite composite = queryList.addItem().addComposite("facet-controls");
composite.setLabel(message("xmlui.ArtifactBrowser.SimpleSearch.selected_filters"));
CheckBox box = composite.addCheckBox("fq");
for (String name : fqs) {
//for(Map.Entry<String, Integer> filter : filters.entrySet()){
//String name = filter.getKey();
//long count = filter.getValue();
String field = name;
String value = name;
if (name.contains(":")) {
field = name.split(":")[0];
value = name.split(":")[1];
} else {
//We have got no field, so we are using everything
field = "*";
}
field = field.replace("_lc", "");
value = value.replace("\\", "");
if (field.equals("*")) {
field = "all";
}
if (name.startsWith("*:")) {
name = name.substring(name.indexOf(":") + 1, name.length());
}
Option option = box.addOption(true, name);
option.addContent(message("xmlui.ArtifactBrowser.SimpleSearch.filter." + field));
if (field.equals("location.comm") || field.equals("location.coll")) {
//We have a community/collection, resolve it to a dspaceObject
value = SolrServiceImpl.locationToName(context, field, value);
}
option.addContent(": " + value);
}
}
int i = 1;
String field = SearchUtils.getConfig().getString("solr.search.filter.type." + i, null);
if (field != null) {
//We have at least one filter so add our filter box
Item item = queryList.addItem("search-filter-list", "search-filter-list");
Composite filterComp = item.addComposite("search-filter-controls");
filterComp.setLabel(T_FILTER_HEAD);
filterComp.setHelp(T_FILTER_HELP);
// filterComp.setLabel("");
Select select = filterComp.addSelect("filtertype");
//First of all add a default filter
select.addOption("*", message("xmlui.ArtifactBrowser.SimpleSearch.filter.all"));
//For each field found (at least one) add options
while (field != null) {
select.addOption(field, message("xmlui.ArtifactBrowser.SimpleSearch.filter." + field));
field = SearchUtils.getConfig().getString("solr.search.filter.type." + ++i, null);
}
//Add a box so we can search for our value
Text fieldText = filterComp.addText("filter");
//And last add an add button
filterComp.enableAddOperation();
}
buildSearchControls(query);
query.addPara(null, "button-list").addButton("submit").setValue(T_go);
// Build the DRI Body
//Division results = body.addDivision("results", "primary");
//results.setHead(T_head);
// Add the result division
try {
buildSearchResultsDivision(search);
} catch (SearchServiceException e) {
throw new UIException(e.getMessage(), e);
}
}
protected String[] getParameterFacetQueries() {
try {
java.util.List<String> allFilterQueries = new ArrayList<String>();
Request request = ObjectModelHelper.getRequest(objectModel);
if (request.getParameterValues("fq") != null) {
for (int i = 0; i < request.getParameterValues("fq").length; i++) {
String fq = request.getParameterValues("fq")[i];
log.debug("fq: " + fq);
// BUG: adding a '*' breaks queries like date range.
//allFilterQueries.add(fq + "*");
//log.debug("allFilterQueries.add: " + fq + "*");
allFilterQueries.add(fq);
}
}
String type = request.getParameter("filtertype");
String value = request.getParameter("filter");
// BUG: was "search-filter-controls_add" instead of "submit_search-filter-controls_add".
if (value != null && !value.equals("") && request.getParameter("submit_search-filter-controls_add") != null) {
// BUG: adding a '*' breaks queries with ranges and with sint field types.
allFilterQueries.add((type.equals("*") ? "" : type + ":") + value); // + "*");
log.debug("allFilterQueries.add 2nd: " + (type.equals("*") ? "" : type + ":") + value + "*");
}
return allFilterQueries.toArray(new String[allFilterQueries.size()]);
} catch (Exception e) {
return null;
}
}
/**
* Get the search query from the URL parameter, if none is found the empty
* string is returned.
*/
protected String getQuery() throws UIException {
Request request = ObjectModelHelper.getRequest(objectModel);
String query = URLDecode(request.getParameter("query"));
if (query == null) {
return "";
}
return query.trim();
}
/**
* 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));
}
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("rpp") == null) {
parameters.put("rpp", 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", getParameterOrder());
}
if (parameters.get("etal") == null) {
parameters.put("etal", String.valueOf(getParameterEtAl()));
}
return super.generateURL("search", parameters);
}
}