diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/Controllers.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/Controllers.java index fc6c0c100..af26a622d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/Controllers.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/Controllers.java @@ -70,14 +70,14 @@ public class Controllers { public static final String TAB_PRIMARY_JSP = "/templates/tabs/tabprimary.jsp"; public static final String ALPHA_INDEX_JSP = "/templates/alpha/alphaIndex.jsp"; - public static final String SEARCH_BASIC_JSP = "/templates/search/searchBasic.jsp"; public static final String SEARCH_PAGED_JSP = "/templates/search/searchPaged.jsp"; public static final String SEARCH_FAILED_JSP = "/templates/search/searchFailed.jsp"; public static final String SEARCH_GROUP_JSP = "/templates/search/searchGroup.jsp"; public static final Object SEARCH_FORM_JSP = "/templates/search/searchForm.jsp"; - + public static final Object SEARCH_BAD_QUERY_JSP = "/templates/search/searchBadQuery.jsp"; + public static final String BROWSE_GROUP_JSP = "/templates/browse/browseGroup.jsp"; public static final String HORIZONTAL_JSP = "/templates/edit/fetch/horizontal.jsp"; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/FreemarkerPagedSearchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/FreemarkerPagedSearchController.java index 380da7cfe..a5bd4ff15 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/FreemarkerPagedSearchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/FreemarkerPagedSearchController.java @@ -27,6 +27,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.Term; +import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; @@ -72,7 +73,6 @@ import edu.cornell.mannlib.vitro.webapp.utils.Html2Text; import edu.cornell.mannlib.vitro.webapp.utils.StringUtils; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.IndividualTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.LinkTemplateModel; -import freemarker.template.Configuration; /** * PagedSearchController is the new search controller that interacts @@ -88,14 +88,26 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(FreemarkerPagedSearchController.class.getName()); - private static final String TEMPLATE_SEARCH_RESULTS = "search-pagedResults.ftl"; - private static final String TEMPLATE_ERROR = "search-error.ftl"; - - String NORESULT_MSG = "The search returned no results."; - private IndexSearcher searcher = null; private int defaultHitsPerPage = 25; private int defaultMaxSearchSize= 1000; + + protected enum SearchTemplate { + PAGED_RESULTS("search-pagedResults.ftl"), + FORM("search-form.ftl"), + ERROR("search-error.ftl"), + BAD_QUERY("search-badQuery.ftl"); + + private final String filename; + + SearchTemplate(String filename) { + this.filename = filename; + } + + public String toString() { + return filename; + } + } public void init(ServletConfig config) throws ServletException { super.init(config); @@ -158,13 +170,15 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple String qtxt = vreq.getParameter(VitroQuery.QUERY_PARAMETER_NAME); Analyzer analyzer = getAnalyzer(getServletContext()); - Query query = getQuery(vreq, portalFlag, analyzer, indexDir, qtxt); - log.debug("query for '" + qtxt +"' is " + query.toString()); - - if (query == null ) { - return doNoQuery(portal); - } + Query query = null; + try { + query = getQuery(vreq, portalFlag, analyzer, indexDir, qtxt); + log.debug("query for '" + qtxt +"' is " + query.toString()); + } catch (ParseException e) { + return doBadQuery(portal, qtxt); + } + IndexSearcher searcherForRequest = getIndexSearcher(indexDir); TopDocs topDocs = null; @@ -295,7 +309,7 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple return doSearchError(e); } - return new TemplateResponseValues(TEMPLATE_SEARCH_RESULTS, body); + return new TemplateResponseValues(SearchTemplate.PAGED_RESULTS.toString(), body); } private void alphaSortIndividuals(List beans) { @@ -510,7 +524,7 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple } private Query getQuery(VitroRequest request, PortalFlag portalState, - Analyzer analyzer, String indexDir, String querystr ) throws SearchException{ + Analyzer analyzer, String indexDir, String querystr ) throws SearchException, ParseException { Query query = null; try{ //String querystr = request.getParameter(VitroQuery.QUERY_PARAMETER_NAME); @@ -572,7 +586,9 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple log.debug("Query: " + query); - }catch (Exception ex){ + } catch (ParseException e) { + throw new ParseException(e.getMessage()); + } catch (Exception ex){ throw new SearchException(ex.getMessage()); } @@ -756,20 +772,20 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple private TemplateResponseValues doSearchError(String message) { Map body = new HashMap(); body.put("message", "Search failed: " + message); - return new TemplateResponseValues(TEMPLATE_ERROR, body); + return new TemplateResponseValues(SearchTemplate.ERROR.toString(), body); } private ExceptionResponseValues doSearchError(Throwable e) { Map body = new HashMap(); body.put("message", "Search failed: " + e.getMessage()); - return new ExceptionResponseValues(TEMPLATE_ERROR, body, e); + return new ExceptionResponseValues(SearchTemplate.ERROR.toString(), body, e); } - private TemplateResponseValues doNoQuery(Portal portal) { + private TemplateResponseValues doBadQuery(Portal portal, String query) { Map body = new HashMap(); body.put("title", "Search " + portal.getAppName()); - body.put("message", "No query entered."); - return new TemplateResponseValues(TEMPLATE_ERROR, body); + body.put("query", query); + return new TemplateResponseValues(SearchTemplate.BAD_QUERY.toString(), body); } private TemplateResponseValues doFailedSearch(String message, String querytext) { @@ -779,14 +795,14 @@ public class FreemarkerPagedSearchController extends FreemarkerHttpServlet imple message = "Search failed."; } body.put("message", message); - return new TemplateResponseValues(TEMPLATE_ERROR, body); + return new TemplateResponseValues(SearchTemplate.ERROR.toString(), body); } private TemplateResponseValues doNoHits(String querytext) { Map body = new HashMap(); body.put("title", "Search for '" + querytext + "'"); body.put("message", "No matching results."); - return new TemplateResponseValues(TEMPLATE_ERROR, body); + return new TemplateResponseValues(SearchTemplate.ERROR.toString(), body); } /** diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 89f50e00e..664e6fd9f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -29,6 +29,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.Term; +import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; @@ -150,13 +151,17 @@ public class PagedSearchController extends VitroHttpServlet implements Searcher{ String qtxt = vreq.getParameter(VitroQuery.QUERY_PARAMETER_NAME); Analyzer analyzer = getAnalyzer(getServletContext()); - Query query = getQuery(vreq, portalFlag, analyzer, indexDir, qtxt); - log.debug("query for '" + qtxt +"' is " + query.toString()); - - if (query == null ) { - doNoQuery(request, response); + + Query query = null; + try { + query = getQuery(vreq, portalFlag, analyzer, indexDir, qtxt); + } catch (ParseException e) { + log.warn("Query parse exception: " + e); + doBadQuery(qtxt, request, response); return; - } + } + + log.debug("query for '" + qtxt +"' is " + query.toString()); IndexSearcher searcherForRequest = getIndexSearcher(indexDir); @@ -426,7 +431,7 @@ public class PagedSearchController extends VitroHttpServlet implements Searcher{ } private Query getQuery(VitroRequest request, PortalFlag portalState, - Analyzer analyzer, String indexDir, String querystr ) throws SearchException{ + Analyzer analyzer, String indexDir, String querystr ) throws SearchException, ParseException { Query query = null; try{ //String querystr = request.getParameter(VitroQuery.QUERY_PARAMETER_NAME); @@ -495,8 +500,10 @@ public class PagedSearchController extends VitroHttpServlet implements Searcher{ } log.debug("Query: " + query); - - }catch (Exception ex){ + + } catch (ParseException e) { + throw new ParseException(e.getMessage()); + } catch (Exception ex){ throw new SearchException(ex.getMessage()); } @@ -677,12 +684,13 @@ public class PagedSearchController extends VitroHttpServlet implements Searcher{ } } - private void doNoQuery(HttpServletRequest request, + private void doBadQuery(String queryStr, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Portal portal = (new VitroRequest(request)).getPortal(); request.setAttribute("title", "Search "+portal.getAppName()); - request.setAttribute("bodyJsp", Controllers.SEARCH_FORM_JSP); + request.setAttribute("bodyJsp", Controllers.SEARCH_BAD_QUERY_JSP); + request.setAttribute("queryStr", queryStr); RequestDispatcher rd = request .getRequestDispatcher(Controllers.BASIC_JSP); diff --git a/webapp/web/templates/freemarker/body/search/search-badQuery.ftl b/webapp/web/templates/freemarker/body/search/search-badQuery.ftl new file mode 100644 index 000000000..e562be68f --- /dev/null +++ b/webapp/web/templates/freemarker/body/search/search-badQuery.ftl @@ -0,0 +1,7 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +
+

Your query '${query}' was invalid. Please modify your search and try again.

+ + <#include "search-form.ftl"> +
\ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/search/search-form.ftl b/webapp/web/templates/freemarker/body/search/search-form.ftl new file mode 100644 index 000000000..15c23e9a6 --- /dev/null +++ b/webapp/web/templates/freemarker/body/search/search-form.ftl @@ -0,0 +1,19 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +
+ +
+
+

Search

+ +

+
+
+ +
+ <#include "search-help.ftl"> +
+ +
+ +${stylesheets.addFromTheme("/css/search.css")} \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/search/search-help.ftl b/webapp/web/templates/freemarker/body/search/search-help.ftl new file mode 100644 index 000000000..32a190884 --- /dev/null +++ b/webapp/web/templates/freemarker/body/search/search-help.ftl @@ -0,0 +1,18 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +

Search Tips

+
    +
  • Use short, single terms unless your searches are returning too many results
  • +
  • When you enter more than one term, the search will look for records containing all of them unless you add the word "OR" between your terms.
  • +
  • "NOT" can help limit searches -- e.g., climate NOT change
  • +
  • Except for boolean operators, searches are not case-sensitive, so "Geneva" and "geneva" are equivalent
  • +
  • Enclose a phrase in quotes (") to search for the whole phrase, not individual words (e.g., "protein folding") -- both leading and ending quotes are required
  • +
  • Phrase searches may be combined with boolean operators: "climate change" OR "global warming"
  • +
  • The search uses stemming by default so that close word variations will also be found (e.g., "sequence" also matches "sequences" and "sequencing"). + Use the wildcard * character to match wider variation (e.g., nano* to match both + nanotechnology and nanofabrication), but note that searching uses stemmed, or shortened, versions of words, + so "cogniti*" finds nothing while "cognit*" finds both cognitive and cognition
  • +
  • If you're not sure of the spelling, put a ~ at the end -- e.g., cabage~ finds cabbage, + steven~ finds Stephen and Stefan (as well as a few unwanted extra words)
  • +
  • To match a person or unit's primary entry, enter name: Smith or name: Biology
  • +
\ No newline at end of file diff --git a/webapp/web/templates/search/searchBadQuery.jsp b/webapp/web/templates/search/searchBadQuery.jsp new file mode 100644 index 000000000..bed52f467 --- /dev/null +++ b/webapp/web/templates/search/searchBadQuery.jsp @@ -0,0 +1,35 @@ +<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%> + +<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %><%/* this odd thing points to something in web.xml */ %> +<%@ page errorPage="/error.jsp"%> +<% /*********************************************** + Used when the search results are empty. + + request.attributes: + + request.parameters: + None yet. + + Consider sticking < % = MiscWebUtils.getReqInfo(request) % > in the html output + for debugging info. + + **********************************************/ +%> + + + + + + +
+
+

+ + +

+ + +
+