/*
* SortOption.java
*
* 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;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dspace.core.ConfigurationManager;
/**
* Class to mediate with the sort configuration
*
* @author Richard Jones
*
*/
public class SortOption
{
public static final String ASCENDING = "ASC";
public static final String DESCENDING = "DESC";
/** the sort configuration number */
private int number;
/** the name of the sort */
private String name;
/** the metadata field to sort on */
private String metadata;
/** the type of data we are sorting by */
private String type;
/** the metadata broken down into bits for convenience */
private String[] mdBits;
/** should the sort option be visible for user selection */
private boolean visible;
/** the sort options available for this index */
private static Set<SortOption> sortOptionsSet = null;
private static Map<Integer, SortOption> sortOptionsMap = null;
/**
* Construct a new SortOption object with the given parameters
*
* @param number
* @param name
* @param md
* @param type
* @throws SortException
*/
public SortOption(int number, String name, String md, String type)
throws SortException
{
this.name = name;
this.type = type;
this.metadata = md;
this.number = number;
this.visible = true;
generateMdBits();
}
/**
* Construct a new SortOption object using the definition from the configuration
*
* @param number
* @param definition
* @throws SortException
*/
public SortOption(int number, String definition)
throws SortException
{
this.number = number;
String rx = "(\\w+):([\\w\\.\\*]+):(\\w+):?(\\w*)";
Pattern pattern = Pattern.compile(rx);
Matcher matcher = pattern.matcher(definition);
if (!matcher.matches())
{
throw new SortException("Sort Order configuration is not valid: webui.itemlist.sort-option." +
number + " = " + definition);
}
name = matcher.group(1);
metadata = matcher.group(2);
type = matcher.group(3);
// If the option is configured to be hidden, then set the visible flag to false
// otherwise, flag it as visible (true)
if (matcher.groupCount() > 3 && "hide".equalsIgnoreCase(matcher.group(4)))
visible = false;
else
visible = true;
generateMdBits();
}
/**
* @return Returns the metadata.
*/
public String getMetadata()
{
return metadata;
}
/**
* @param metadata The metadata to set.
*/
public void setMetadata(String metadata)
{
this.metadata = metadata;
}
/**
* @return Returns the name.
*/
public String getName()
{
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return Returns the type.
*/
public String getType()
{
return type;
}
/**
* @param type The type to set.
*/
public void setType(String type)
{
this.type = type;
}
/**
* @return Returns the number.
*/
public int getNumber()
{
return number;
}
/**
* @param number The number to set.
*/
public void setNumber(int 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
*/
public String[] getMdBits()
{
return mdBits;
}
/**
* Tell the class to generate the metadata bits
*
* @throws SortException
*/
public void generateMdBits()
throws SortException
{
try
{
mdBits = interpretField(metadata, null);
}
catch(IOException e)
{
throw new SortException(e);
}
}
/**
* Take a string representation of a metadata field, and return it as an array.
* This is just a convenient utility method to basically break the metadata
* representation up by its delimiter (.), and stick it in an array, inserting
* the value of the init parameter when there is no metadata field part.
*
* @param mfield the string representation of the metadata
* @param init the default value of the array elements
* @return a three element array with schema, element and qualifier respectively
*/
public String[] interpretField(String mfield, String init)
throws IOException
{
StringTokenizer sta = new StringTokenizer(mfield, ".");
String[] field = {init, init, init};
int i = 0;
while (sta.hasMoreTokens())
{
field[i++] = sta.nextToken();
}
// error checks to make sure we have at least a schema and qualifier for both
if (field[0] == null || field[1] == null)
{
throw new IOException("at least a schema and element be " +
"specified in configuration. You supplied: " + mfield);
}
return field;
}
/**
* Is this a date field
*
* @return
*/
public boolean isDate()
{
if (type != null)
{
if ("date".equals(type))
{
return true;
}
}
return false;
}
/**
* Is the default sort option
*
* @return
*/
public boolean isDefault()
{
if (number == 0)
{
return true;
}
return false;
}
/**
* @return a map of the configured sort options
*/
public static Map<Integer, SortOption> getSortOptionsMap() throws SortException
{
if (SortOption.sortOptionsMap != null)
return SortOption.sortOptionsMap;
synchronized (SortOption.class)
{
if (SortOption.sortOptionsMap == null)
{
Map<Integer, SortOption> newSortOptionsMap = new HashMap<Integer, SortOption>();
for (SortOption so : SortOption.getSortOptions())
{
newSortOptionsMap.put(new Integer(so.getNumber()), so);
}
SortOption.sortOptionsMap = newSortOptionsMap;
}
}
return SortOption.sortOptionsMap;
}
/**
* Return all the configured sort options
* @return
* @throws SortException
*/
public static Set<SortOption> getSortOptions() throws SortException
{
if (SortOption.sortOptionsSet != null)
return SortOption.sortOptionsSet;
synchronized (SortOption.class)
{
if (SortOption.sortOptionsSet == null)
{
Set<SortOption> newSortOptionsSet = new HashSet<SortOption>();
int idx = 1;
String option;
while ( ((option = ConfigurationManager.getProperty("webui.itemlist.sort-option." + idx))) != null)
{
SortOption so = new SortOption(idx, option);
newSortOptionsSet.add(so);
idx++;
}
SortOption.sortOptionsSet = newSortOptionsSet;
}
}
return SortOption.sortOptionsSet;
}
/**
* Get the defined sort option by number (.1, .2, etc)
* @param number
* @return
* @throws SortException
*/
public static SortOption getSortOption(int number) throws SortException
{
for (SortOption so : SortOption.getSortOptions())
{
if (so.getNumber() == number)
return so;
}
return null;
}
/**
* Get the default sort option - initially, just the first one defined
* @return
* @throws SortException
*/
public static SortOption getDefaultSortOption() throws SortException
{
for (SortOption so : getSortOptions())
return so;
return null;
}
}