/** * 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.xmlui.aspect.artifactbrowser; import org.apache.cocoon.environment.Request; import org.apache.oro.text.perl.Perl5Util; import org.dspace.app.xmlui.utils.UIException; import org.dspace.core.Constants; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; /** * Central place where advanced search queries can be built since these are built on several places * * @author Kevin Van de Velde (kevin at atmire dot com) * @author Ben Bosman (ben at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * * @deprecated Since DSpace 4 the system use an abstraction layer named * Discovery to provide access to different search providers. The * legacy system built upon Apache Lucene is likely to be removed in * a future version. If you are interested in using Lucene as backend * for the DSpace search system, please consider to build a Lucene * implementation of the Discovery interfaces */ @Deprecated public class AdvancedSearchUtils { private static final int FIELD_MAX_COUNT = 12; /** * Given a list of search fields build a lucene search query string. * * @param fields The search fields * @return A string */ public static String buildQuery(java.util.List<SearchField> fields) { Perl5Util util = new Perl5Util(); StringBuilder query = new StringBuilder(); query.append("("); // Loop through the fields building the search query as we go. for (SearchField field : fields) { // if the field is empty, then skip it and try a later one. if (field.getQuery() == null) { continue; } // Add the conjunction for everything but the first field. if (fields.indexOf(field) > 0) { query.append(" ").append(field.getConjunction()).append(" "); } // Two cases, one if a specific search field is specified or if // ANY is given then just a general search is performed. if ("ANY".equals(field.getField())) { // No field specified, query.append("(").append(field.getQuery()).append(")"); } else { // Specific search field specified, add the field specific field. // Replace single quotes with double quotes (only if they match) String subQuery = util.substitute("s/\'(.*)\'/\"$1\"/g", field.getQuery()); // If the field is not quoted ... if (!util.match("/\".*\"/", subQuery)) { // ... then separate each word and re-specify the search field. subQuery = util.substitute("s/[ ]+/ " + field.getField() + ":/g", subQuery); } // Put the subQuery into the general query query.append("(").append(field.getField()).append(":").append(subQuery).append(")"); } } if (query.length() == 1) { return ""; } return query.append(")").toString(); } /** * Get a list of search fields from the request object * and parse them into a linear array of fileds. The field's * index is preserved, so if it comes in as index 17 it will * be outputted as field 17. * * @param request The http request object * @return Array of search fields * @throws org.dspace.app.xmlui.utils.UIException */ public static java.util.List<SearchField> getSearchFields(Request request) throws UIException { // Get how many fields to search int numSearchField; try { String numSearchFieldStr = request.getParameter("num_search_field"); numSearchField = Integer.valueOf(numSearchFieldStr); } catch (NumberFormatException nfe) { numSearchField = FIELD_MAX_COUNT; } // Iterate over all the possible fields and add each one to the list of fields. ArrayList<SearchField> fields = new ArrayList<SearchField>(); for (int i = 1; i <= numSearchField; i++) { String field = request.getParameter("field"+i); String query = decodeFromURL(request.getParameter("query"+i)); String conjunction = request.getParameter("conjunction"+i); if (field != null) { field = field.trim(); if (field.length() == 0) { field = null; } } if (query != null) { query = query.trim(); if (query.length() == 0) { query = null; } } if (conjunction != null) { conjunction = conjunction.trim(); if (conjunction.length() == 0) { conjunction = null; } } if (field == null) { field = "ANY"; } if (conjunction == null) { conjunction = "AND"; } if (query != null) { fields.add(new SearchField(i, field, query, conjunction)); } } return fields; } /** * A private record keeping class to relate the various * components of a search field together. */ public static class SearchField { /** What index the search field is, typically there are just three - but the theme may expand this number */ private int index; /** The field to search, ANY if none specified */ private String field; /** The query string to search for */ private String query; /** the conjunction: either "AND" or "OR" */ private String conjuction; public SearchField(int index, String field, String query, String conjunction) { this.index = index; this.field = field; this.query = query; this.conjuction = conjunction; } public int getIndex() { return this.index;} public String getField() { return this.field;} public String getQuery() { return this.query;} public String getConjunction() { return this.conjuction;} } /** * Decode the given string from URL transmission. * * @param encodedString * The encoded string. * @return The unencoded string */ private static String decodeFromURL(String encodedString) throws UIException { if (encodedString == null) { return null; } try { // Percent(%) is a special character, and must first be escaped as %25 if (encodedString.contains("%")) { encodedString = encodedString.replace("%", "%25"); } return URLDecoder.decode(encodedString, Constants.DEFAULT_ENCODING); } catch (UnsupportedEncodingException uee) { throw new UIException(uee); } } }