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
This commit is contained in:
Graham Triggs
2008-01-10 14:03:36 +00:00
parent 4b4828ef0e
commit d86af20a5a
34 changed files with 732 additions and 444 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
boolean valid = true;
this.defaultOrder = SortOption.ASCENDING;
this.number = number;
if (isMetadataIndex())
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;
}
}
else
{
valid = false;
}
if (!valid)
if (!valid)
{
throw new BrowseException("Browse Index configuration is not valid: webui.browse.index." +
number + " = " + definition);
}
}
catch (SortException se)
{
throw new BrowseException("Browse Index configuration is not valid: webui.browse.index." +
number + " = " + definition);
throw new BrowseException("Error in SortOptions", se);
}
}

View File

@@ -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

View File

@@ -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();
return sortOption;
}
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())
{
if (so.getNumber() == sortBy)
sortOption = so;
}
}
}
}
}
return sortOption;
}
catch (SortException se)
{
throw new BrowseException("Error in SortOptions", se);
}
}
/**
* @return Returns the startsWith.

View File

@@ -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<Integer, String> getSortValues(ItemMetadataProxy item, Map itemMDMap)
throws BrowseException, SQLException
{
// now obtain the sort order values that we will use
Map<Integer, String> sortMap = new HashMap<Integer, String>();
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<Integer, String> sortMap = new HashMap<Integer, String>();
for (SortOption so : SortOption.getSortOptions())
{
String[] somd = so.getMdBits();
DCValue[] dcv = item.getMetadata(somd[0], somd[1], somd[2], Item.ANY);
Integer key = new Integer(so.getNumber());
String metadata = so.getMetadata();
if (dcv == null)
// 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]);
// first, erase the existing indexes
clearDatabase();
// prepare some CLI output
StringBuffer logMe = new StringBuffer();
for (SortOption so : SortOption.getSortOptions())
{
logMe.append(" " + so.getMetadata() + " ");
}
createItemTables();
output.message("Creating browse index " + bis[i].getName() +
": index by " + bis[i].getMetadata() +
" sortable by: " + logMe.toString());
// 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);

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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,8 +143,22 @@ 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 {
@@ -133,7 +169,7 @@ public class DSIndexer
}
// read in indexes from the config
ArrayList indexConfigList = new ArrayList();
ArrayList<String> indexConfigList = new ArrayList<String>();
// 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,15 +851,15 @@ 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;
}
}

View File

@@ -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,7 +163,17 @@ 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)

View File

@@ -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.
*

View File

@@ -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)
{

View File

@@ -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);
}
}
}

View File

@@ -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(),

View File

@@ -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

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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);
}
}

View File

@@ -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<Integer, SortOption> getSortOptionsMap() throws BrowseException
public static Map<Integer, SortOption> 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<SortOption> getSortOptions() throws BrowseException
public static Set<SortOption> 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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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" %>

View File

@@ -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" %>

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -474,7 +474,7 @@ plugin.single.org.dspace.app.webui.util.StyleSelection = \
# 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
# 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.<n> = <option name> : \
# webui.itemlist.sort-option.<n> = <option name> : \
# <schema prefix>.<element>[.<qualifier>|.*] : \
# (date | text | ...) : (show | hide)
#
@@ -518,9 +518,9 @@ webui.browse.index.4 = subject:metadata:dc.subject.*:text
# 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.2 = dateissued:dc.date.issued:date
webui.browse.sort-option.3 = dateaccessioned:dc.date.accessioned:date
webui.itemlist.sort-option.1 = title:dc.title:title
webui.itemlist.sort-option.2 = dateissued:dc.date.issued:date
webui.itemlist.sort-option.3 = dateaccessioned:dc.date.accessioned:date
# Set the options for the size (number of characters) of the fields stored in the database.
#
@@ -550,9 +550,9 @@ webui.browse.sort-option.3 = dateaccessioned:dc.date.accessioned:date
#
# The default datatypes (and delegates) are:
#
# 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
#
# If you redefine a default datatype here, the configuration will be used in preference
# to the default, however, if you do not explicitly redefine a datatype, then the
@@ -560,8 +560,8 @@ webui.browse.sort-option.3 = dateaccessioned:dc.date.accessioned:date
#
# Uncomment the configuration below to use the multi-lingual MARC 21 title ordering.
#
#plugin.named.org.dspace.browse.BrowseOrderDelegate= \
# org.dspace.browse.BrowseOrderTitleMarc21=title
#plugin.named.org.dspace.sort.OrderFormatDelegate= \
# org.dspace.sort.OrderFormatTitleMarc21=title
## Set the options for how authors are displayed in the browse listing