From d86af20a5a0a8328b6def217401f0f0ba3a585c9 Mon Sep 17 00:00:00 2001 From: Graham Triggs Date: Thu, 10 Jan 2008 14:03:36 +0000 Subject: [PATCH] First part of search update - reduce search size, add in fields for sorting content, lessen dependency on handles git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@2508 9c30dcfa-912a-0410-8fc2-9e0234be79fd --- ...terBOD.java => AbstractTextFilterOFD.java} | 9 +- .../java/org/dspace/browse/BrowseEngine.java | 8 +- .../java/org/dspace/browse/BrowseIndex.java | 132 +++---- .../java/org/dspace/browse/BrowseInfo.java | 2 +- .../java/org/dspace/browse/BrowserScope.java | 99 +++--- .../java/org/dspace/browse/IndexBrowse.java | 138 +++++--- .../org/dspace/content/ItemComparator.java | 4 +- .../java/org/dspace/search/DSAnalyzer.java | 11 + .../java/org/dspace/search/DSIndexer.java | 326 ++++++++++-------- .../main/java/org/dspace/search/DSQuery.java | 86 +++-- .../java/org/dspace/search/QueryArgs.java | 25 ++ .../java/org/dspace/search/QueryResults.java | 16 +- .../OrderFormat.java} | 46 +-- .../OrderFormatAuthor.java} | 7 +- .../OrderFormatDelegate.java} | 6 +- .../OrderFormatText.java} | 7 +- .../OrderFormatTitle.java} | 7 +- .../OrderFormatTitleMarc21.java} | 7 +- .../java/org/dspace/sort/SortException.java | 68 ++++ .../dspace/{browse => sort}/SortOption.java | 34 +- .../components/RecentSubmissionsManager.java | 8 +- .../app/webui/jsptag/BrowseListTag.java | 1 + .../webui/servlet/AbstractBrowserServlet.java | 8 +- .../dspace/app/webui/servlet/FeedServlet.java | 8 +- .../webui/servlet/SimpleSearchServlet.java | 19 + .../webui/servlet/admin/ItemMapServlet.java | 1 + dspace-jspui/src/main/webapp/browse/full.jsp | 3 +- .../src/main/webapp/layout/navbar-admin.jsp | 2 +- .../aspect/administrative/WithdrawnItems.java | 7 +- .../artifactbrowser/CollectionViewer.java | 8 +- .../artifactbrowser/CommunityViewer.java | 8 +- .../artifactbrowser/ConfigurableBrowse.java | 39 ++- .../app/xmlui/cocoon/DSpaceFeedGenerator.java | 2 +- dspace/config/dspace.cfg | 24 +- 34 files changed, 732 insertions(+), 444 deletions(-) rename dspace-api/src/main/java/org/dspace/browse/{AbstractTextFilterBOD.java => AbstractTextFilterOFD.java} (95%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrder.java => sort/OrderFormat.java} (74%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrderAuthor.java => sort/OrderFormatAuthor.java} (93%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrderDelegate.java => sort/OrderFormatDelegate.java} (96%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrderText.java => sort/OrderFormatText.java} (93%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrderTitle.java => sort/OrderFormatTitle.java} (93%) rename dspace-api/src/main/java/org/dspace/{browse/BrowseOrderTitleMarc21.java => sort/OrderFormatTitleMarc21.java} (92%) create mode 100644 dspace-api/src/main/java/org/dspace/sort/SortException.java rename dspace-api/src/main/java/org/dspace/{browse => sort}/SortOption.java (92%) diff --git a/dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterBOD.java b/dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterOFD.java similarity index 95% rename from dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterBOD.java rename to dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterOFD.java index 7ade579083..7d148e9c50 100644 --- a/dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterBOD.java +++ b/dspace-api/src/main/java/org/dspace/browse/AbstractTextFilterOFD.java @@ -1,5 +1,5 @@ /* - * AbstractTextFilterBOD.java + * AbstractTextFilterOFD.java * * Version: $Revision: 1.0 $ * @@ -42,6 +42,7 @@ package org.dspace.browse; import org.apache.log4j.Logger; import org.dspace.text.filter.TextFilter; +import org.dspace.sort.OrderFormatDelegate; /** * Helper class for creating order delegates. @@ -49,7 +50,7 @@ import org.dspace.text.filter.TextFilter; * To configure the filters create a subclass and, in an object initializer, * create an array of classes that implement TextFilter: * - * class MyLocaleDelegate extends AbstractTextFilterBOD { + * class MyLocaleDelegate extends AbstractTextFilterOFD { * { * filters = new TextFilter[] { new LocaleOrderingFilter(); } * } @@ -72,9 +73,9 @@ import org.dspace.text.filter.TextFilter; * * @author Graham Triggs */ -public abstract class AbstractTextFilterBOD implements BrowseOrderDelegate +public abstract class AbstractTextFilterOFD implements OrderFormatDelegate { - private final static Logger log = Logger.getLogger(AbstractTextFilterBOD.class); + private final static Logger log = Logger.getLogger(AbstractTextFilterOFD.class); // Initialised in subclass in an object initializer protected TextFilter[] filters; diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java index 2ad15f8efb..6351bd9074 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseEngine.java @@ -49,6 +49,8 @@ import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.core.Context; import org.dspace.core.LogManager; +import org.dspace.sort.SortOption; +import org.dspace.sort.OrderFormat; /** * This class does most of the actual grunt work of preparing a browse @@ -285,7 +287,7 @@ public class BrowseEngine rawValue = value; // make sure the incoming value is normalised - value = BrowseOrder.makeSortString(value, scope.getFilterValueLang(), + value = OrderFormat.makeSortString(value, scope.getFilterValueLang(), scope.getBrowseIndex().getDataType()); // set the values in the Browse Query @@ -737,12 +739,12 @@ public class BrowseEngine if (scope.hasJumpToValue()) { // Normalize it based on the specified language as appropriate for this index - return BrowseOrder.makeSortString(scope.getJumpToValue(), scope.setJumpToValueLang(), scope.getBrowseIndex().getDataType()); + return OrderFormat.makeSortString(scope.getJumpToValue(), scope.setJumpToValueLang(), scope.getBrowseIndex().getDataType()); } else if (scope.hasStartsWith()) { // Scope has a starts with, so normalize that instead - return BrowseOrder.makeSortString(scope.getStartsWith(), null, scope.getBrowseIndex().getDataType()); + return OrderFormat.makeSortString(scope.getStartsWith(), null, scope.getBrowseIndex().getDataType()); } // No focus value on the scope (ie. focus by id), so just return the passed focus value diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java b/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java index 44bbea481b..c0c34ebd48 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java @@ -41,12 +41,13 @@ package org.dspace.browse; import java.io.IOException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.dspace.core.ConfigurationManager; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; /** * This class holds all the information about a specifically configured @@ -113,7 +114,7 @@ public class BrowseIndex displayType = "item"; sortOption = SortOption.getDefaultSortOption(); } - catch (BrowseException be) + catch (SortException se) { // FIXME Exception handling } @@ -140,82 +141,89 @@ public class BrowseIndex private BrowseIndex(String definition, int number) throws BrowseException { - boolean valid = true; - this.defaultOrder = SortOption.ASCENDING; - this.number = number; - - String rx = "(\\w+):(\\w+):([\\w\\.\\*,]+):?(\\w*):?(\\w*)"; - Pattern pattern = Pattern.compile(rx); - Matcher matcher = pattern.matcher(definition); - - if (matcher.matches()) + try { - name = matcher.group(1); - displayType = matcher.group(2); - - if (isMetadataIndex()) + boolean valid = true; + this.defaultOrder = SortOption.ASCENDING; + this.number = number; + + String rx = "(\\w+):(\\w+):([\\w\\.\\*,]+):?(\\w*):?(\\w*)"; + Pattern pattern = Pattern.compile(rx); + Matcher matcher = pattern.matcher(definition); + + if (matcher.matches()) { - metadataAll = matcher.group(3); - datatype = matcher.group(4); + name = matcher.group(1); + displayType = matcher.group(2); - if (metadataAll != null) - metadata = metadataAll.split(","); - - if (metadata == null || metadata.length == 0) - valid = false; - - if (datatype == null || datatype.equals("")) - valid = false; - - // If an optional ordering configuration is supplied, - // set the defaultOrder appropriately (asc or desc) - if (matcher.groupCount() > 4) + if (isMetadataIndex()) { - String order = matcher.group(5); - if (SortOption.DESCENDING.equalsIgnoreCase(order)) - this.defaultOrder = SortOption.DESCENDING; + metadataAll = matcher.group(3); + datatype = matcher.group(4); + + if (metadataAll != null) + metadata = metadataAll.split(","); + + if (metadata == null || metadata.length == 0) + valid = false; + + if (datatype == null || datatype.equals("")) + valid = false; + + // If an optional ordering configuration is supplied, + // set the defaultOrder appropriately (asc or desc) + if (matcher.groupCount() > 4) + { + String order = matcher.group(5); + if (SortOption.DESCENDING.equalsIgnoreCase(order)) + this.defaultOrder = SortOption.DESCENDING; + } + + tableBaseName = makeTableBaseName(number); } - - tableBaseName = makeTableBaseName(number); - } - else if (isItemIndex()) - { - String sortName = matcher.group(3); - - for (SortOption so : SortOption.getSortOptions()) + else if (isItemIndex()) { - if (so.getName().equals(sortName)) - sortOption = so; - } + String sortName = matcher.group(3); - if (sortOption == null) + for (SortOption so : SortOption.getSortOptions()) + { + if (so.getName().equals(sortName)) + sortOption = so; + } + + if (sortOption == null) + valid = false; + + // If an optional ordering configuration is supplied, + // set the defaultOrder appropriately (asc or desc) + if (matcher.groupCount() > 3) + { + String order = matcher.group(4); + if (SortOption.DESCENDING.equalsIgnoreCase(order)) + this.defaultOrder = SortOption.DESCENDING; + } + + tableBaseName = getItemBrowseIndex().tableBaseName; + } + else + { valid = false; - - // If an optional ordering configuration is supplied, - // set the defaultOrder appropriately (asc or desc) - if (matcher.groupCount() > 3) - { - String order = matcher.group(4); - if (SortOption.DESCENDING.equalsIgnoreCase(order)) - this.defaultOrder = SortOption.DESCENDING; } - - tableBaseName = getItemBrowseIndex().tableBaseName; } else { valid = false; } + + if (!valid) + { + throw new BrowseException("Browse Index configuration is not valid: webui.browse.index." + + number + " = " + definition); + } } - else + catch (SortException se) { - valid = false; - } - - if (!valid) - { - throw new BrowseException("Browse Index configuration is not valid: webui.browse.index." + - number + " = " + definition); + throw new BrowseException("Error in SortOptions", se); } } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseInfo.java b/dspace-api/src/main/java/org/dspace/browse/BrowseInfo.java index f80317b71c..32baa900c0 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseInfo.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseInfo.java @@ -40,7 +40,6 @@ package org.dspace.browse; import java.sql.SQLException; -import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -51,6 +50,7 @@ import org.dspace.content.DCValue; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.sort.SortOption; /** * The results of a Browse, including all the contextual information about diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java index 0b6ad095bd..d6175f0e5f 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowserScope.java @@ -39,6 +39,8 @@ import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.core.Context; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.apache.log4j.Logger; /** @@ -404,53 +406,60 @@ public class BrowserScope public SortOption getSortOption() throws BrowseException { - // If a sortOption hasn't been set, work out the default - if (sortOption == null) - { - // We need a browse index first though - if (browseIndex != null) - { - // If a sorting hasn't been specified, and it's a metadata browse - if (sortBy <= 0 && browseIndex.isMetadataIndex()) - { - // Create a dummy sortOption for the metadata sort - String dataType = browseIndex.getDataType(); - String type = ("date".equals(dataType) ? "date" : "text"); - sortOption = new SortOption(0, browseIndex.getName(), browseIndex.getMetadata(0), type); - } - else - { - // If a sorting hasn't been specified - if (sortBy <= 0) - { - // Get the sort option from the index - sortOption = browseIndex.getSortOption(); - - if (sortOption == null) - { - // No sort option, so default to the first one defined in the config - for (SortOption so : SortOption.getSortOptions()) - { - sortOption = so; - break; - } - } - } - else - { - // A sorting has been specified, so get it from the configured sort columns - for (SortOption so : SortOption.getSortOptions()) + try + { + // If a sortOption hasn't been set, work out the default + if (sortOption == null) + { + // We need a browse index first though + if (browseIndex != null) + { + // If a sorting hasn't been specified, and it's a metadata browse + if (sortBy <= 0 && browseIndex.isMetadataIndex()) + { + // Create a dummy sortOption for the metadata sort + String dataType = browseIndex.getDataType(); + String type = ("date".equals(dataType) ? "date" : "text"); + sortOption = new SortOption(0, browseIndex.getName(), browseIndex.getMetadata(0), type); + } + else + { + // If a sorting hasn't been specified + if (sortBy <= 0) { - if (so.getNumber() == sortBy) - sortOption = so; + // Get the sort option from the index + sortOption = browseIndex.getSortOption(); + + if (sortOption == null) + { + // No sort option, so default to the first one defined in the config + for (SortOption so : SortOption.getSortOptions()) + { + sortOption = so; + break; + } + } } - } - } - } - } - - return sortOption; - } + else + { + // A sorting has been specified, so get it from the configured sort columns + for (SortOption so : SortOption.getSortOptions()) + { + if (so.getNumber() == sortBy) + sortOption = so; + } + } + } + } + } + + return sortOption; + } + catch (SortException se) + { + throw new BrowseException("Error in SortOptions", se); + } + } /** * @return Returns the startsWith. diff --git a/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java b/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java index 854df38ff7..2ae8d4bf4e 100644 --- a/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java +++ b/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java @@ -54,6 +54,9 @@ import org.apache.log4j.Logger; import org.dspace.content.DCValue; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; +import org.dspace.sort.OrderFormat; /** * Tool to create Browse indexes. This class is used from the command line to @@ -433,7 +436,7 @@ public class IndexBrowse for (int x = 0; x < values.length; x++) { // get the normalised version of the value - String nVal = BrowseOrder.makeSortString(values[x].value, values[x].language, bis[i].getDataType()); + String nVal = OrderFormat.makeSortString(values[x].value, values[x].language, bis[i].getDataType()); Map sortMap = getSortValues(item, itemMDMap); @@ -469,51 +472,59 @@ public class IndexBrowse private Map getSortValues(ItemMetadataProxy item, Map itemMDMap) throws BrowseException, SQLException { - // now obtain the sort order values that we will use - Map sortMap = new HashMap(); - for (SortOption so : SortOption.getSortOptions()) + try { - Integer key = new Integer(so.getNumber()); - String metadata = so.getMetadata(); - - // If we've already used the metadata for this Item - // it will be cached in the map - DCValue value = null; - - if (itemMDMap != null) - value = (DCValue) itemMDMap.get(metadata); - - // We haven't used this metadata before, so grab it from the item - if (value == null) + // now obtain the sort order values that we will use + Map sortMap = new HashMap(); + for (SortOption so : SortOption.getSortOptions()) { - String[] somd = so.getMdBits(); - DCValue[] dcv = item.getMetadata(somd[0], somd[1], somd[2], Item.ANY); - - if (dcv == null) + Integer key = new Integer(so.getNumber()); + String metadata = so.getMetadata(); + + // If we've already used the metadata for this Item + // it will be cached in the map + DCValue value = null; + + if (itemMDMap != null) + value = (DCValue) itemMDMap.get(metadata); + + // We haven't used this metadata before, so grab it from the item + if (value == null) { - continue; + String[] somd = so.getMdBits(); + DCValue[] dcv = item.getMetadata(somd[0], somd[1], somd[2], Item.ANY); + + if (dcv == null) + { + continue; + } + + // we only use the first dc value + if (dcv.length > 0) + { + // Set it as the current metadata value to use + // and add it to the map + value = dcv[0]; + + if (itemMDMap != null) + itemMDMap.put(metadata, dcv[0]); + } } - - // we only use the first dc value - if (dcv.length > 0) + + // normalise the values as we insert into the sort map + if (value != null && value.value != null) { - // Set it as the current metadata value to use - // and add it to the map - value = dcv[0]; - - if (itemMDMap != null) - itemMDMap.put(metadata, dcv[0]); + String nValue = OrderFormat.makeSortString(value.value, value.language, so.getType()); + sortMap.put(key, nValue); } } - // normalise the values as we insert into the sort map - if (value != null && value.value != null) - { - String nValue = BrowseOrder.makeSortString(value.value, value.language, so.getType()); - sortMap.put(key, nValue); - } + return sortMap; + } + catch (SortException se) + { + throw new BrowseException("Error in SortOptions", se); } - return sortMap; } /** @@ -696,26 +707,33 @@ public class IndexBrowse private void prepTables() throws BrowseException { - // first, erase the existing indexes - clearDatabase(); - - createItemTables(); - - // for each current browse index, make all the relevant tables - for (int i = 0; i < bis.length; i++) + try { - createTables(bis[i]); - - // prepare some CLI output - StringBuffer logMe = new StringBuffer(); - for (SortOption so : SortOption.getSortOptions()) - { - logMe.append(" " + so.getMetadata() + " "); - } - - output.message("Creating browse index " + bis[i].getName() + - ": index by " + bis[i].getMetadata() + - " sortable by: " + logMe.toString()); + // first, erase the existing indexes + clearDatabase(); + + createItemTables(); + + // for each current browse index, make all the relevant tables + for (int i = 0; i < bis.length; i++) + { + createTables(bis[i]); + + // prepare some CLI output + StringBuffer logMe = new StringBuffer(); + for (SortOption so : SortOption.getSortOptions()) + { + logMe.append(" " + so.getMetadata() + " "); + } + + output.message("Creating browse index " + bis[i].getName() + + ": index by " + bis[i].getMetadata() + + " sortable by: " + logMe.toString()); + } + } + catch (SortException se) + { + throw new BrowseException("Error in SortOptions", se); } } @@ -884,6 +902,10 @@ public class IndexBrowse context.commit(); } } + catch (SortException se) + { + throw new BrowseException("Error in SortOptions", se); + } catch (SQLException e) { log.error("caught exception: ", e); @@ -994,6 +1016,10 @@ public class IndexBrowse context.commit(); } } + catch (SortException se) + { + throw new BrowseException("Error in SortOptions", se); + } catch (SQLException e) { log.error("caught exception: ", e); diff --git a/dspace-api/src/main/java/org/dspace/content/ItemComparator.java b/dspace-api/src/main/java/org/dspace/content/ItemComparator.java index 1d67ab7319..cb67366c66 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemComparator.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemComparator.java @@ -45,7 +45,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import org.dspace.browse.BrowseOrder; +import org.dspace.sort.OrderFormat; /** * Compare two Items by their DCValues. @@ -256,6 +256,6 @@ public class ItemComparator implements Comparator return value.value; } - return BrowseOrder.makeSortString(value.value, value.language, BrowseOrder.TITLE); + return OrderFormat.makeSortString(value.value, value.language, OrderFormat.TITLE); } } diff --git a/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java b/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java index 045c72e988..606cec6a0e 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java @@ -48,6 +48,7 @@ import org.apache.lucene.analysis.PorterStemFilter; import org.apache.lucene.analysis.StopFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardFilter; +import org.dspace.core.ConfigurationManager; /** * Custom Lucene Analyzer that combines the standard filter, lowercase filter, @@ -94,4 +95,14 @@ public class DSAnalyzer extends Analyzer return result; } + + public int getPositionIncrementGap(String fieldName) + { + // If it is the default field, or bounded fields is turned off in the config, return the default value + if ("default".equalsIgnoreCase(fieldName) || !ConfigurationManager.getBooleanProperty("search.boundedfields", false)) + return super.getPositionIncrementGap(fieldName); + + // Not the default field, and we want bounded fields, so return an large gap increment + return 10; + } } diff --git a/dspace-api/src/main/java/org/dspace/search/DSIndexer.java b/dspace-api/src/main/java/org/dspace/search/DSIndexer.java index 9389e4f82d..deb697f0fd 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSIndexer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSIndexer.java @@ -47,16 +47,22 @@ import java.io.StringWriter; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; +import java.util.Calendar; +import java.util.TimeZone; +import java.text.SimpleDateFormat; +import java.text.ParseException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.PosixParser; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.document.DateTools; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; @@ -75,6 +81,8 @@ import org.dspace.core.Context; import org.dspace.core.Email; import org.dspace.core.LogManager; import org.dspace.handle.HandleManager; +import org.dspace.sort.SortOption; +import org.dspace.sort.OrderFormat; /** * DSIndexer contains the methods that index Items and their metadata, @@ -111,6 +119,20 @@ public class DSIndexer String schema; String element; String qualifier = null; + String type = "text"; + + IndexConfig() + { + } + + IndexConfig(String indexName, String schema, String element, String qualifier, String type) + { + this.indexName = indexName; + this.schema = schema; + this.element = element; + this.qualifier = qualifier; + this.type = type; + } } private static String index_directory = ConfigurationManager.getProperty("search.dir"); @@ -121,9 +143,23 @@ public class DSIndexer /** The analyzer for this DSpace instance */ private static Analyzer analyzer = null; - // Static initialisation of index configuration / - private static IndexConfig[] indexConfigArr = new IndexConfig[0]; - + /** Static initialisation of index configuration */ + /** Includes backwards compatible default configuration */ + private static IndexConfig[] indexConfigArr = new IndexConfig[] + { + new IndexConfig("author", "dc", "contributor", Item.ANY, "text") , + new IndexConfig("author", "dc", "creator", Item.ANY, "text"), + new IndexConfig("author", "dc", "description", "statementofresponsibility", "text"), + new IndexConfig("title", "dc", "title", Item.ANY, "text"), + new IndexConfig("keyword", "dc", "subject", Item.ANY, "text"), + new IndexConfig("abstract", "dc", "description", "abstract", "text"), + new IndexConfig("abstract", "dc", "description", "tableofcontents", "text"), + new IndexConfig("series", "dc", "relation", "ispartofseries", "text"), + new IndexConfig("mimetype", "dc", "format", "mimetype", "text"), + new IndexConfig("sponsor", "dc", "description", "sponsorship", "text"), + new IndexConfig("identifier", "dc", "identifier", Item.ANY, "text") + }; + static { // calculate maxfieldlength @@ -133,7 +169,7 @@ public class DSIndexer } // read in indexes from the config - ArrayList indexConfigList = new ArrayList(); + ArrayList indexConfigList = new ArrayList(); // read in search.index.1, search.index.2.... for (int i = 1; ConfigurationManager.getProperty("search.index." + i) != null; i++) @@ -148,7 +184,7 @@ public class DSIndexer for (int i = 0; i < indexConfigList.size(); i++) { indexConfigArr[i] = new IndexConfig(); - String index = (String) indexConfigList.get(i); + String index = indexConfigList.get(i); String[] configLine = index.split(":"); @@ -172,6 +208,11 @@ public class DSIndexer throw new RuntimeException( "Malformed configuration line: search.index." + i); } + + if (configLine.length > 2) + { + indexConfigArr[i].type = configLine[2]; + } } } @@ -246,7 +287,7 @@ public class DSIndexer Item item = (Item)dso; if (item.isArchived() && !item.isWithdrawn()) { - if(requiresIndexing(handle, ((Item)dso).getLastModified()) || force) + if (requiresIndexing(handle, ((Item)dso).getLastModified()) || force) { Document doc = buildDocument(context, (Item) dso); @@ -696,7 +737,7 @@ public class DSIndexer * to determine if the index is stale. * * @param handle - * @param dso + * @param lastModified * @return * @throws SQLException * @throws IOException @@ -810,17 +851,17 @@ public class DSIndexer throws SQLException, IOException { // Create Lucene Document - Document doc = buildDocument(Constants.COMMUNITY, community.getHandle(), null); + Document doc = buildDocument(Constants.COMMUNITY, community.getID(), community.getHandle(), null); // and populate it String name = community.getMetadata("name"); - if(name != null) + if (name != null) { - doc.add(new Field("name", name, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", name, Field.Store.YES, Field.Index.TOKENIZED)); + doc.add(new Field("name", name, Field.Store.NO, Field.Index.TOKENIZED)); + doc.add(new Field("default", name, Field.Store.NO, Field.Index.TOKENIZED)); } - + return doc; } @@ -839,15 +880,15 @@ public class DSIndexer String location_text = buildCollectionLocationString(context, collection); // Create Lucene Document - Document doc = buildDocument(Constants.COLLECTION, collection.getHandle(), location_text); + Document doc = buildDocument(Constants.COLLECTION, collection.getID(), collection.getHandle(), location_text); // and populate it String name = collection.getMetadata("name"); - if(name != null) + if (name != null) { - doc.add(new Field("name", name, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", name, Field.Store.YES, Field.Index.TOKENIZED)); + doc.add(new Field("name", name, Field.Store.NO, Field.Index.TOKENIZED)); + doc.add(new Field("default", name, Field.Store.NO, Field.Index.TOKENIZED)); } return doc; @@ -866,7 +907,6 @@ public class DSIndexer private static Document buildDocument(Context context, Item item) throws SQLException, IOException { - String handle = item.getHandle(); if(handle == null) @@ -877,7 +917,7 @@ public class DSIndexer // get the location string (for searching by collection & community) String location = buildItemLocationString(context, item); - Document doc = buildDocument(Constants.ITEM, handle, location); + Document doc = buildDocument(Constants.ITEM, item.getID(), handle, location); log.debug("Building Item: " + handle); @@ -902,132 +942,71 @@ public class DSIndexer mydc = item.getMetadata(indexConfigArr[i].schema, indexConfigArr[i].element, indexConfigArr[i].qualifier, Item.ANY); } - // put them all from an array of strings to one string for - // writing out pack all of the arrays of DCValues into plain - // text strings for the indexer - String content_text = ""; - for (j = 0; j < mydc.length; j++) { - content_text = new String(content_text + mydc[j].value + " "); + if (!StringUtils.isEmpty(mydc[j].value)) + { + if ("timestamp".equalsIgnoreCase(indexConfigArr[i].type)) + { + Date d = toDate(mydc[j].value); + if (d != null) + { + doc.add( new Field(indexConfigArr[i].indexName, + DateTools.dateToString(d, DateTools.Resolution.SECOND), + Field.Store.NO, + Field.Index.TOKENIZED)); + } + } + else if ("date".equalsIgnoreCase(indexConfigArr[i].type)) + { + Date d = toDate(mydc[j].value); + if (d != null) + { + doc.add( new Field(indexConfigArr[i].indexName, + DateTools.dateToString(d, DateTools.Resolution.DAY), + Field.Store.NO, + Field.Index.TOKENIZED)); + } + } + else + { + // TODO: use a delegate to allow custom 'types' to be used to reformat the field + doc.add( new Field(indexConfigArr[i].indexName, + mydc[j].value, + Field.Store.NO, + Field.Index.TOKENIZED)); + } + + doc.add( new Field("default", mydc[j].value, Field.Store.NO, Field.Index.TOKENIZED)); + } } - - // arranges content with fields in ArrayLists with same index to - // put - // into hash later - k = fields.indexOf(indexConfigArr[i].indexName); - - if (k < 0) - { - fields.add(indexConfigArr[i].indexName); - content.add(content_text); - } - else - { - content_text = new String(content_text - + (String) content.get(k) + " "); - content.set(k, content_text); - } - } - - // build the hash - for (int i = 0; i < fields.size(); i++) - { - - doc.add( - new Field( - (String) fields.get(i), - (String) content.get(i), - Field.Store.YES, Field.Index.TOKENIZED - )); - - doc.add(new Field("default", (String) content.get(i), Field.Store.YES, Field.Index.TOKENIZED)); - } - } - else - // if no search indexes found in cfg file, for backward compatibility - { - // extract metadata (ANY is wildcard from Item class) - DCValue[] authors = item.getDC("contributor", Item.ANY, Item.ANY); - for (j = 0; j < authors.length; j++) - { - doc.add(new Field("author", authors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", authors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] creators = item.getDC("creator", Item.ANY, Item.ANY); - for (j = 0; j < creators.length; j++) //also authors - { - doc.add(new Field("author", creators[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", creators[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] sors = item.getDC("description", "statementofresponsibility", Item.ANY); - for (j = 0; j < sors.length; j++) //also authors - { - doc.add(new Field("author", sors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", sors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] titles = item.getDC("title", Item.ANY, Item.ANY); - for (j = 0; j < titles.length; j++) - { - doc.add(new Field("title", titles[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", titles[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] keywords = item.getDC("subject", Item.ANY, Item.ANY); - for (j = 0; j < keywords.length; j++) - { - doc.add(new Field("keyword", keywords[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", keywords[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] abstracts = item.getDC("description", "abstract", Item.ANY); - for (j = 0; j < abstracts.length; j++) - { - doc.add(new Field("abstract", abstracts[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", abstracts[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] tocs = item.getDC("description", "tableofcontents", Item.ANY); - for (j = 0; j < tocs.length; j++) - { - doc.add(new Field("abstract", tocs[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", tocs[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] series = item.getDC("relation", "ispartofseries", Item.ANY); - for (j = 0; j < series.length; j++) - { - doc.add(new Field("series", series[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", series[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] mimetypes = item.getDC("format", "mimetype", Item.ANY); - for (j = 0; j < mimetypes.length; j++) - { - doc.add(new Field("mimetype", mimetypes[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", mimetypes[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] sponsors = item.getDC("description", "sponsorship", Item.ANY); - for (j = 0; j < sponsors.length; j++) - { - doc.add(new Field("sponsor", sponsors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", sponsors[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - } - - DCValue[] identifiers = item.getDC("identifier", Item.ANY, Item.ANY); - for (j = 0; j < identifiers.length; j++) - { - doc.add(new Field("identifier", identifiers[j].value, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", identifiers[j].value, Field.Store.YES, Field.Index.TOKENIZED)); } } log.debug(" Added Metadata"); + try + { + // Now get the configured sort options, and add those as untokenized fields + // Note that we will use the sort order delegates to normalise the values written + for (SortOption so : SortOption.getSortOptions()) + { + String[] somd = so.getMdBits(); + DCValue[] dcv = item.getMetadata(somd[0], somd[1], somd[2], Item.ANY); + if (dcv.length > 0) + { + String value = OrderFormat.makeSortString(dcv[0].value, dcv[0].language, so.getType()); + doc.add( new Field("sort_" + so.getName(), value, Field.Store.NO, Field.Index.UN_TOKENIZED) ); + } + } + } + catch (Exception e) + { + log.error(e.getMessage(),e); + } + + log.debug(" Added Sorting"); + try { // now get full text of any bitstreams in the TEXT bundle @@ -1077,11 +1056,11 @@ public class DSIndexer * Create Lucene document with all the shared fields initialized. * * @param type Type of DSpace Object - * @param handle - * @param location - * @return + * @param id + *@param handle + * @param location @return */ - private static Document buildDocument(int type, String handle, String location) + private static Document buildDocument(int type, int id, String handle, String location) { Document doc = new Document(); @@ -1089,10 +1068,14 @@ public class DSIndexer // (not tokenized, but it is indexed) doc.add(new Field(LAST_INDEXED_FIELD, Long.toString(System.currentTimeMillis()), Field.Store.YES, Field.Index.UN_TOKENIZED)); - + // KEPT FOR BACKWARDS COMPATIBILITY // do location, type, handle first doc.add(new Field("type", Integer.toString(type), Field.Store.YES, Field.Index.NO)); + // New fields to weaken the dependence on handles, and allow for faster list display + doc.add(new Field("search.resourcetype", Integer.toString(type), Field.Store.YES, Field.Index.NO)); + doc.add(new Field("search.resourceid", Integer.toString(id), Field.Store.YES, Field.Index.NO)); + // want to be able to search for handle, so use keyword // (not tokenized, but it is indexed) if (handle != null) @@ -1105,17 +1088,72 @@ public class DSIndexer doc.add(new Field("handle", handle, Field.Store.YES, Field.Index.UN_TOKENIZED)); // add to full text index - doc.add(new Field("default", handle, Field.Store.YES, Field.Index.TOKENIZED)); + doc.add(new Field("default", handle, Field.Store.NO, Field.Index.TOKENIZED)); } if(location != null) { - doc.add(new Field("location", location, Field.Store.YES, Field.Index.TOKENIZED)); - doc.add(new Field("default", location, Field.Store.YES, Field.Index.TOKENIZED)); + doc.add(new Field("location", location, Field.Store.NO, Field.Index.TOKENIZED)); + doc.add(new Field("default", location, Field.Store.NO, Field.Index.TOKENIZED)); } return doc; } + /** + * Helper function to retrieve a date using a best guess of the potential date encodings on a field + * + * @param t + * @return + */ + private static Date toDate(String t) + { + SimpleDateFormat[] dfArr; + // Choose the likely date formats based on string length + switch (t.length()) + { + case 4: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy") }; + break; + case 6: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyyMM") }; + break; + case 7: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy-MM") }; + break; + case 8: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyyMMdd"), new SimpleDateFormat("yyyy MMM") }; + break; + case 10: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy-MM-dd") }; + break; + case 11: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy MMM dd") }; + break; + case 20: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") }; + break; + default: + dfArr = new SimpleDateFormat[] { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") }; + break; + } + + + for (SimpleDateFormat df : dfArr) + { + try + { + // Parse the date + df.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC"))); + return df.parse(t); + } + catch (ParseException pe) + { + log.error("Unable to parse date format", pe); + } + } + + return null; + } } diff --git a/dspace-api/src/main/java/org/dspace/search/DSQuery.java b/dspace-api/src/main/java/org/dspace/search/DSQuery.java index f037251577..93fb089d70 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSQuery.java +++ b/dspace-api/src/main/java/org/dspace/search/DSQuery.java @@ -40,7 +40,6 @@ package org.dspace.search; import java.io.IOException; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -56,6 +55,8 @@ import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Searcher; +import org.apache.lucene.search.Sort; +import org.apache.lucene.search.SortField; import org.apache.oro.text.perl.Perl5Util; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -63,6 +64,7 @@ import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; +import org.dspace.sort.SortOption; // issues // need to filter query string for security @@ -123,10 +125,12 @@ public class DSQuery String querystring = args.getQuery(); QueryResults qr = new QueryResults(); List hitHandles = new ArrayList(); - List hitTypes = new ArrayList(); + List hitIds = new ArrayList(); + List hitTypes = new ArrayList(); // set up the QueryResults object qr.setHitHandles(hitHandles); + qr.setHitIds(hitIds); qr.setHitTypes(hitTypes); qr.setStart(args.getStart()); qr.setPageSize(args.getPageSize()); @@ -159,8 +163,18 @@ public class DSQuery } Query myquery = qp.parse(querystring); - Hits hits = searcher.search(myquery); + Hits hits = null; + if (args.getSortOption() == null) + { + hits = searcher.search(myquery, new Sort(new SortField[] { new SortField("type"), SortField.FIELD_SCORE })); + } + else + { + SortField[] sortFields = new SortField[] { new SortField("type"), new SortField("sort_" + args.getSortOption().getName(), SortOption.DESCENDING.equals(args.getSortOrder())), SortField.FIELD_SCORE }; + hits = searcher.search(myquery, new Sort(sortFields)); + } + // set total number of hits qr.setHitCount(hits.length()); @@ -181,52 +195,47 @@ public class DSQuery { Document d = hits.doc(i); + String resourceId = d.get("search.resourceid"); + String resourceType = d.get("search.resourcetype"); + String handleText = d.get("handle"); - String handletype = d.get("type"); + String handleType = d.get("type"); - hitHandles.add(handleText); + switch (Integer.parseInt( resourceType != null ? resourceType : handleType)) + { + case Constants.ITEM: + hitTypes.add(new Integer(Constants.ITEM)); + break; - if (handletype.equals("" + Constants.ITEM)) - { - hitTypes.add(new Integer(Constants.ITEM)); - } - else if (handletype.equals("" + Constants.COLLECTION)) - { - hitTypes.add(new Integer(Constants.COLLECTION)); - } - else if (handletype.equals("" + Constants.COMMUNITY)) - { - hitTypes.add(new Integer(Constants.COMMUNITY)); - } - else - { - // error! unknown type! + case Constants.COLLECTION: + hitTypes.add(new Integer(Constants.COLLECTION)); + break; + + case Constants.COMMUNITY: + hitTypes.add(new Integer(Constants.COMMUNITY)); + break; } + + hitHandles.add( handleText ); + hitIds.add( resourceId == null ? null: Integer.parseInt(resourceId) ); } } } catch (NumberFormatException e) { - log - .warn(LogManager.getHeader(c, "Number format exception", "" - + e)); - + log.warn(LogManager.getHeader(c, "Number format exception", "" + e)); qr.setErrorMsg("Number format exception"); } catch (ParseException e) { // a parse exception - log and return null results log.warn(LogManager.getHeader(c, "Invalid search string", "" + e)); - qr.setErrorMsg("Invalid search string"); } catch (TokenMgrError tme) { // Similar to parse exception - log - .warn(LogManager.getHeader(c, "Invalid search string", "" - + tme)); - + log.warn(LogManager.getHeader(c, "Invalid search string", "" + tme)); qr.setErrorMsg("Invalid search string"); } catch(BooleanQuery.TooManyClauses e) @@ -387,6 +396,25 @@ public class DSQuery } } + /** + * Close any IndexSearcher that is currently open. + */ + public static void close() + { + if (searcher != null) + { + try + { + searcher.close(); + searcher = null; + } + catch (IOException ioe) + { + log.error("DSQuery: Unable to close open IndexSearcher", ioe); + } + } + } + public static void main(String[] args) { if (args.length > 0) diff --git a/dspace-api/src/main/java/org/dspace/search/QueryArgs.java b/dspace-api/src/main/java/org/dspace/search/QueryArgs.java index fd69489f5f..c274d73e87 100644 --- a/dspace-api/src/main/java/org/dspace/search/QueryArgs.java +++ b/dspace-api/src/main/java/org/dspace/search/QueryArgs.java @@ -47,6 +47,7 @@ import java.util.Iterator; import javax.servlet.http.HttpServletRequest; import org.dspace.core.Constants; +import org.dspace.sort.SortOption; import org.apache.oro.text.perl.Perl5Util; @@ -64,6 +65,10 @@ public class QueryArgs private int pageSize = 10; + private SortOption sortOption = null; + + private String sortOrder = SortOption.ASCENDING; + /** * set the query string * @@ -128,6 +133,26 @@ public class QueryArgs return pageSize; } + public SortOption getSortOption() + { + return sortOption; + } + + public void setSortOption(SortOption sortOption) + { + this.sortOption = sortOption; + } + + public String getSortOrder() + { + return sortOrder; + } + + public void setSortOrder(String sortOrder) + { + this.sortOrder = sortOrder; + } + /** * Builds an advanced-query description string. * diff --git a/dspace-api/src/main/java/org/dspace/search/QueryResults.java b/dspace-api/src/main/java/org/dspace/search/QueryResults.java index c432c04d5e..c65bd5ea0c 100644 --- a/dspace-api/src/main/java/org/dspace/search/QueryResults.java +++ b/dspace-api/src/main/java/org/dspace/search/QueryResults.java @@ -56,8 +56,8 @@ public class QueryResults private List hitHandles; // handles of content (items, collections, // communities) - private List hitTypes; // Integers from Constants defng types of - // corresponding handles + private List hitTypes; // Resource type - from Constants + private List hitIds; // Resource ids private String errorMsg; //error string, if there is one @@ -112,6 +112,18 @@ public class QueryResults return hitHandles; } + /** set the List of ids corresponding to hits */ + public void setHitIds(List myHits) + { + hitIds = myHits; + } + + /** get the List of handles corresponding to hits */ + public List getHitIds() + { + return hitIds; + } + /** set the List of types corresponding to handles */ public void setHitTypes(List newTypes) { diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrder.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormat.java similarity index 74% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrder.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormat.java index d2165a9573..b41bf4e62b 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrder.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormat.java @@ -1,5 +1,5 @@ /* - * BrowseOrder.java + * OrderFormat.java * * Version: $Revision: 1.0 $ * @@ -38,11 +38,15 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.dspace.core.PluginManager; +import org.dspace.sort.OrderFormatDelegate; +import org.dspace.sort.OrderFormatAuthor; +import org.dspace.sort.OrderFormatTitle; +import org.dspace.sort.OrderFormatText; /** * Class implementing static helpers for anywhere that interacts with the sort columns @@ -52,16 +56,16 @@ import org.dspace.core.PluginManager; * * Types can be defined or configured using the plugin manager: * - * plugin.named.org.dspace.browse.BrowseOrderDelegate= - * org.dspace.browse.BrowseOrderTitleMarc21=title - * org.dspace.browse.BrowseOrderAuthor=author + * plugin.named.org.dspace.sort.OrderFormatDelegate= + * org.dspace.sort.OrderFormatTitleMarc21=title + * org.dspace.sort.OrderFormatAuthor=author * * The following standard types have been defined by default, but can be reconfigured * via the plugin manager: * - * author = org.dspace.browse.BrowseOrderAuthor - * title = org.dspace.browse.BrowseOrderTitle - * text = org.dspace.browse.BrowseOrderText + * author = org.dspace.sort.OrderFormatAuthor + * title = org.dspace.sort.OrderFormatTitle + * text = org.dspace.sort.OrderFormatText * * IMPORTANT - If you change any of the orderings, you need to rebuild the browse sort columns * (ie. run 'index-all', or 'dsrun org.dspace.browse.InitializeBrowse') @@ -69,50 +73,50 @@ import org.dspace.core.PluginManager; * @author Graham Triggs * @version $Revision: 1.0 $ */ -public class BrowseOrder +public class OrderFormat { - private final static Logger log = LogManager.getLogger(BrowseOrder.class); + private final static Logger log = LogManager.getLogger(OrderFormat.class); public final static String AUTHOR = "author"; public final static String TITLE = "title"; public final static String TEXT = "text"; // Array of all available order delegates - avoids excessive calls to plugin manager - private final static String[] delegates = PluginManager.getAllPluginNames(BrowseOrderDelegate.class); + private final static String[] delegates = PluginManager.getAllPluginNames(OrderFormatDelegate.class); - private final static BrowseOrderDelegate authorDelegate = new BrowseOrderAuthor(); - private final static BrowseOrderDelegate titleDelegate = new BrowseOrderTitle(); - private final static BrowseOrderDelegate textDelegate = new BrowseOrderText(); + private final static OrderFormatDelegate authorDelegate = new OrderFormatAuthor(); + private final static OrderFormatDelegate titleDelegate = new OrderFormatTitle(); + private final static OrderFormatDelegate textDelegate = new OrderFormatText(); /** * Generate a sort string for the given DC metadata */ public static String makeSortString(String value, String language, String type) { - BrowseOrderDelegate delegate = null; + OrderFormatDelegate delegate = null; // If a named index has been supplied if (type != null && type.length() > 0) { // Use a delegate if one is configured - if ((delegate = BrowseOrder.getDelegate(type)) != null) + if ((delegate = OrderFormat.getDelegate(type)) != null) { return delegate.makeSortString(value, language); } } // No delegates found, so apply defaults - if (type.equalsIgnoreCase(BrowseOrder.AUTHOR) && authorDelegate != null) + if (type.equalsIgnoreCase(OrderFormat.AUTHOR) && authorDelegate != null) { return authorDelegate.makeSortString(value, language); } - if (type.equalsIgnoreCase(BrowseOrder.TITLE) && titleDelegate != null) + if (type.equalsIgnoreCase(OrderFormat.TITLE) && titleDelegate != null) { return titleDelegate.makeSortString(value, language); } - if (type.equalsIgnoreCase(BrowseOrder.TEXT) && textDelegate != null) + if (type.equalsIgnoreCase(OrderFormat.TEXT) && textDelegate != null) { return textDelegate.makeSortString(value, language); } @@ -123,7 +127,7 @@ public class BrowseOrder /** * Retrieve the named delegate */ - private static BrowseOrderDelegate getDelegate(String name) + private static OrderFormatDelegate getDelegate(String name) { if (name != null && name.length() > 0) { @@ -132,7 +136,7 @@ public class BrowseOrder { if (delegates[idx].equals(name)) { - return (BrowseOrderDelegate)PluginManager.getNamedPlugin(BrowseOrderDelegate.class, name); + return (OrderFormatDelegate)PluginManager.getNamedPlugin(OrderFormatDelegate.class, name); } } } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderAuthor.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatAuthor.java similarity index 93% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrderAuthor.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormatAuthor.java index f2e93f4886..30df751e3e 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderAuthor.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatAuthor.java @@ -1,5 +1,5 @@ /* - * BrowseOrderAuthor.java + * OrderFormatAuthor.java * * Version: $Revision: 1.0 $ * @@ -38,18 +38,19 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import org.dspace.text.filter.DecomposeDiactritics; import org.dspace.text.filter.LowerCaseAndTrim; import org.dspace.text.filter.TextFilter; +import org.dspace.browse.AbstractTextFilterOFD; /** * Standard author ordering delegate implementation * * @author Graham Triggs */ -public class BrowseOrderAuthor extends AbstractTextFilterBOD +public class OrderFormatAuthor extends AbstractTextFilterOFD { { filters = new TextFilter[] { new DecomposeDiactritics(), diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderDelegate.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatDelegate.java similarity index 96% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrderDelegate.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormatDelegate.java index 5955c35051..a94011b589 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderDelegate.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatDelegate.java @@ -1,5 +1,5 @@ /* - * BrowseOrderDelegate.java + * OrderFormatDelegate.java * * Version: $Revision: 1.0 $ * @@ -38,14 +38,14 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; /** * Interface for browse order delegates * * @author Graham Triggs */ -public interface BrowseOrderDelegate +public interface OrderFormatDelegate { /** * Prepare the appropriate sort string for the given value in the diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderText.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatText.java similarity index 93% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrderText.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormatText.java index 60ee00390a..1dfc1f0ecb 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderText.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatText.java @@ -1,5 +1,5 @@ /* - * BrowseOrderText.java + * OrderFormatText.java * * Version: $Revision: 1.0 $ * @@ -38,18 +38,19 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import org.dspace.text.filter.DecomposeDiactritics; import org.dspace.text.filter.LowerCaseAndTrim; import org.dspace.text.filter.TextFilter; +import org.dspace.browse.AbstractTextFilterOFD; /** * Standard text ordering delegate implementation * * @author Graham Triggs */ -public class BrowseOrderText extends AbstractTextFilterBOD +public class OrderFormatText extends AbstractTextFilterOFD { { filters = new TextFilter[] { new DecomposeDiactritics(), diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitle.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatTitle.java similarity index 93% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitle.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormatTitle.java index e6b4fffd70..fac4777b8c 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitle.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatTitle.java @@ -1,5 +1,5 @@ /* - * BrowseOrderTitle.java + * OrderFormatTitle.java * * Version: $Revision: 1.0 $ * @@ -38,19 +38,20 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import org.dspace.text.filter.DecomposeDiactritics; import org.dspace.text.filter.LowerCaseAndTrim; import org.dspace.text.filter.StandardInitialArticleWord; import org.dspace.text.filter.TextFilter; +import org.dspace.browse.AbstractTextFilterOFD; /** * Standard title ordering delegate implementation * * @author Graham Triggs */ -public class BrowseOrderTitle extends AbstractTextFilterBOD +public class OrderFormatTitle extends AbstractTextFilterOFD { { filters = new TextFilter[] { new StandardInitialArticleWord(), diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitleMarc21.java b/dspace-api/src/main/java/org/dspace/sort/OrderFormatTitleMarc21.java similarity index 92% rename from dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitleMarc21.java rename to dspace-api/src/main/java/org/dspace/sort/OrderFormatTitleMarc21.java index c3d6f9b850..7d351db46f 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseOrderTitleMarc21.java +++ b/dspace-api/src/main/java/org/dspace/sort/OrderFormatTitleMarc21.java @@ -1,5 +1,5 @@ /* - * BrowseOrderTitleMarc21.java + * OrderFormatTitleMarc21.java * * Version: $Revision: 1.0 $ * @@ -38,16 +38,17 @@ * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import org.dspace.text.filter.*; +import org.dspace.browse.AbstractTextFilterOFD; /** * MARC 21 title ordering delegate implementation * * @author Graham Triggs */ -public class BrowseOrderTitleMarc21 extends AbstractTextFilterBOD +public class OrderFormatTitleMarc21 extends AbstractTextFilterOFD { { filters = new TextFilter[] { new MARC21InitialArticleWord(), diff --git a/dspace-api/src/main/java/org/dspace/sort/SortException.java b/dspace-api/src/main/java/org/dspace/sort/SortException.java new file mode 100644 index 0000000000..94c2b6dac7 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/sort/SortException.java @@ -0,0 +1,68 @@ +/* + * SortException.java + * + * Version: $Revision: $ + * + * Date: $Date: $ + * + * Copyright (c) 2002-2007, 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. + */ +package org.dspace.sort; + +/** + * Just a quick SortException class to give us the relevant data type + */ +public class SortException extends Exception +{ + + public SortException() + { + super(); + } + + public SortException(String message) + { + super(message); + } + + public SortException(String message, Throwable cause) + { + super(message, cause); + } + + public SortException(Throwable cause) + { + super(cause); + } + +} diff --git a/dspace-api/src/main/java/org/dspace/browse/SortOption.java b/dspace-api/src/main/java/org/dspace/sort/SortOption.java similarity index 92% rename from dspace-api/src/main/java/org/dspace/browse/SortOption.java rename to dspace-api/src/main/java/org/dspace/sort/SortOption.java index e5829d9a99..2033dab581 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SortOption.java +++ b/dspace-api/src/main/java/org/dspace/sort/SortOption.java @@ -33,7 +33,7 @@ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ -package org.dspace.browse; +package org.dspace.sort; import java.io.IOException; import java.util.HashMap; @@ -86,10 +86,10 @@ public class SortOption * @param name * @param md * @param type - * @throws BrowseException + * @throws SortException */ public SortOption(int number, String name, String md, String type) - throws BrowseException + throws SortException { this.name = name; this.type = type; @@ -104,10 +104,10 @@ public class SortOption * * @param number * @param definition - * @throws BrowseException + * @throws SortException */ public SortOption(int number, String definition) - throws BrowseException + throws SortException { this.number = number; @@ -117,7 +117,7 @@ public class SortOption if (!matcher.matches()) { - throw new BrowseException("Sort Order configuration is not valid: webui.browse.sort-order." + + throw new SortException("Sort Order configuration is not valid: webui.itemlist.sort-option." + number + " = " + definition); } @@ -219,10 +219,10 @@ public class SortOption /** * Tell the class to generate the metadata bits * - * @throws BrowseException + * @throws SortException */ public void generateMdBits() - throws BrowseException + throws SortException { try { @@ -230,7 +230,7 @@ public class SortOption } catch(IOException e) { - throw new BrowseException(e); + throw new SortException(e); } } @@ -300,7 +300,7 @@ public class SortOption /** * @return a map of the configured sort options */ - public static Map getSortOptionsMap() throws BrowseException + public static Map getSortOptionsMap() throws SortException { if (SortOption.sortOptionsMap != null) return SortOption.sortOptionsMap; @@ -320,9 +320,9 @@ public class SortOption /** * Return all the configured sort options * @return - * @throws BrowseException + * @throws SortException */ - public static Set getSortOptions() throws BrowseException + public static Set getSortOptions() throws SortException { if (SortOption.sortOptionsSet != null) return SortOption.sortOptionsSet; @@ -333,7 +333,7 @@ public class SortOption int idx = 1; String option; - while ( ((option = ConfigurationManager.getProperty("webui.browse.sort-option." + idx))) != null) + while ( ((option = ConfigurationManager.getProperty("webui.itemlist.sort-option." + idx))) != null) { SortOption so = new SortOption(idx, option); SortOption.sortOptionsSet.add(so); @@ -348,9 +348,9 @@ public class SortOption * Get the defined sort option by number (.1, .2, etc) * @param number * @return - * @throws BrowseException + * @throws SortException */ - public static SortOption getSortOption(int number) throws BrowseException + public static SortOption getSortOption(int number) throws SortException { for (SortOption so : SortOption.getSortOptions()) { @@ -364,9 +364,9 @@ public class SortOption /** * Get the default sort option - initially, just the first one defined * @return - * @throws BrowseException + * @throws SortException */ - public static SortOption getDefaultSortOption() throws BrowseException + public static SortOption getDefaultSortOption() throws SortException { for (SortOption so : getSortOptions()) return so; diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java index 1ae6c09890..66e69770f0 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java @@ -46,7 +46,8 @@ import org.dspace.browse.BrowserScope; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseInfo; import org.dspace.browse.BrowseException; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.core.ConfigurationManager; import org.dspace.content.Item; @@ -120,6 +121,11 @@ public class RecentSubmissionsManager return rs; } + catch (SortException se) + { + log.error("caught exception: ", se); + throw new RecentSubmissionsException(se); + } catch (BrowseException e) { log.error("caught exception: ", e); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java index 1b53cb2815..5c8df9ed8c 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java @@ -53,6 +53,7 @@ import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Utils; import org.dspace.storage.bitstore.BitstreamStorageManager; +import org.dspace.sort.SortOption; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AbstractBrowserServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AbstractBrowserServlet.java index 94b4f06216..fc0b8d6b56 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AbstractBrowserServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AbstractBrowserServlet.java @@ -15,7 +15,8 @@ import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseInfo; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.core.ConfigurationManager; @@ -251,6 +252,11 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet return scope; } + catch (SortException se) + { + log.error("caught exception: ", se); + throw new ServletException(se); + } catch (BrowseException e) { log.error("caught exception: ", e); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedServlet.java index 6f1f194476..dc22d62119 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedServlet.java @@ -66,7 +66,8 @@ import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseInfo; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -436,6 +437,11 @@ public class FeedServlet extends DSpaceServlet return channel; } + catch (SortException se) + { + log.error("caught exception: ", se); + throw new IOException(se); + } catch (BrowseException e) { log.error("caught exception: ", e); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java index 9325e90804..b73f39993c 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java @@ -65,6 +65,7 @@ import org.dspace.handle.HandleManager; import org.dspace.search.DSQuery; import org.dspace.search.QueryArgs; import org.dspace.search.QueryResults; +import org.dspace.sort.SortOption; /** * Servlet for handling a simple search. @@ -97,6 +98,8 @@ public class SimpleSearchServlet extends DSpaceServlet int start = UIUtil.getIntParameter(request, "start"); String advanced = request.getParameter("advanced"); String fromAdvanced = request.getParameter("from_advanced"); + int sortBy = UIUtil.getIntParameter(request, "sort_by"); + String order = request.getParameter("order"); String advancedQuery = ""; HashMap queryHash = new HashMap(); @@ -117,6 +120,22 @@ public class SimpleSearchServlet extends DSpaceServlet QueryResults qResults = null; QueryArgs qArgs = new QueryArgs(); + try + { + qArgs.setSortOption(SortOption.getSortOption(sortBy)); + if (SortOption.DESCENDING.equalsIgnoreCase(order)) + { + qArgs.setSortOrder(SortOption.DESCENDING); + } + else + { + qArgs.setSortOrder(SortOption.ASCENDING); + } + } + catch (Exception e) + { + } + // if the "advanced" flag is set, build the query string from the // multiple query fields if (advanced != null) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java index 3eb6daa9e0..85726da1b9 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java @@ -52,6 +52,7 @@ import org.dspace.content.ItemIterator; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.sort.SortOption; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; diff --git a/dspace-jspui/src/main/webapp/browse/full.jsp b/dspace-jspui/src/main/webapp/browse/full.jsp index c26ae382d7..a42f562d41 100644 --- a/dspace-jspui/src/main/webapp/browse/full.jsp +++ b/dspace-jspui/src/main/webapp/browse/full.jsp @@ -49,11 +49,10 @@ <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ page import="org.dspace.browse.BrowseInfo" %> -<%@ page import="org.dspace.browse.SortOption" %> +<%@ page import="org.dspace.sort.SortOption" %> <%@ page import="org.dspace.content.Collection" %> <%@ page import="org.dspace.content.Community" %> <%@ page import="org.dspace.browse.BrowseIndex" %> -<%@ page import="org.dspace.browse.SortOption" %> <%@ page import="org.dspace.core.ConfigurationManager" %> <%@ page import="java.net.URLEncoder" %> <%@ page import="java.util.Map" %> diff --git a/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp b/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp index 0da1cf3259..03a171a118 100644 --- a/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp +++ b/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp @@ -50,7 +50,7 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="org.dspace.browse.BrowseInfo" %> -<%@ page import="org.dspace.browse.SortOption" %> +<%@ page import="org.dspace.sort.SortOption" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/WithdrawnItems.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/WithdrawnItems.java index 66a2e4e766..581f7621ac 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/WithdrawnItems.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/administrative/WithdrawnItems.java @@ -78,7 +78,8 @@ import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseInfo; import org.dspace.browse.BrowseItem; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DCDate; @@ -475,9 +476,9 @@ public class WithdrawnItems extends AbstractDSpaceTransformer implements } } } - catch (BrowseException be) + catch (SortException se) { - throw new WingException("Unable to get sort options", be); + throw new WingException("Unable to get sort options", se); } } diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java index 8cbd62646b..326f0d43d2 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java @@ -66,10 +66,10 @@ import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseItem; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; import org.xml.sax.SAXException; @@ -324,6 +324,10 @@ public class CollectionViewer extends AbstractDSpaceTransformer implements Cache BrowseEngine be = new BrowseEngine(context); this.recentSubmissionItems = be.browse(scope).getResults(); } + catch (SortException se) + { + log.error("Caught SortException", se); + } catch (BrowseException bex) { log.error("Caught BrowseException", bex); diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java index 4df9931a8c..71ad044d5d 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java @@ -67,11 +67,11 @@ import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseItem; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; import org.xml.sax.SAXException; @@ -375,6 +375,10 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea BrowseEngine be = new BrowseEngine(context); this.recentSubmittedItems = be.browse(scope).getResults(); } + catch (SortException se) + { + log.error("Caught SortException", se); + } catch (BrowseException bex) { log.error("Caught BrowseException", bex); diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ConfigurableBrowse.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ConfigurableBrowse.java index b23813f31b..3f18323d54 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ConfigurableBrowse.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ConfigurableBrowse.java @@ -42,8 +42,6 @@ package org.dspace.app.xmlui.aspect.artifactbrowser; import java.io.IOException; import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.sql.SQLException; import java.util.HashMap; import java.util.Locale; @@ -80,13 +78,13 @@ import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowseInfo; import org.dspace.browse.BrowseItem; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; +import org.dspace.sort.SortException; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.core.ConfigurationManager; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.xml.sax.SAXException; @@ -473,9 +471,9 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements } } } - catch (BrowseException be) + catch (SortException se) { - throw new WingException("Unable to get sort options", be); + throw new WingException("Unable to get sort options", se); } } @@ -623,21 +621,28 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements } else if (bi.isItemIndex() && !bi.isInternalIndex()) { - // If a default sort option is specified by the index, but it isn't - // the same as sort option requested, attempt to find an index that - // is configured to use that sort by default - // This is so that we can then highlight the correct option in the navigation - SortOption bso = bi.getSortOption(); - SortOption so = SortOption.getSortOption(sortBy); - if ( bso != null && bso != so) + try { - BrowseIndex newBi = BrowseIndex.getBrowseIndex(so); - if (newBi != null) + // If a default sort option is specified by the index, but it isn't + // the same as sort option requested, attempt to find an index that + // is configured to use that sort by default + // This is so that we can then highlight the correct option in the navigation + SortOption bso = bi.getSortOption(); + SortOption so = SortOption.getSortOption(sortBy); + if ( bso != null && bso != so) { - bi = newBi; - type = bi.getName(); + BrowseIndex newBi = BrowseIndex.getBrowseIndex(so); + if (newBi != null) + { + bi = newBi; + type = bi.getName(); + } } } + catch (SortException se) + { + throw new UIException("Unable to get sort options", se); + } } params.scope.setBrowseIndex(bi); diff --git a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceFeedGenerator.java b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceFeedGenerator.java index 0d6c49a2ca..da30e01dc4 100644 --- a/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceFeedGenerator.java +++ b/dspace-xmlui/dspace-xmlui-api/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceFeedGenerator.java @@ -70,7 +70,7 @@ import org.dspace.browse.BrowseEngine; import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseIndex; import org.dspace.browse.BrowserScope; -import org.dspace.browse.SortOption; +import org.dspace.sort.SortOption; import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.Community; diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 7f6ebca06f..b4f21244d6 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -474,7 +474,7 @@ plugin.single.org.dspace.app.webui.util.StyleSelection = \ # webui.browse.index. = : item : : (asc | desc) # # sort option name: this is the sorting to be applied to the display. It must match the -# name given to one of the webui.browse.sort-option entries given below. +# name given to one of the webui.itemlist.sort-option entries given below. # # The final part of the configuration is optional, and specifies the default ordering # for the index - whether it is ASCending (the default, and best for text indexes), or @@ -499,13 +499,13 @@ webui.browse.index.4 = subject:metadata:dc.subject.*:text # Set the options for what can be sorted by # -# Sort options will be available when browsing a list of items (i.e. only in -# "full" mode, not "single" mode). You can define an arbitrary number of fields +# Sort options will be available when browsing a list of items (i.e. an 'item' browse, +# or search results). You can define an arbitrary number of fields # to sort on, irrespective of which fields you display using webui.itemlist.columns # # the format is: # -# webui.browse.sort-option. =