/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.sort; import java.io.IOException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import org.dspace.core.ConfigurationManager; /** * Class to mediate with the sort configuration * * @author Richard Jones * */ public class SortOption { private static final Logger log = Logger.getLogger(SortOption.class); public static final String ASCENDING = "ASC"; public static final String DESCENDING = "DESC"; /** the number of the sort option as given in the config file */ 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; static { try { Set<SortOption> newSortOptionsSet = new TreeSet<SortOption>(new Comparator<SortOption>() { @Override public int compare(SortOption sortOption, SortOption sortOption1) { return Integer.valueOf(sortOption.getNumber()).compareTo(Integer.valueOf(sortOption1.getNumber())); } }); 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; } catch (SortException se) { log.fatal("Unable to load SortOptions", se); } } /** * Construct a new SortOption object with the given parameters * * @param number * the number of the sort option as given in the config file * @param name * sort option name * @param md * the metadata field to sort on * @param type * the type of data we are sorting by * @throws SortException if sort error */ 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 * the number of the sort option as given in the config file * @param definition * definition from the configuration * @throws SortException if sort error */ 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 sort option number (as given in the config file). */ 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 (String[]) ArrayUtils.clone(mdBits); } /** * Tell the class to generate the metadata bits * * @throws SortException if sort error */ private 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 3-element array with schema, element and qualifier respectively * @throws IOException * A general class of exceptions produced by failed or interrupted I/O operations. */ public final 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 true if is date */ public boolean isDate() { if ("date".equals(type)) { return true; } return false; } /** * Is the default sort option? * @return true if is default sort option */ public boolean isDefault() { if (number == 0) { return true; } return false; } /** * Return all the configured sort options. * @return a set of the configured sort options * @throws SortException if sort error */ public static Set<SortOption> getSortOptions() throws SortException { if (SortOption.sortOptionsSet == null) { throw new SortException("Sort options not loaded"); } return SortOption.sortOptionsSet; } /** * Get the defined sort option by number (.1, .2, etc). * @param number * the number of the sort option as given in the config file * @return the configured sort option with given number * @throws SortException if sort error */ 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 the first configured sort option * @throws SortException if sort error */ public static SortOption getDefaultSortOption() throws SortException { for (SortOption so : getSortOptions()) { return so; } return null; } }