Author: cbrisson Date: Sun Nov 20 10:15:58 2016 New Revision: 1770544 URL: http://svn.apache.org/viewvc?rev=1770544&view=rev Log: [tools] reenginering: - create a new CollectionTool ($collection) containing collection sorting and string splitting methods - make toLocale(Object) a public method of LocaleConfig - deprecate SortTool and ConversionTool (splitting goes to CollectionTool, number parsing is redundant with NumberTool, toLocale is now in LocaleConfig, date conversions are redundant with DateTool ones)
Added: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/CollectionTool.java - copied, changed from r1769770, velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ConversionTool.java velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LocaleConfig.java velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java Copied: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/CollectionTool.java (from r1769770, velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java) URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/CollectionTool.java?p2=velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/CollectionTool.java&p1=velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java&r1=1769770&r2=1770544&rev=1770544&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/CollectionTool.java Sun Nov 20 10:15:58 2016 @@ -19,21 +19,24 @@ package org.apache.velocity.tools.generi * under the License. */ +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.velocity.tools.config.DefaultKey; + +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.velocity.tools.config.DefaultKey; - /** - * SortTool allows a user to sort a collection (or array, iterator, etc) - * on any arbitary set of properties exposed by the objects contained - * within the collection. + * <p>CollectionTool allows a user to sort a collection (or array, iterator, etc) + * on any arbitrary set of properties exposed by the objects contained + * within the collection, and to generate arrays by splitting strings. + * </p> * * <p>The sort tool is specifically designed to use within a #foreach * but you may find other uses for it.</p> @@ -110,12 +113,107 @@ import org.apache.velocity.tools.config. * * @author S. Brett Sutton * @author Nathan Bubna - * @since VelocityTools 1.2 + * @since VelocityTools 3.0 * @version $Id$ */ -@DefaultKey("sorter") -public class SortTool extends SafeConfig +@DefaultKey("collection") +public class CollectionTool extends SafeConfig { + public static final String STRINGS_DELIMITER_FORMAT_KEY = "stringsDelimiter"; + public static final String STRINGS_TRIM_KEY = "trimStrings"; + + public static final String DEFAULT_STRINGS_DELIMITER = ","; + public static final boolean DEFAULT_STRINGS_TRIM = true; + + private String stringsDelimiter = DEFAULT_STRINGS_DELIMITER; + private boolean stringsTrim = DEFAULT_STRINGS_TRIM; + + /** + * Sets the delimiter used for separating values in a single String value. + * The default string delimiter is a comma. + * + * @see #split(String) + */ + protected final void setStringsDelimiter(String stringsDelimiter) + { + this.stringsDelimiter = stringsDelimiter; + } + + public final String getStringsDelimiter() + { + return this.stringsDelimiter; + } + + /** + * Sets whether strings should be trimmed when separated from + * a delimited string value. + * The default is true. + * + * @see #split(String) + */ + protected final void setStringsTrim(boolean stringsTrim) + { + this.stringsTrim = stringsTrim; + } + + public final boolean getStringsTrim() + { + return this.stringsTrim; + } + + /** + * Does the actual configuration. This is protected, so + * subclasses may share the same ValueParser and call configure + * at any time, while preventing templates from doing so when + * configure(Map) is locked. + */ + protected void configure(ValueParser values) + { + super.configure(values); + + String delimiter = values.getString(STRINGS_DELIMITER_FORMAT_KEY); + if (delimiter != null) + { + setStringsDelimiter(delimiter); + } + + Boolean trim = values.getBoolean(STRINGS_TRIM_KEY); + if (trim != null) + { + setStringsTrim(trim); + } + } + + /** + * @param value the value to be converted + * @return an array of String objects containing all of the values + * derived from the specified array, Collection, or delimited String + */ + public String[] split(String value) + { + if (value == null) + { + return null; + } + String[] values; + if (value.indexOf(this.stringsDelimiter) < 0) + { + values = new String[] { value }; + } + else + { + values = value.split(this.stringsDelimiter); + } + if (this.stringsTrim) + { + for (int i=0,l=values.length; i < l; i++) + { + values[i] = values[i].trim(); + } + } + return values; + } + /** * Sorts a Collection using a Comparator. A defensive copy is made * of the Collection beforehand, so the original Collection is left @@ -221,6 +319,25 @@ public class SortTool extends SafeConfig return sort(map, (List)null); } + public Collection sort(Object object) + { + if (object instanceof Collection) + { + return sort((Collection)object, (List)null); + } + else if (object instanceof Object[]) + { + return sort((Object[])object, (List)null); + } + else if (object instanceof Map) + { + return sort((Map)object, (List)null); + } + // the object type is not supported + getLog().error("object type not supported: {}", object == null ? "null" : object.getClass().getName()); + return null; + } + /** * Sorts the collection on a single property. * Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ConversionTool.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ConversionTool.java?rev=1770544&r1=1770543&r2=1770544&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ConversionTool.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/ConversionTool.java Sun Nov 20 10:15:58 2016 @@ -53,10 +53,13 @@ import org.apache.velocity.tools.config. * @author Nathan Bubna * @version $Revision$ $Date: 2007-02-26 11:24:39 -0800 (Mon, 26 Feb 2007) $ * @since VelocityTools 2.0 + * @deprecated use NumberTool for numbers formatting/parsing, DateTool for date/time formatting/parsing, + * or CollectionTool for toStrings(). */ @DefaultKey("convert") @SkipSetters +@Deprecated public class ConversionTool extends LocaleConfig implements Serializable { public static final String STRINGS_DELIMITER_FORMAT_KEY = "stringsDelimiter"; @@ -107,6 +110,7 @@ public class ConversionTool extends Loca * The default string delimiter is a comma. * * @see #parseStringList + * @deprecated use {@link CollectionTool#setStringsDelimiter(String)} */ protected final void setStringsDelimiter(String stringsDelimiter) { @@ -130,6 +134,10 @@ public class ConversionTool extends Loca this.stringsTrim = stringsTrim; } + /** + * @deprecated use {@link CollectionTool#getStringsTrim()} + * @return strings trim + */ public final boolean getStringsTrim() { return this.stringsTrim; @@ -140,6 +148,10 @@ public class ConversionTool extends Loca this.numberFormat = format; } + /** + * @deprecated use {@link NumberTool} format + * @return number format + */ public final String getNumberFormat() { return this.numberFormat; @@ -150,6 +162,10 @@ public class ConversionTool extends Loca this.dateFormat = format; } + /** + * @deprecated use {@link DateTool#getDateFormat()} + * @return date format + */ public final String getDateFormat() { return this.dateFormat; @@ -244,6 +260,7 @@ public class ConversionTool extends Loca * @param value the object to be converted * @return a {@link Locale} for the specified value or * <code>null</code> if the value is null or the conversion failed + * @deprecated use {@link DateTool}.toLocale(Object) */ public Locale toLocale(Object value) { @@ -268,6 +285,7 @@ public class ConversionTool extends Loca * @param value the date to convert * @return the object as a {@link Date} or <code>null</code> if no * conversion is possible + * @deprecated use {@link DateTool#toDate(Object)} */ public Date toDate(Object value) { @@ -284,6 +302,11 @@ public class ConversionTool extends Loca return parseDate(s); } + /** + * @param value + * @return calendar + * @deprecated use {@link DateTool#toCalendar(Object)} + */ public Calendar toCalendar(Object value) { if (value == null) @@ -310,6 +333,7 @@ public class ConversionTool extends Loca * @param value the value to be converted * @return an array of String objects containing all of the values * derived from the specified array, Collection, or delimited String + * @deprecated use {@link CollectionTool#split(String)} */ public String[] toStrings(Object value) { @@ -695,6 +719,7 @@ public class ConversionTool extends Loca * @param value the string to parse * @return the string as a {@link Number} or <code>null</code> if no * conversion is possible + * @deprecated use {@link NumberTool#toNumber(Object)} */ public Number parseNumber(String value) { @@ -711,6 +736,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Number} or <code>null</code> if no * conversion is possible * @see #parseNumber(String value, String format, Object locale) + * @deprecated use {@link NumberTool#toNumber(String, Object)} */ public Number parseNumber(String value, String format) { @@ -726,6 +752,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Number} or <code>null</code> if no * conversion is possible * @see java.text.NumberFormat#parse + * @deprecated use {@link NumberTool#toNumber(String, Object, Locale)} */ public Number parseNumber(String value, Object locale) { @@ -742,6 +769,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Number} or <code>null</code> if no * conversion is possible * @see java.text.NumberFormat#parse + * @deprecated use {@link NumberTool#toNumber(String, Object, Locale)} */ public Number parseNumber(String value, String format, Object locale) { @@ -764,6 +792,7 @@ public class ConversionTool extends Loca * @param value the date to convert * @return the object as a {@link Date} or <code>null</code> if no * conversion is possible + * @deprecated use {@link DateTool#toDate(Object)} */ public Date parseDate(String value) { @@ -780,6 +809,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Date} or <code>null</code> if no * conversion is possible * @see ConversionUtils#toDate(String str, String format, Locale locale, TimeZone timezone) + * @deprecated use {@link DateTool#toDate(String, Object)} */ public Date parseDate(String value, String format) { @@ -795,6 +825,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Date} or <code>null</code> if no * conversion is possible * @see java.text.SimpleDateFormat#parse + * @deprecated use {@link DateTool#toDate(String, Object, Locale)}} */ public Date parseDate(String value, Object locale) { @@ -811,6 +842,7 @@ public class ConversionTool extends Loca * @return the string as a {@link Date} or <code>null</code> if no * conversion is possible * @see java.text.SimpleDateFormat#parse + * @deprecated use {@link DateTool#toDate(String, Object, Locale)}} */ public Date parseDate(String value, String format, Object locale) { @@ -829,6 +861,7 @@ public class ConversionTool extends Loca * conversion is possible * @see #getDateFormat * @see java.text.SimpleDateFormat#parse + * @deprecated use {@link DateTool#toDate(String, Object, Locale, TimeZone)}} */ public Date parseDate(String value, String format, Object locale, TimeZone timezone) Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LocaleConfig.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LocaleConfig.java?rev=1770544&r1=1770543&r2=1770544&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LocaleConfig.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/LocaleConfig.java Sun Nov 20 10:15:58 2016 @@ -20,6 +20,8 @@ package org.apache.velocity.tools.generi */ import java.util.Locale; + +import org.apache.velocity.tools.ConversionUtils; import org.apache.velocity.tools.ToolContext; /** @@ -71,4 +73,24 @@ public class LocaleConfig extends SafeCo this.locale = locale; } + /** + * @param value the object to be converted + * @return a {@link Locale} for the specified value or + * <code>null</code> if the value is null or the conversion failed + * @since VelocityTools 3.0 + */ + public Locale toLocale(Object value) + { + if (value == null) + { + return null; + } + else if (value instanceof Locale) + { + return (Locale)value; + } + return ConversionUtils.toLocale(String.valueOf(value)); + } + + } Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java?rev=1770544&r1=1770543&r2=1770544&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/generic/SortTool.java Sun Nov 20 10:15:58 2016 @@ -112,300 +112,10 @@ import org.apache.velocity.tools.config. * @author Nathan Bubna * @since VelocityTools 1.2 * @version $Id$ + * @deprecated use CollectionTool sort methods */ @DefaultKey("sorter") -public class SortTool extends SafeConfig +@Deprecated +public class SortTool extends CollectionTool { - /** - * Sorts a Collection using a Comparator. A defensive copy is made - * of the Collection beforehand, so the original Collection is left - * untouched. - * - * @param c The Collection to sort. - * @param comparator The comparator to use for sorting. - * @return A copy of the original Collection, - * sorted using the supplied Comparator. - * @since VelocityTools 2.0.1 - */ - public <T> Collection<T> sort(final Collection<T> c, - final Comparator<T> comparator) - { - final ArrayList<T> list = new ArrayList<T>(c); - Collections.sort(list, comparator); - return list; - } - - /** - * Sorts an array using a Comparator. A defensive copy is made - * of the array beforehand, so the original array is left - * untouched. - * - * @param a The array to sort. - * @param comparator The comparator to use for sorting. - * @return A copy of the original array, - * sorted using the supplied Comparator. - * @since VelocityTools 2.0.1 - */ - public <T> T[] sort(final T[] a, final Comparator<T> comparator) - { - final T[] copy = a.clone(); - Arrays.sort(copy, comparator); - return copy; - } - - /** - * Sorts a Map's values using a Comparator. A defensive copy is made - * of the values beforehand, so the original Map is left - * untouched. - * - * @param map The Map whose values should be sorted. - * @param comparator The comparator to use for sorting. - * @return A copy of the original Map's values, - * sorted using the supplied Comparator. - * @since VelocityTools 2.0.1 - */ - public <T> Collection<T> sort(final Map<?,T> map, - final Comparator<T> comparator) - { - return sort(map.values(), comparator); - } - - /** - * Sorts a Collection (or array, or Map's values) - * using a Comparator. A defensive copy is made - * of the original beforehand, so the original is left - * untouched. Unsupported collection objects result in - * a <code>null</code> return value. - * - * @param o The Collection to sort. - * @param comparator The comparator to use for sorting. - * @return A copy of the original Collection, - * sorted using the supplied Comparator. - * @since VelocityTools 2.0.1 - */ - public Collection<?> sort(final Object o, - final Comparator<?> comparator) - { - if (o instanceof Collection) - { - return sort((Collection<?>)o, comparator); - } - else if (o instanceof Object[]) - { - return sort((Object[])o, comparator); - } - else if (o instanceof Map) - { - return sort((Map<?,?>)o, comparator); - } - else - { - // the object type is not supported - getLog().error("object type not supported: {}", o == null ? "null" : o.getClass().getName()); - return null; - } - } - - public Collection sort(Collection collection) - { - return sort(collection, (List)null); - } - - public Collection sort(Object[] array) - { - return sort(array, (List)null); - } - - public Collection sort(Map map) - { - return sort(map, (List)null); - } - - /** - * Sorts the collection on a single property. - * - * @param object the collection to be sorted. - * @param property the property to sort on. - */ - public Collection sort(Object object, String property) - { - List properties = new ArrayList(1); - properties.add(property); - - if (object instanceof Collection) - { - return sort((Collection)object, properties); - } - else if (object instanceof Object[]) - { - return sort((Object[])object, properties); - } - else if (object instanceof Map) - { - return sort((Map)object, properties); - } - // the object type is not supported - getLog().error("object type not supported: {}", object == null ? "null" : object.getClass().getName()); - return null; - } - - public Collection sort(Collection collection, List properties) - { - List list = new ArrayList(collection.size()); - list.addAll(collection); - return internalSort(list, properties); - } - - public Collection sort(Map map, List properties) - { - return sort(map.values(), properties); - } - - public Collection sort(Object[] array, List properties) - { - return internalSort(Arrays.asList(array), properties); - } - - protected Collection internalSort(List list, List properties) - { - try - { - if (properties == null) - { - Collections.sort(list); - } else { - Collections.sort(list, new PropertiesComparator(properties)); - } - return list; - } - catch (Exception e) - { - getLog().error("exception encountered while sorting: {}", e.getMessage()); - return null; - } - } - - - /** - * Does all of the comparisons - */ - public static class PropertiesComparator - implements Comparator, java.io.Serializable - { - private static final int TYPE_ASCENDING = 1; - private static final int TYPE_DESCENDING = -1; - - public static final String TYPE_ASCENDING_SHORT = "asc"; - public static final String TYPE_DESCENDING_SHORT = "desc"; - - List properties; - int[] sortTypes; - - public PropertiesComparator(List props) - { - // copy the list so we can safely drop :asc and :desc suffixes - this.properties = new ArrayList(props.size()); - this.properties.addAll(props); - - // determine ascending/descending - sortTypes = new int[properties.size()]; - - for (int i = 0; i < properties.size(); i++) - { - if (properties.get(i) == null) - { - throw new IllegalArgumentException("Property " + i - + "is null, sort properties may not be null."); - } - - // determine if the property contains a sort type - // e.g "Name:asc" means sort by property Name ascending - String prop = properties.get(i).toString(); - int colonIndex = prop.indexOf(':'); - if (colonIndex != -1) - { - String sortType = prop.substring(colonIndex + 1); - properties.set(i, prop.substring(0, colonIndex)); - - if (TYPE_ASCENDING_SHORT.equalsIgnoreCase(sortType)) - { - sortTypes[i] = TYPE_ASCENDING; - } - else if (TYPE_DESCENDING_SHORT.equalsIgnoreCase(sortType)) - { - sortTypes[i] = TYPE_DESCENDING; - } - else - { - //FIXME: log this - // invalide property sort type. use default instead. - sortTypes[i] = TYPE_ASCENDING; - } - } - else - { - // default sort type is ascending. - sortTypes[i] = TYPE_ASCENDING; - } - } - } - - public int compare(Object lhs, Object rhs) - { - for (int i = 0; i < properties.size(); i++) - { - int comparison = 0; - String property = (String)properties.get(i); - - // properties must be comparable - Comparable left = getComparable(lhs, property); - Comparable right = getComparable(rhs, property); - - if (left == null && right != null) - { - // find out how right feels about left being null - comparison = right.compareTo(null); - // and reverse that (if it works) - comparison *= -1; - } - else if (left instanceof String) - { - //TODO: make it optional whether or not case is ignored - comparison = ((String)left).compareToIgnoreCase((String)right); - } - else if (left != null) - { - comparison = left.compareTo(right); - } - - // return the first difference we find - if (comparison != 0) - { - // multiplied by the sort direction, of course - return comparison * sortTypes[i]; - } - } - return 0; - } - } - - /** - * Safely retrieves the comparable value for the specified property - * from the specified object. Subclasses that wish to perform more - * advanced, efficient, or just different property retrieval methods - * should override this method to do so. - */ - protected static Comparable getComparable(Object object, String property) - { - try - { - return (Comparable)PropertyUtils.getProperty(object, property); - } - catch (Exception e) - { - throw new IllegalArgumentException("Could not retrieve comparable value for '" - + property + "' from " + object + ": " + e); - } - } - }