Author: jcompagner Date: Sat May 10 05:40:57 2008 New Revision: 655070 URL: http://svn.apache.org/viewvc?rev=655070&view=rev Log: WICKET-1596 New convenience methods for ValueMap
Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/CopyOnWriteValueMap.java wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/IValueMap.java wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/ValueMap.java wicket/trunk/wicket/src/test/java/org/apache/wicket/util/value/ValueMapTest.java Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/CopyOnWriteValueMap.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/CopyOnWriteValueMap.java?rev=655070&r1=655069&r2=655070&view=diff ============================================================================== --- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/CopyOnWriteValueMap.java (original) +++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/CopyOnWriteValueMap.java Sat May 10 05:40:57 2008 @@ -33,6 +33,7 @@ * if it is, a copy is made. * * @author Johan Compagner + * @author Doug Donohoe * @since 1.2.6 */ public class CopyOnWriteValueMap implements IValueMap, Serializable @@ -103,7 +104,8 @@ /** * @see java.util.Map#equals(Object) */ - public boolean equals(Object o) + @Override + public boolean equals(Object o) { return wrapped.equals(o); } @@ -315,8 +317,135 @@ /** * @see IValueMap#toString() */ - public String toString() + @Override + public String toString() { return super.toString(); } + + //// + //// getAs convenience methods + //// + + /** + * @see IValueMap#getAsBoolean(String) + * + */ + public Boolean getAsBoolean(String key) + { + return wrapped.getAsBoolean(key); + } + + /** + * @see IValueMap#getAsBoolean(String, boolean) + * + */ + public boolean getAsBoolean(String key, boolean defaultValue) + { + return wrapped.getAsBoolean(key, defaultValue); + } + + /** + * @see IValueMap#getAsInteger(String) + */ + public Integer getAsInteger(String key) + { + return wrapped.getAsInteger(key); + } + + /** + * @see IValueMap#getAsInteger(String, int) + */ + public int getAsInteger(String key, int defaultValue) + { + return wrapped.getAsInteger(key, defaultValue); + } + + /** + * @see IValueMap#getAsLong(String) + */ + public Long getAsLong(String key) + { + return wrapped.getAsLong(key); + } + + /** + * @see IValueMap#getAsLong(String, long) + */ + public long getAsLong(String key, long defaultValue) + { + return wrapped.getAsLong(key, defaultValue); + } + + /** + * @see IValueMap#getAsDouble(String) + */ + public Double getAsDouble(String key) + { + return wrapped.getAsDouble(key); + } + + /** + * @see IValueMap#getAsDouble(String, double) + */ + public double getAsDouble(String key, double defaultValue) + { + return wrapped.getAsDouble(key, defaultValue); + } + + /** + * @see IValueMap#getAsDuration(String) + */ + public Duration getAsDuration(String key) + { + return wrapped.getAsDuration(key); + } + + /** + * @see IValueMap#getAsDuration(String, Duration) + */ + public Duration getAsDuration(String key, Duration defaultValue) + { + return wrapped.getAsDuration(key, defaultValue); + } + + /** + * @see IValueMap#getAsTime(String) + */ + public Time getAsTime(String key) + { + return wrapped.getAsTime(key); + } + + /** + * @see IValueMap#getAsTime(String, Time) + */ + public Time getAsTime(String key, Time defaultValue) + { + return wrapped.getAsTime(key, defaultValue); + } + + /** + * @see IValueMap#getAsEnum(String, Class<T>) + */ + public <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass) + { + return wrapped.getAsEnum(key, eClass); + } + + /** + * @see IValueMap#getAsEnum + */ + public <T extends Enum<T>> T getAsEnum(String key, T defaultValue) + { + return wrapped.getAsEnum(key, defaultValue); + } + + /** + * @see IValueMap#getAsEnum(String, Class<T>, T) + */ + public <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass, T defaultValue) + { + return wrapped.getAsEnum(key, eClass, defaultValue); + } } \ No newline at end of file Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/IValueMap.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/IValueMap.java?rev=655070&r1=655069&r2=655070&view=diff ============================================================================== --- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/IValueMap.java (original) +++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/IValueMap.java Sat May 10 05:40:57 2008 @@ -29,6 +29,7 @@ * variety of convenience methods. * * @author Johan Compagner + * @author Doug Donohoe * @since 1.2.6 */ public interface IValueMap extends Map @@ -228,4 +229,218 @@ * @return the key with the correct writing */ String getKey(final String key); + + //// + //// getAs convenience methods + //// + + /** + * Retrieves a <code>Boolean</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid boolean or + * no value is in this <code>IValueMap</code> + * + */ + Boolean getAsBoolean(String key); + + /** + * Retrieves a <code>boolean</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid boolean or + * no value is in this <code>IValueMap</code> + * + */ + boolean getAsBoolean(String key, boolean defaultValue); + + /** + * Retrieves an <code>Integer</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid integer or + * no value is in this <code>IValueMap</code> + * + */ + Integer getAsInteger(String key); + + /** + * Retrieves an <code>integer</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid integer or + * no value is in this <code>IValueMap</code> + * + */ + int getAsInteger(String key, int defaultValue); + + /** + * Retrieves a <code>Long</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid long or + * no value is in this <code>IValueMap</code> + * + */ + Long getAsLong(String key); + + /** + * Retrieves a <code>long</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid long or + * no value is in this <code>IValueMap</code> + * + */ + long getAsLong(String key, long defaultValue); + + /** + * Retrieves a <code>Double</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid double or + * no value is in this <code>IValueMap</code> + * + */ + Double getAsDouble(String key); + + /** + * Retrieves a <code>double</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid double or + * no value is in this <code>IValueMap</code> + * + */ + double getAsDouble(String key, double defaultValue); + + /** + * Retrieves a <code>Duration</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid Duration or + * no value is in this <code>IValueMap</code> + * + */ + Duration getAsDuration(String key); + + /** + * Retrieves a <code>Duration</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid Duration or + * no value is in this <code>IValueMap</code> + * + */ + Duration getAsDuration(String key, Duration defaultValue); + + /** + * Retrieves a <code>Time</code> value by key. + * + * @param key + * the key + * + * @return the value or null if value is not a valid Time or + * no value is in this <code>IValueMap</code> + * + */ + Time getAsTime(String key); + + /** + * Retrieves a <code>Time</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default to return + * + * @return the value or defaultValue if value is not a valid Time or + * no value is in this <code>IValueMap</code> + * + */ + Time getAsTime(String key, Time defaultValue); + + /** + * Retrieves an <code>Enum</code> value by key. + * + * @param key + * the key + * + * @param eClass + * the enumeration class + * + * @return the value or null if value is not a valid value of the Enumeration or + * no value is in this <code>IValueMap</code> + * + */ + <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass); + + /** + * Retrieves an <code>Enum</code> value by key. + * + * @param key + * the key + * + * @param defaultValue + * the default value from the Enumeration (cannot be null) + * + * @return the value or defaultValue if value is not a valid value of the Enumeration or + * no value is in this <code>IValueMap</code> + * + */ + <T extends Enum<T>> T getAsEnum(String key, T defaultValue); + + /** + * Retrieves an <code>Enum</code> value by key. + * + * @param key + * the key + * + * @param eClass + * the enumeration class + * + * @param defaultValue + * the default value from the Enumeration (may be null) + * + * @return the value or defaultValue if value is not a valid value of the Enumeration or + * no value is in this <code>IValueMap</code> + * + */ + <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass, T defaultValue); } \ No newline at end of file Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/ValueMap.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/ValueMap.java?rev=655070&r1=655069&r2=655070&view=diff ============================================================================== --- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/ValueMap.java (original) +++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/value/ValueMap.java Sat May 10 05:40:57 2008 @@ -17,6 +17,8 @@ package org.apache.wicket.util.value; import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; @@ -53,14 +55,21 @@ * key/value string for diagnostics. * * @author Jonathan Locke + * @author Doug Donohoe * @since 1.2.6 */ public class ValueMap extends HashMap implements IValueMap { /** an empty <code>ValueMap</code>. */ - public static final ValueMap EMPTY_MAP = new ValueMap(); + public static final ValueMap EMPTY_MAP; - private static final long serialVersionUID = 1L; + /** create EMPTY_MAP, make immutable **/ + static { + EMPTY_MAP = new ValueMap(); + EMPTY_MAP.makeImmutable(); + } + + private static final long serialVersionUID = 1L; /** * <code>true</code> if this <code>ValueMap</code> has been made immutable. @@ -127,8 +136,7 @@ int equalsIndex2 = keyValuePairs.indexOf('=', delimiterIndex + 1); if (equalsIndex2 != -1) { - int delimiterIndex2 = keyValuePairs.lastIndexOf(delimiter, equalsIndex2); - delimiterIndex = delimiterIndex2; + delimiterIndex = keyValuePairs.lastIndexOf(delimiter, equalsIndex2); } else { @@ -192,8 +200,7 @@ } else { - throw new IllegalArgumentException("Invalid key value list: '" + keyValuePairs + - "'"); + throw new IllegalArgumentException("Invalid key value list: '" + keyValuePairs + '\''); } } } @@ -201,7 +208,8 @@ /** * @see java.util.Map#clear() */ - public final void clear() + @Override + public final void clear() { checkMutability(); super.clear(); @@ -418,7 +426,8 @@ /** * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ - public Object put(final Object key, final Object value) + @Override + public Object put(final Object key, final Object value) { checkMutability(); return super.put(key, value); @@ -469,7 +478,8 @@ /** * @see java.util.Map#putAll(java.util.Map) */ - public void putAll(final Map map) + @Override + public void putAll(final Map map) { checkMutability(); super.putAll(map); @@ -478,7 +488,8 @@ /** * @see java.util.Map#remove(java.lang.Object) */ - public Object remove(final Object key) + @Override + public Object remove(final Object key) { checkMutability(); return super.remove(key); @@ -489,19 +500,17 @@ */ public String getKey(final String key) { - Iterator iter = keySet().iterator(); - while (iter.hasNext()) - { - Object keyValue = iter.next(); - if (keyValue instanceof String) - { - String keyString = (String)keyValue; - if (key.equalsIgnoreCase(keyString)) - { - return keyString; - } - } - } + for (Object keyValue : keySet()) + { + if (keyValue instanceof String) + { + String keyString = (String) keyValue; + if (key.equalsIgnoreCase(keyString)) + { + return keyString; + } + } + } return null; } @@ -512,7 +521,8 @@ * the tag-attribute style of markup elements. For example: * <code>a="x" b="y" c="z"</code>. */ - public String toString() + @Override + public String toString() { final StringBuffer buffer = new StringBuffer(); for (final Iterator iterator = entrySet().iterator(); iterator.hasNext();) @@ -534,7 +544,7 @@ buffer.append(value); } - buffer.append("\""); + buffer.append('\"'); if (iterator.hasNext()) { buffer.append(' '); @@ -546,11 +556,260 @@ /** * Throws an exception if <code>ValueMap</code> is immutable. */ - private final void checkMutability() + private void checkMutability() { if (immutable) { throw new UnsupportedOperationException("Map is immutable"); } } + + //// + //// getAs convenience methods + //// + + /** + * @see IValueMap#getAsBoolean(String) + * + */ + public Boolean getAsBoolean(String key) + { + if (!containsKey(key)) return null; + + try + { + return getBoolean(key); + } + catch (StringValueConversionException ignored) + { + return null; + } + } + + /** + * @see IValueMap#getAsBoolean(String, boolean) + * + */ + public boolean getAsBoolean(String key, boolean defaultValue) + { + try + { + return getBoolean(key); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsInteger(String) + */ + public Integer getAsInteger(String key) + { + if (!containsKey(key)) return null; + + try + { + return getInt(key); + } + catch (StringValueConversionException ignored) + { + return null; + } + } + + /** + * @see IValueMap#getAsInteger(String, int) + */ + public int getAsInteger(String key, int defaultValue) + { + try + { + return getInt(key, defaultValue); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsLong(String) + */ + public Long getAsLong(String key) + { + if (!containsKey(key)) return null; + + try + { + return getLong(key); + } + catch (StringValueConversionException ignored) + { + return null; + } + } + + /** + * @see IValueMap#getAsLong(String, long) + */ + public long getAsLong(String key, long defaultValue) + { + try + { + return getLong(key, defaultValue); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsDouble(String) + */ + public Double getAsDouble(String key) + { + if (!containsKey(key)) return null; + + try + { + return getDouble(key); + } + catch (StringValueConversionException ignored) + { + return null; + } + } + + /** + * @see IValueMap#getAsDouble(String, double) + */ + public double getAsDouble(String key, double defaultValue) + { + try + { + return getDouble(key, defaultValue); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsDuration(String) + */ + public Duration getAsDuration(String key) + { + return getAsDuration(key, null); + } + + /** + * @see IValueMap#getAsDuration(String, Duration) + */ + public Duration getAsDuration(String key, Duration defaultValue) + { + if (!containsKey(key)) return defaultValue; + + try + { + return getDuration(key); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsTime(String) + */ + public Time getAsTime(String key) + { + return getAsTime(key, null); + } + + /** + * @see IValueMap#getAsTime(String, Time) + */ + public Time getAsTime(String key, Time defaultValue) + { + if (!containsKey(key)) return defaultValue; + + try + { + return getTime(key); + } + catch (StringValueConversionException ignored) + { + return defaultValue; + } + } + + /** + * @see IValueMap#getAsEnum(String, Class<T>) + */ + public <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass) + { + return getEnumImpl(key, eClass, null); + } + + /** + * @see IValueMap#getAsEnum + */ + public <T extends Enum<T>> T getAsEnum(String key, T defaultValue) + { + if (defaultValue == null) throw new IllegalArgumentException("Default value cannot be null"); + return getEnumImpl(key, defaultValue.getClass(), defaultValue); + } + + /** + * @see IValueMap#getAsEnum(String, Class<T>, T) + */ + public <T extends Enum<T>> T getAsEnum(String key, Class<T> eClass, T defaultValue) + { + return getEnumImpl(key, eClass, defaultValue); + } + + /** + * get enum implementation + */ + @SuppressWarnings({"unchecked"}) + private <T extends Enum<T>> T getEnumImpl(String key, Class<?> eClass, T defaultValue) + { + if (eClass == null) throw new IllegalArgumentException("eClass value cannot be null"); + + String value = getString(key); + if (value == null) return defaultValue; + + Method valueOf = null; + try + { + valueOf = eClass.getMethod("valueOf", String.class); + } + catch (NoSuchMethodException e) + { + throw new RuntimeException("Could not find method valueOf(String s) for " + eClass.getName(), e); + } + + try + { + return (T) valueOf.invoke(eClass, value); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Could not invoke method valueOf(String s) on " + eClass.getName(), e); + } + catch (InvocationTargetException e) + { + // IllegalArgumentException thrown if enum isn't defined - just return default + if (e.getCause() instanceof IllegalArgumentException) + { + return defaultValue; + } + throw new RuntimeException(e); // shouldn't happen + } + } } Modified: wicket/trunk/wicket/src/test/java/org/apache/wicket/util/value/ValueMapTest.java URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/util/value/ValueMapTest.java?rev=655070&r1=655069&r2=655070&view=diff ============================================================================== --- wicket/trunk/wicket/src/test/java/org/apache/wicket/util/value/ValueMapTest.java (original) +++ wicket/trunk/wicket/src/test/java/org/apache/wicket/util/value/ValueMapTest.java Sat May 10 05:40:57 2008 @@ -17,9 +17,12 @@ package org.apache.wicket.util.value; import junit.framework.TestCase; +import org.apache.wicket.util.time.Time; +import org.apache.wicket.util.time.Duration; /** * @author jcompagner + * @author Doug Donohoe */ public class ValueMapTest extends TestCase { @@ -98,4 +101,131 @@ assertEquals("val=ue3", vm.get("param3")); } + + /** + * Enumeration for testing + */ + public enum TestEnum { + one, two, three + } + + /** + * Test getting enums from value map + */ + public void testEnum() + { + String name = "name"; + + TestEnum fetch = TestEnum.valueOf("one"); + assertEquals(fetch, TestEnum.one); + + ValueMap vm = new ValueMap(); + vm.put(name, "one"); + + // test get + TestEnum test = vm.getAsEnum(name, TestEnum.class, TestEnum.three); + assertEquals(test, TestEnum.one); + + // test get alternate + test = vm.getAsEnum(name, TestEnum.three); + assertEquals(test, TestEnum.one); + + // test get alternate null + try { + vm.getAsEnum(name, (TestEnum) null); + fail("Should have thrown an exception"); + } + catch (IllegalArgumentException ignored) + { + + } + + // test get if nothing there + test = vm.getAsEnum("missing", TestEnum.class, TestEnum.two); + assertEquals(test, TestEnum.two); + + test = vm.getAsEnum("missing", TestEnum.class, null); + assertEquals(test, null); + + test = vm.getAsEnum("missing", TestEnum.class); + assertEquals(test, null); + + // test get if value doesn't match enum + vm.put(name, "bogus"); + test = vm.getAsEnum(name, TestEnum.class, TestEnum.one); + assertEquals(test, TestEnum.one); + } + + /** + * test other getAs methods + */ + public void testGetAs() + { + ValueMap vm = new ValueMap(); + + Boolean booleanValue = true; + Integer integerValue = 42; + Long longValue = integerValue * 1L; + Double doubleValue = integerValue * 1.0D; + Time timeValue = Time.milliseconds(System.currentTimeMillis()); + Duration durationValue = Duration.hours(1); + + boolean defBoolean = !booleanValue; + int defInteger = 10101; + long defLong = defInteger * 1L; + double defDouble = defInteger * 1.0D; + Time defTime = Time.milliseconds(System.currentTimeMillis()); + Duration defDuration = Duration.hours(42); + + vm.put("num", integerValue.toString()); + vm.put("num.bad", "xxx"); + vm.put("time", timeValue.toString()); + vm.put("time.bad", "xxx"); + vm.put("duration", durationValue.toString()); + vm.put("duration.bad", "xxx"); + vm.put("boolean", booleanValue.toString()); + vm.put("boolean.bad", "xxx"); + + // boolean + assertEquals(booleanValue, vm.getAsBoolean("boolean")); + assertNull(vm.getAsBoolean("boolean.bad")); + assertEquals(defBoolean, vm.getAsBoolean("boolean.bad", defBoolean)); + assertNull(vm.getAsBoolean("boolean.missing")); + assertEquals(defBoolean, vm.getAsBoolean("boolean.missing", defBoolean)); + + // integer + assertEquals(integerValue, vm.getAsInteger("num")); + assertNull(vm.getAsInteger("num.bad")); + assertEquals(defInteger, vm.getAsInteger("num.bad", defInteger)); + assertNull(vm.getAsInteger("num.missing")); + assertEquals(defInteger, vm.getAsInteger("num.missing", defInteger)); + + // long + assertEquals(longValue, vm.getAsLong("num")); + assertNull(vm.getAsLong("num.bad")); + assertEquals(defLong, vm.getAsLong("num.bad", defLong)); + assertNull(vm.getAsLong("num.missing")); + assertEquals(defLong, vm.getAsLong("num.missing", defLong)); + + // double + assertEquals(doubleValue, vm.getAsDouble("num")); + assertNull(vm.getAsDouble("num.bad")); + assertEquals(defDouble, vm.getAsDouble("num.bad", defDouble)); + assertNull(vm.getAsDouble("num.missing")); + assertEquals(defDouble, vm.getAsDouble("num.missing", defDouble)); + + // time + assertEquals(timeValue.toString(), vm.getAsTime("time").toString()); // use toSTring since equals seems broken + assertNull(vm.getAsTime("time.bad")); + assertEquals(defTime, vm.getAsTime("time.bad", defTime)); + assertNull(vm.getAsTime("time.missing")); + assertEquals(defTime, vm.getAsTime("time.missing", defTime)); + + // duration + assertEquals(durationValue, vm.getAsDuration("duration")); + assertNull(vm.getAsDuration("duration.bad")); + assertEquals(defDuration, vm.getAsDuration("duration.bad", defDuration)); + assertNull(vm.getAsDuration("duration.missing")); + assertEquals(defDuration, vm.getAsDuration("duration.missing", defDuration)); + } }