Improved browse configuration (ability to hide sort options from the browse controls, can set left-hand navigation to asc and/or desc lists). Improves normalisation of titles.

git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@2406 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Graham Triggs
2007-11-29 11:58:05 +00:00
parent 68bc714dfd
commit 603b82a006
12 changed files with 156 additions and 114 deletions

View File

@@ -185,6 +185,15 @@ public class BrowseIndex
if (sortOption == null) if (sortOption == null)
valid = false; 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; tableBaseName = getItemBrowseIndex().tableBaseName;
} }
else else
@@ -632,19 +641,15 @@ public class BrowseIndex
throws BrowseException throws BrowseException
{ {
BrowseIndex[] bis = getBrowseIndices(); BrowseIndex[] bis = getBrowseIndices();
ArrayList tables = new ArrayList(); String[] returnTables = new String[bis.length + 1];
for (int i = 0; i < bis.length; i++) for (int i = 0; i < bis.length; i++)
{ {
String tableName = bis[i].getTableName(); returnTables[i] = bis[i].getTableName();
tables.add(tableName);
} }
// FIXME: this complies with the old BrowseTables method, but I'm // FIXME: this complies with the old BrowseTables method, but I'm
// not really sure why it's here // not really sure why it's here
tables.add("Communities2Item"); returnTables[bis.length] = "Communities2Item";
String[] returnTables = new String[tables.size()];
returnTables = (String[]) tables.toArray((String[]) returnTables);
return returnTables; return returnTables;
} }

View File

@@ -40,10 +40,7 @@
package org.dspace.browse; package org.dspace.browse;
import org.dspace.text.filter.DecomposeDiactritics; import org.dspace.text.filter.*;
import org.dspace.text.filter.LowerCaseAndTrim;
import org.dspace.text.filter.MARC21InitialArticleWord;
import org.dspace.text.filter.TextFilter;
/** /**
* MARC 21 title ordering delegate implementation * MARC 21 title ordering delegate implementation
@@ -55,6 +52,7 @@ public class BrowseOrderTitleMarc21 extends AbstractTextFilterBOD
{ {
filters = new TextFilter[] { new MARC21InitialArticleWord(), filters = new TextFilter[] { new MARC21InitialArticleWord(),
new DecomposeDiactritics(), new DecomposeDiactritics(),
new StripLeadingNonAlphaNum(),
new LowerCaseAndTrim() }; new LowerCaseAndTrim() };
} }
} }

View File

@@ -335,18 +335,9 @@ public class BrowserScope
if (order != null) if (order != null)
return order; return order;
try BrowseIndex bi = getBrowseIndex();
{ if (bi != null)
SortOption so = getSortOption(); return bi.getDefaultOrder();
if (so != null)
return so.getDefaultOrder();
}
catch (BrowseException be)
{
// recoverable problem, just log the error and continue
log.debug("Unable to retrieve a sort option for this browse", be);
}
return SortOption.ASCENDING; return SortOption.ASCENDING;
} }
@@ -425,7 +416,7 @@ public class BrowserScope
// Create a dummy sortOption for the metadata sort // Create a dummy sortOption for the metadata sort
String dataType = browseIndex.getDataType(); String dataType = browseIndex.getDataType();
String type = ("date".equals(dataType) ? "date" : "text"); String type = ("date".equals(dataType) ? "date" : "text");
sortOption = new SortOption(0, browseIndex.getName(), browseIndex.getMetadata(), type, browseIndex.getDefaultOrder()); sortOption = new SortOption(0, browseIndex.getName(), browseIndex.getMetadata(), type);
} }
else else
{ {
@@ -570,18 +561,10 @@ public class BrowserScope
return false; return false;
} }
try BrowseIndex bi = getBrowseIndex();
{
SortOption so = getSortOption();
if (so != null && SortOption.DESCENDING.equalsIgnoreCase(so.getDefaultOrder())) if (bi != null && SortOption.DESCENDING.equalsIgnoreCase(bi.getDefaultOrder()))
return false; return false;
}
catch (BrowseException be)
{
// recoverable problem, just log the error and continue
log.debug("Unable to retrieve a sort option for this browse", be);
}
return true; return true;
} }

View File

@@ -561,7 +561,8 @@ public class IndexBrowse
public static void main(String[] argv) public static void main(String[] argv)
throws SQLException, BrowseException, ParseException throws SQLException, BrowseException, ParseException
{ {
IndexBrowse indexer = new IndexBrowse(); Context context = new Context();
IndexBrowse indexer = new IndexBrowse(context);
// create an options object and populate it // create an options object and populate it
CommandLineParser parser = new PosixParser(); CommandLineParser parser = new PosixParser();
@@ -655,6 +656,7 @@ public class IndexBrowse
} }
indexer.usage(options); indexer.usage(options);
context.complete();
} }
/** /**

View File

@@ -36,7 +36,6 @@
package org.dspace.browse; package org.dspace.browse;
import java.io.IOException; import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@@ -73,8 +72,8 @@ public class SortOption
/** the metadata broken down into bits for convenience */ /** the metadata broken down into bits for convenience */
private String[] mdBits; private String[] mdBits;
/** default ordering for this sort, when not supplied by the user */ /** should the sort option be visible for user selection */
private String defaultOrder; private boolean visible;
/** the sort options available for this index */ /** the sort options available for this index */
private static Set<SortOption> sortOptionsSet = null; private static Set<SortOption> sortOptionsSet = null;
@@ -96,21 +95,7 @@ public class SortOption
this.type = type; this.type = type;
this.metadata = md; this.metadata = md;
this.number = number; this.number = number;
this.defaultOrder = SortOption.ASCENDING; this.visible = true;
generateMdBits();
}
public SortOption(int number, String name, String md, String type, String defaultOrder)
throws BrowseException
{
this.name = name;
this.type = type;
this.metadata = md;
this.number = number;
if (SortOption.DESCENDING.equalsIgnoreCase(defaultOrder))
this.defaultOrder = SortOption.DESCENDING;
else
this.defaultOrder = SortOption.ASCENDING;
generateMdBits(); generateMdBits();
} }
@@ -139,27 +124,17 @@ public class SortOption
name = matcher.group(1); name = matcher.group(1);
metadata = matcher.group(2); metadata = matcher.group(2);
type = matcher.group(3); type = matcher.group(3);
if (matcher.groupCount() > 3)
defaultOrder = matcher.group(4);
// If the default order is specified as descending, keep it // If the option is configured to be hidden, then set the visible flag to false
// Otherwise, set the default order to ascending // otherwise, flag it as visible (true)
if (SortOption.DESCENDING.equalsIgnoreCase(defaultOrder)) if (matcher.groupCount() > 3 && "hide".equalsIgnoreCase(matcher.group(4)))
defaultOrder = SortOption.DESCENDING; visible = false;
else else
defaultOrder = SortOption.ASCENDING; visible = true;
generateMdBits(); generateMdBits();
} }
/**
* @return Returns the default ordering for this sort option
*/
public String getDefaultOrder()
{
return defaultOrder;
}
/** /**
* @return Returns the metadata. * @return Returns the metadata.
*/ */
@@ -224,6 +199,15 @@ public class SortOption
this.number = number; this.number = number;
} }
/**
* Should this sort option be made visible in the UI
* @return true if visible, false otherwise
*/
public boolean isVisible()
{
return visible;
}
/** /**
* @return a 3 element array of the metadata bits * @return a 3 element array of the metadata bits
*/ */
@@ -346,22 +330,14 @@ public class SortOption
SortOption.sortOptionsSet = new HashSet<SortOption>(); SortOption.sortOptionsSet = new HashSet<SortOption>();
synchronized (SortOption.sortOptionsSet) synchronized (SortOption.sortOptionsSet)
{ {
Enumeration en = ConfigurationManager.propertyNames(); int idx = 1;
String option;
String rx = "webui\\.browse\\.sort-option\\.(\\d+)"; while ( ((option = ConfigurationManager.getProperty("webui.browse.sort-option." + idx))) != null)
Pattern pattern = Pattern.compile(rx);
while (en.hasMoreElements())
{ {
String property = (String) en.nextElement(); SortOption so = new SortOption(idx, option);
Matcher matcher = pattern.matcher(property);
if (matcher.matches())
{
int number = Integer.parseInt(matcher.group(1));
String option = ConfigurationManager.getProperty(property);
SortOption so = new SortOption(number, option);
SortOption.sortOptionsSet.add(so); SortOption.sortOptionsSet.add(so);
} idx++;
} }
} }

View File

@@ -83,7 +83,7 @@ public abstract class InitialArticleWord implements TextFilter
while (initialEnd < 0 && curPos < str.length()) while (initialEnd < 0 && curPos < str.length())
{ {
// Have we found a significant character // Have we found a significant character
if (Character.isLetterOrDigit(str.charAt(curPos)) || str.charAt(curPos) == '\'') if (Character.isLetterOrDigit(str.charAt(curPos)))
{ {
// Mark this as the cut point for the initial word // Mark this as the cut point for the initial word
initialStart = curPos; initialStart = curPos;

View File

@@ -133,7 +133,7 @@ public class MARC21InitialArticleWord extends InitialArticleWord
{ "die", Language.AFRIKAANS, Language.GERMAN, Language.YIDDISH }, { "die", Language.AFRIKAANS, Language.GERMAN, Language.YIDDISH },
{ "dos", Language.YIDDISH }, { "dos", Language.YIDDISH },
{ "e", Language.NORWEGIAN }, { "e", Language.NORWEGIAN },
{ "'e", Language.FRISIAN }, { "e", Language.FRISIAN }, // should be 'e - leading apostrophes are ignored
{ "een", Language.DUTCH }, { "een", Language.DUTCH },
{ "eene", Language.DUTCH }, { "eene", Language.DUTCH },
{ "egy", Language.HUNGARIAN }, { "egy", Language.HUNGARIAN },
@@ -205,21 +205,21 @@ public class MARC21InitialArticleWord extends InitialArticleWord
{ "mga", Language.TAGALOG }, { "mga", Language.TAGALOG },
{ "m\u0303ga", Language.TAGALOG }, { "m\u0303ga", Language.TAGALOG },
{ "mia", Language.GREEK }, { "mia", Language.GREEK },
{ "'n", Language.AFRIKAANS, Language.DUTCH, Language.FRISIAN }, { "n", Language.AFRIKAANS, Language.DUTCH, Language.FRISIAN }, // should be 'n - leading apostrophes are ignored
{ "na", Language.HAWAIIAN, Language.IRISH, Language.SCOTTISH_GAELIC }, { "na", Language.HAWAIIAN, Language.IRISH, Language.SCOTTISH_GAELIC },
{ "na h-", Language.IRISH, Language.SCOTTISH_GAELIC }, { "na h-", Language.IRISH, Language.SCOTTISH_GAELIC },
{ "nje", Language.ALBANIAN }, { "nje", Language.ALBANIAN },
{ "ny", Language.MALAGASY }, { "ny", Language.MALAGASY },
{ "'o", Language.NEAPOLITAN_ITALIAN }, { "o", Language.NEAPOLITAN_ITALIAN }, // should be 'o - leading apostrophes are ignored
{ "o", Language.GALICIAN, Language.HAWAIIAN, Language.PORTUGUESE, Language.ROMANIAN }, { "o", Language.GALICIAN, Language.HAWAIIAN, Language.PORTUGUESE, Language.ROMANIAN },
{ "os", Language.PORTUGUESE }, { "os", Language.PORTUGUESE },
{ "'r", Language.ICELANDIC }, { "r", Language.ICELANDIC }, // should be 'r - leading apostrophes are ignored
{ "'s", Language.GERMAN }, { "s", Language.GERMAN }, // should be 's - leading apostrophes are ignored
{ "sa", Language.TAGALOG }, { "sa", Language.TAGALOG },
{ "sa mga", Language.TAGALOG }, { "sa mga", Language.TAGALOG },
{ "si", Language.TAGALOG }, { "si", Language.TAGALOG },
{ "sin\u00e1", Language.TAGALOG }, { "sin\u00e1", Language.TAGALOG },
{ "'t", Language.DUTCH, Language.FRISIAN }, { "t", Language.DUTCH, Language.FRISIAN }, // should be 't - leading apostrophes are ignored
{ "ta", Language.CLASSICAL_GREEK, Language.GREEK }, { "ta", Language.CLASSICAL_GREEK, Language.GREEK },
{ "tais", Language.CLASSICAL_GREEK }, { "tais", Language.CLASSICAL_GREEK },
{ "tas", Language.CLASSICAL_GREEK }, { "tas", Language.CLASSICAL_GREEK },

View File

@@ -0,0 +1,62 @@
/*
* StripLeadingNonAlphaNum.java
*
* Version: $Revision: 1.0 $
*
* Date: $Date: 2007/03/02 11:22:13 $
*
* Copyright (c) 2002-2005, 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.text.filter;
public class StripLeadingNonAlphaNum implements TextFilter
{
public String filter(String str)
{
int i = 0;
while (i < str.length() && !Character.isLetterOrDigit(str.charAt(i)))
i++;
if (i > 0)
return str.substring(i);
return str;
}
public String filter(String str, String lang)
{
return filter(str);
}
}

View File

@@ -139,6 +139,11 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet
} }
} }
if (order == null && bi != null)
{
order = bi.getDefaultOrder();
}
// if no resultsperpage set, default to 20 // if no resultsperpage set, default to 20
if (resultsperpage == -1) if (resultsperpage == -1)
{ {

View File

@@ -358,11 +358,14 @@
<select name="sort_by"> <select name="sort_by">
<% <%
for (SortOption sortBy : sortOptions) for (SortOption sortBy : sortOptions)
{
if (sortBy.isVisible())
{ {
String selected = (sortBy.getName().equals(sortedBy) ? "selected=\"selected\"" : ""); String selected = (sortBy.getName().equals(sortedBy) ? "selected=\"selected\"" : "");
String mKey = "browse.sort-by." + sortBy.getName(); String mKey = "browse.sort-by." + sortBy.getName();
%> <option value="<%= sortBy.getNumber() %>" <%= selected %>><fmt:message key="<%= mKey %>"/></option><% %> <option value="<%= sortBy.getNumber() %>" <%= selected %>><fmt:message key="<%= mKey %>"/></option><%
} }
}
%> %>
</select> </select>
<% <%

View File

@@ -464,12 +464,15 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements
Select sortSelect = controlsForm.addSelect(BrowseParams.SORT_BY); Select sortSelect = controlsForm.addSelect(BrowseParams.SORT_BY);
for (SortOption so : sortOptions) for (SortOption so : sortOptions)
{
if (so.isVisible())
{ {
sortSelect.addOption(so.equals(info.getSortOption()), so.getNumber(), sortSelect.addOption(so.equals(info.getSortOption()), so.getNumber(),
message("xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by." + so.getName())); message("xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by." + so.getName()));
} }
} }
} }
}
catch (BrowseException be) catch (BrowseException be)
{ {
throw new WingException("Unable to get sort options", be); throw new WingException("Unable to get sort options", be);

View File

@@ -453,11 +453,15 @@ plugin.single.org.dspace.app.webui.util.StyleSelection = \
# The other form is for indexes of the items themselves, ie. each entry will be displayed # The other form is for indexes of the items themselves, ie. each entry will be displayed
# according to the configuration of by webui.itemlist.columns: # according to the configuration of by webui.itemlist.columns:
# #
# webui.browse.index.<n> = <index name> : item : <sort option name> # webui.browse.index.<n> = <index name> : item : <sort option name> : (asc | desc)
# #
# sort option name: this is the sorting to be applied to the display. It must match the # 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.browse.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
# DESCending (useful for dates - ie. most recent submissions)
# NOTE: the text to render the index will use the <sort option name> parameter to select # NOTE: the text to render the index will use the <sort option name> parameter to select
# the message key from Messages.properties using a key of the form: # the message key from Messages.properties using a key of the form:
# #
@@ -485,15 +489,16 @@ webui.browse.index.4 = subject:metadata:dc.subject.*:text
# #
# webui.browse.sort-option.<n> = <option name> : \ # webui.browse.sort-option.<n> = <option name> : \
# <schema prefix>.<element>[.<qualifier>|.*] : \ # <schema prefix>.<element>[.<qualifier>|.*] : \
# (date | text | ...) : (asc | desc) # (date | text | ...) : (show | hide)
# #
# This is defined much the same as above. The parameter after the metadata # This is defined much the same as above. The parameter after the metadata
# just lets the sorter know which normalisation to use - standard normalisations are title, # just lets the sorter know which normalisation to use - standard normalisations are title,
# text or date - however additional normalisations can be defined using the PluginManager. # text or date - however additional normalisations can be defined using the PluginManager.
# #
# The final part of the configuration is optional, and specifies the default ordering # The final parts of the configuration is optional - whether to SHOW (the default) or
# for the index - whether it is ASCending (the default, and best for text indexes), or # HIDE the option from the sorting controls in the user interface. This can be useful if
# DESCending (useful for dates - ie. most recent submissions) # you need to define a specific date sort for use by the recent items lists,
# but otherwise don't want users to choose that option.
# #
webui.browse.sort-option.1 = title:dc.title:title webui.browse.sort-option.1 = title:dc.title:title
webui.browse.sort-option.2 = dateissued:dc.date.issued:date webui.browse.sort-option.2 = dateissued:dc.date.issued:date