sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1480602 [9/15] - in /sis/branches/Android: ./ ide-project/ ide-project/NetBeans/ ide-project/NetBeans/nbproject/ ide-project/eclipse/ sis-app/src/main/java/org/apache/sis/cli/ sis-build-helper/ sis-build-helper/src/main/java/org/apache/sis...
Date Thu, 09 May 2013 12:24:20 GMT
Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Numbers.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Numbers.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Numbers.java [UTF-8] Thu May  9 12:24:13 2013
@@ -17,7 +17,7 @@
 package org.apache.sis.util;
 
 import java.util.Map;
-import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Queue;
 import java.util.Set;
@@ -26,11 +26,10 @@ import java.util.Collections;
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
-
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.util.CollectionsExt;
 
-import static org.apache.sis.util.collection.Collections.emptyQueue;
-import static org.apache.sis.util.collection.Collections.emptySortedSet;
+import static java.lang.Double.doubleToLongBits;
 
 
 /**
@@ -40,22 +39,32 @@ import static org.apache.sis.util.collec
  * @since   0.3 (derived from geotk-2.5)
  * @version 0.3
  * @module
+ *
+ * @see org.apache.sis.math.MathFunctions
  */
 public final class Numbers extends Static {
     /**
-     * Constant of value {@value} used in {@code switch} statements or as index in arrays.
+     * Constant of value {@value} used in {@code switch} statements or as index in arrays.
      */
     public static final byte
+            BIG_DECIMAL=10, BIG_INTEGER=9,
             DOUBLE=8, FLOAT=7, LONG=6, INTEGER=5, SHORT=4, BYTE=3, CHARACTER=2, BOOLEAN=1, OTHER=0;
-    // Note: This class assumes that DOUBLE is the greatest public constant.
 
     /**
      * Mapping between a primitive type and its wrapper, if any.
+     *
+     * {@note In the particular case of <code>Class</code> keys, <code>IdentityHashMap</code> and
+     *        <code>HashMap</code> have identical behavior since <code>Class</code> is final and
+     *        does not override the <code>equals(Object)</code> and <code>hashCode()</code> methods.
+     *        The <code>IdentityHashMap</code> Javadoc claims that it is faster than the regular
+     *        <code>HashMap</code>. But maybe the most interesting property is that it allocates
+     *        less objects since <code>IdentityHashMap</code> implementation doesn't need the chain
+     *        of objects created by <code>HashMap</code>.}
      */
-    private static final Map<Class<?>,Numbers> MAPPING = new HashMap<Class<?>,Numbers>(16);
+    private static final Map<Class<?>,Numbers> MAPPING = new IdentityHashMap<Class<?>,Numbers>(11);
     static {
-        new Numbers(BigDecimal.class, true, false, (byte) (DOUBLE+2)); // Undocumented enum.
-        new Numbers(BigInteger.class, false, true, (byte) (DOUBLE+1)); // Undocumented enum.
+        new Numbers(BigDecimal.class, true, false, BIG_DECIMAL);
+        new Numbers(BigInteger.class, false, true, BIG_INTEGER);
         new Numbers(Double   .TYPE, Double   .class, true,  false, (byte) Double   .SIZE, DOUBLE,    'D', Double   .valueOf(Double.NaN));
         new Numbers(Float    .TYPE, Float    .class, true,  false, (byte) Float    .SIZE, FLOAT,     'F', Float    .valueOf(Float .NaN));
         new Numbers(Long     .TYPE, Long     .class, false, true,  (byte) Long     .SIZE, LONG,      'J', Long     .valueOf(        0L));
@@ -275,6 +284,7 @@ public final class Numbers extends Stati
         }
         if (c1 == null) return c2;
         if (c2 == null) return c1;
+        // At this point, m1 and m2 can not be null.
         return (m1.ordinal >= m2.ordinal) ? c1 : c2;
     }
 
@@ -295,7 +305,7 @@ public final class Numbers extends Stati
             throws IllegalArgumentException
     {
         return narrowestClass((n1 != null) ? n1.getClass() : null,
-                           (n2 != null) ? n2.getClass() : null);
+                              (n2 != null) ? n2.getClass() : null);
     }
 
     /**
@@ -336,152 +346,121 @@ public final class Numbers extends Stati
         }
         if (c1 == null) return c2;
         if (c2 == null) return c1;
+        // At this point, m1 and m2 can not be null.
         return (m1.ordinal < m2.ordinal) ? c1 : c2;
     }
 
     /**
-     * Returns the smallest class capable to hold the specified value. If the given value is
-     * {@code null}, then this method returns {@code null}. Otherwise this method delegates
-     * to {@link #narrowestClass(double)} or {@link #narrowestClass(long)} depending on the value type.
-     *
-     * @param  value The value to be wrapped in a finer (if possible) {@link Number}.
-     * @return The narrowest type capable to hold the given value.
-     *
-     * @see #narrowestNumber(Number)
-     */
-    public static Class<? extends Number> narrowestClass(final Number value) {
-        if (value == null) {
-            return null;
-        }
-        if (isPrimitiveInteger(value.getClass())) {
-            return narrowestClass(value.longValue());
-        } else {
-            return narrowestClass(value.doubleValue());
-        }
-    }
-
-    /**
      * Returns the smallest class capable to hold the specified value.
-     * This is similar to {@link #narrowestClass(long)}, but extended to floating point values.
-     *
-     * @param  value The value to be wrapped in a {@link Number}.
-     * @return The narrowest type capable to hold the given value.
-     *
-     * @see #narrowestNumber(double)
-     */
-    public static Class<? extends Number> narrowestClass(final double value) {
-        final long lg = (long) value;
-        if (value == lg) {
-            return narrowestClass(lg);
-        }
-        final float fv = (float) value;
-        if (Double.doubleToRawLongBits(value) == Double.doubleToRawLongBits(fv)) {
-            return Float.class;
-        }
-        return Double.class;
-    }
-
-    /**
-     * Returns the smallest class capable to hold the specified value.
-     * This method makes the following choice:
+     * This method applies the following choices, in that order:
      *
      * <ul>
-     *   <li>If the given value is between {@value java.lang.Byte#MIN_VALUE} and
+     *   <li>If the given value is {@code null}, then this method returns {@code null}.</li>
+     *   <li>Otherwise if the given value can not be casted from {@code double} to an other type
+     *       without precision lost, return {@code Double.class}.</li>
+     *   <li>Otherwise if the given value can not be casted from {@code float} to an other type
+     *       without precision lost, return {@code Float.class}.</li>
+     *   <li>Otherwise if the given value is between {@value java.lang.Byte#MIN_VALUE} and
      *       {@value java.lang.Byte#MAX_VALUE}, then this method returns {@code Byte.class};</li>
-     *   <li>If the given value is between {@value java.lang.Short#MIN_VALUE} and
+     *   <li>Otherwise if the given value is between {@value java.lang.Short#MIN_VALUE} and
      *       {@value java.lang.Short#MAX_VALUE}, then this method returns {@code Short.class};</li>
-     *   <li>If the given value is between {@value java.lang.Integer#MIN_VALUE} and
+     *   <li>Otherwise if the given value is between {@value java.lang.Integer#MIN_VALUE} and
      *       {@value java.lang.Integer#MAX_VALUE}, then this method returns {@code Integer.class};</li>
      *   <li>Otherwise this method returns {@code Long.class};</li>
      * </ul>
      *
-     * @param  value The value to be wrapped in a {@link Number}.
+     * @param  value The value to be wrapped in a finer (if possible) {@link Number}.
      * @return The narrowest type capable to hold the given value.
      *
-     * @see #narrowestNumber(long)
+     * @see #narrowestNumber(Number)
      */
-    public static Class<? extends Number> narrowestClass(final long value) {
-        // Tests MAX_VALUE before MIN_VALUE because it is more likely to fail.
-        if (value <= Byte   .MAX_VALUE  &&  value >= Byte   .MIN_VALUE) return Byte.class;
-        if (value <= Short  .MAX_VALUE  &&  value >= Short  .MIN_VALUE) return Short.class;
-        if (value <= Integer.MAX_VALUE  &&  value >= Integer.MIN_VALUE) return Integer.class;
-        return Long.class;
+    @SuppressWarnings("fallthrough")
+    public static Class<? extends Number> narrowestClass(final Number value) {
+        if (value == null) {
+            return null;
+        }
+        boolean isFloat = false;
+        final long longValue = value.longValue();
+        switch (getEnumConstant(value.getClass())) {
+            default: {
+                final double doubleValue = value.doubleValue();
+                final float  floatValue  = (float) doubleValue;
+                isFloat = (doubleToLongBits(floatValue) == doubleToLongBits(doubleValue));
+                if (doubleValue != longValue) {
+                    return isFloat ? Float.class : Double.class;
+                }
+                // Fall through.
+            }
+            case LONG:    if (((int)   longValue) != longValue) return isFloat ? Float.class : Long.class;
+            case INTEGER: if (((short) longValue) != longValue) return Integer.class;
+            case SHORT:   if (((byte)  longValue) != longValue) return Short  .class;
+            case BYTE:    return Byte.class;
+        }
     }
 
     /**
-     * Returns the number of the smallest class capable to hold the specified value. If the
-     * given value is {@code null}, then this method returns {@code null}. Otherwise this
-     * method delegates to {@link #narrowestNumber(double)} or {@link #narrowestNumber(long)}
-     * depending on the value type.
+     * Returns the given number wrapped in the smallest class capable to hold the specified value.
+     * This method is equivalent to the following code, in a slightly more efficient way:
+     *
+     * {@preformat java
+     *     return cast(value, narrowestClass(value));
+     * }
      *
      * @param  value The value to be wrapped in a finer (if possible) {@link Number}.
      * @return The narrowest type capable to hold the given value.
      *
      * @see #narrowestClass(Number)
+     * @see #cast(Number, Class)
      */
+    @SuppressWarnings("fallthrough")
     public static Number narrowestNumber(final Number value) {
         if (value == null) {
             return null;
         }
         final Number candidate;
-        if (isPrimitiveInteger(value.getClass())) {
-            candidate = narrowestNumber(value.longValue());
-        } else {
-            candidate = narrowestNumber(value.doubleValue());
+        boolean isFloat = false;
+        final long longValue = value.longValue();
+        switch (getEnumConstant(value.getClass())) {
+            default: {
+                final double doubleValue = value.doubleValue();
+                final float  floatValue  = (float) doubleValue;
+                isFloat = (doubleToLongBits(floatValue) == doubleToLongBits(doubleValue));
+                if (doubleValue != longValue) {
+                    candidate = isFloat ? ((Number) Float .valueOf(floatValue))
+                                        : ((Number) Double.valueOf(doubleValue));
+                    break;
+                }
+                // Fall through everywhere.
+            }
+            case LONG: {
+                if (((int) longValue) != longValue) {
+                    candidate = isFloat ? ((Number) Float.valueOf((float) longValue))
+                                        : ((Number) Long.valueOf(longValue));
+                    break;
+                }
+            }
+            case INTEGER: {
+                if (((short) longValue) != longValue) {
+                    candidate = Integer.valueOf((int) longValue);
+                    break;
+                }
+            }
+            case SHORT: {
+                if (((byte) longValue) != longValue) {
+                    candidate = Short.valueOf((short) longValue);
+                    break;
+                }
+            }
+            case BYTE: {
+                candidate = Byte.valueOf((byte) longValue);
+                break;
+            }
         }
         // Keep the existing instance if possible.
         return value.equals(candidate) ? value : candidate;
     }
 
     /**
-     * Returns the number of the smallest class capable to hold the specified value.
-     * This is similar to {@link #narrowestNumber(long)}, but extended to floating point values.
-     *
-     * @param  value The value to be wrapped in a {@link Number}.
-     * @return The narrowest type capable to hold the given value.
-     *
-     * @see #narrowestClass(double)
-     */
-    public static Number narrowestNumber(final double value) {
-        final long lg = (long) value;
-        if (value == lg) {
-            return narrowestNumber(lg);
-        }
-        final float fv = (float) value;
-        if (Double.doubleToRawLongBits(value) == Double.doubleToRawLongBits(fv)) {
-            return Float.valueOf(fv);
-        }
-        return Double.valueOf(value);
-    }
-
-    /**
-     * Returns the number of the smallest type capable to hold the specified value.
-     * This method makes the following choice:
-     *
-     * <ul>
-     *   <li>If the given value is between {@value java.lang.Byte#MIN_VALUE} and
-     *       {@value java.lang.Byte#MAX_VALUE}, then it is wrapped in a {@link Byte} object.</li>
-     *   <li>If the given value is between {@value java.lang.Short#MIN_VALUE} and
-     *       {@value java.lang.Short#MAX_VALUE}, then it is wrapped in a {@link Short} object.</li>
-     *   <li>If the given value is between {@value java.lang.Integer#MIN_VALUE} and
-     *       {@value java.lang.Integer#MAX_VALUE}, then it is wrapped in an {@link Integer} object.</li>
-     *   <li>Otherwise the value is wrapped in a {@link Long} object.</li>
-     * </ul>
-     *
-     * @param  value The value to be wrapped in a {@link Number}.
-     * @return The given value as a number of the narrowest type capable to hold it.
-     *
-     * @see #narrowestClass(long)
-     */
-    public static Number narrowestNumber(final long value) {
-        // Tests MAX_VALUE before MIN_VALUE because it is more likely to fail.
-        if (value <= Byte   .MAX_VALUE  &&  value >= Byte   .MIN_VALUE) return Byte   .valueOf((byte)  value);
-        if (value <= Short  .MAX_VALUE  &&  value >= Short  .MIN_VALUE) return Short  .valueOf((short) value);
-        if (value <= Integer.MAX_VALUE  &&  value >= Integer.MIN_VALUE) return Integer.valueOf((int)   value);
-        return Long.valueOf(value);
-    }
-
-    /**
      * Returns the smallest number capable to hold the specified value.
      *
      * @param  value The value to be wrapped in a {@link Number}.
@@ -489,11 +468,10 @@ public final class Numbers extends Stati
      * @throws NumberFormatException if the given value can not be parsed as a number.
      *
      * @see #narrowestNumber(Number)
-     * @see #narrowestNumber(double)
-     * @see #narrowestNumber(long)
      */
-    public static Number narrowestNumber(String value) throws NumberFormatException {
-        value = CharSequences.trimWhitespaces(value);
+    public static Number narrowestNumber(final String value) throws NumberFormatException {
+        // Do not trim whitespaces. It is up to the caller to do that if he wants.
+        // For such low level function, we are better to avoid hidden initiative.
         final int length = value.length();
         for (int i=0; i<length; i++) {
             final char c = value.charAt(i);
@@ -506,45 +484,118 @@ public final class Numbers extends Stati
 
     /**
      * Casts a number to the specified class. The class must by one of {@link Byte},
-     * {@link Short}, {@link Integer}, {@link Long}, {@link Float} or {@link Double}.
+     * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, {@link Double},
+     * {@link BigInteger} or {@link BigDecimal}.
      * This method makes the following choice:
      *
      * <ul>
      *   <li>If the given type is {@code Double.class}, then this method returns
-     *       <code>{@linkplain Double#valueOf(double) Double.valueOf}(n.doubleValue())</code>;</li>
+     *       <code>{@linkplain Double#valueOf(double) Double.valueOf}(number.doubleValue())</code>;</li>
      *   <li>If the given type is {@code Float.class}, then this method returns
-     *       <code>{@linkplain Float#valueOf(float) Float.valueOf}(n.floatValue())</code>;</li>
+     *       <code>{@linkplain Float#valueOf(float) Float.valueOf}(number.floatValue())</code>;</li>
      *   <li>And likewise for all remaining known types.</li>
      * </ul>
      *
-     * {@note This method is intentionally restricted to primitive types. Other types
-     *        like <code>BigDecimal</code> are not the purpose of this method. See the
-     *        <code>ConverterRegistry</code> class for a more generic method.}
-     *
-     * @param <N> The class to cast to.
-     * @param n The number to cast.
-     * @param c The destination type.
-     * @return The number casted to the given type.
-     * @throws IllegalArgumentException If the given type is unknown.
+     * This method does not verify if the given type is wide enough for the given value,
+     * because the type has typically been calculated by {@link #widestClass(Class, Class)}
+     * or {@link #narrowestClass(Number)}. If nevertheless the given type is not wide enough,
+     * then the behavior depends on the implementation of the corresponding
+     * {@code Number.fooValue()} method - typically, the value is just rounded or truncated.
+     *
+     * @param  <N>    The class to cast to.
+     * @param  number The number to cast, or {@code null}.
+     * @param  type   The destination type.
+     * @return The number casted to the given type, or {@code null} if the given value was null.
+     * @throws IllegalArgumentException If the given type is not one of the primitive
+     *         wrappers for numeric types.
      */
     @SuppressWarnings("unchecked")
-    public static <N extends Number> N cast(final Number n, final Class<N> c)
+    public static <N extends Number> N cast(final Number number, final Class<N> type)
             throws IllegalArgumentException
     {
-        if (n == null || n.getClass() == c) {
-            return (N) n;
+        if (number == null || number.getClass() == type) {
+            return (N) number;
         }
-        if (c == Byte   .class) return (N) Byte   .valueOf(n.  byteValue());
-        if (c == Short  .class) return (N) Short  .valueOf(n. shortValue());
-        if (c == Integer.class) return (N) Integer.valueOf(n.   intValue());
-        if (c == Long   .class) return (N) Long   .valueOf(n.  longValue());
-        if (c == Float  .class) return (N) Float  .valueOf(n. floatValue());
-        if (c == Double .class) return (N) Double .valueOf(n.doubleValue());
-        throw unknownType(c);
+        switch (getEnumConstant(type)) {
+            case BYTE:    return (N) Byte   .valueOf(number.  byteValue());
+            case SHORT:   return (N) Short  .valueOf(number. shortValue());
+            case INTEGER: return (N) Integer.valueOf(number.   intValue());
+            case LONG:    return (N) Long   .valueOf(number.  longValue());
+            case FLOAT:   return (N) Float  .valueOf(number. floatValue());
+            case DOUBLE:  return (N) Double .valueOf(number.doubleValue());
+            case BIG_INTEGER: {
+                final BigInteger c;
+                if (number instanceof BigInteger) {
+                    c = (BigInteger) number;
+                } else if (number instanceof BigDecimal) {
+                    c = ((BigDecimal) number).toBigInteger();
+                } else {
+                    c = BigInteger.valueOf(number.longValue());
+                }
+                return (N) c;
+            }
+            case BIG_DECIMAL: {
+                final BigDecimal c;
+                if (number instanceof BigDecimal) {
+                    c = (BigDecimal) number;
+                } else if (number instanceof BigInteger) {
+                    c = new BigDecimal((BigInteger) number);
+                } else if (isInteger(number.getClass())) {
+                    c = BigDecimal.valueOf(number.longValue());
+                } else {
+                    c = BigDecimal.valueOf(number.doubleValue());
+                }
+                return (N) c;
+            }
+            default: {
+                if (type.isInstance(number)) {
+                    return (N) number;
+                }
+                throw unknownType(type);
+            }
+        }
+    }
+
+    /**
+     * Wraps the given value in a {@code Number} of the specified class.
+     * The given type shall be one of {@link Byte}, {@link Short}, {@link Integer}, {@link Long},
+     * {@link Float}, {@link Double}, {@link BigInteger} and {@link BigDecimal} classes.
+     * Furthermore, the given value shall be convertible to the given class without precision lost,
+     * otherwise an {@link IllegalArgumentException} will be thrown.
+     *
+     * @param  <N> The wrapper class.
+     * @param  value The value to wrap.
+     * @param  type The desired wrapper class.
+     * @return The value wrapped in an object of the given class.
+     * @throws IllegalArgumentException If the given type is not one of the primitive
+     *         wrappers for numeric types, or if the given value can not be wrapped in
+     *         an instance of the given class without precision lost.
+     */
+    @SuppressWarnings("unchecked")
+    public static <N extends Number> N wrap(final double value, final Class<N> type)
+            throws IllegalArgumentException
+    {
+        final N number;
+        switch (getEnumConstant(type)) {
+            case BYTE:        number = (N) Byte      .valueOf((byte)  value); break;
+            case SHORT:       number = (N) Short     .valueOf((short) value); break;
+            case INTEGER:     number = (N) Integer   .valueOf((int)   value); break;
+            case LONG:        number = (N) Long      .valueOf((long)  value); break;
+            case FLOAT:       number = (N) Float     .valueOf((float) value); break;
+            case DOUBLE:      return   (N) Double    .valueOf(value); // No need to verify.
+            case BIG_INTEGER: number = (N) BigInteger.valueOf((long) value); break;
+            case BIG_DECIMAL: return   (N) BigDecimal.valueOf(value); // No need to verify.
+            default: throw unknownType(type);
+        }
+        if (doubleToLongBits(number.doubleValue()) != doubleToLongBits(value)) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.CanNotConvertValue_2, value, type));
+        }
+        return number;
     }
 
     /**
      * Converts the specified string into a value object. The value object can be an instance of
+     * {@link BigDecimal}, {@link BigInteger},
      * {@link Double}, {@link Float}, {@link Long}, {@link Integer}, {@link Short}, {@link Byte},
      * {@link Boolean}, {@link Character} or {@link String} according the specified type. This
      * method makes the following choice:
@@ -557,45 +608,45 @@ public final class Numbers extends Stati
      *   <li>And likewise for all remaining known types.</li>
      * </ul>
      *
-     * {@note This method is intentionally restricted to primitive types, with the addition of
-     *        <code>String</code> which can be though as an identity operation. Other types
-     *        like <code>BigDecimal</code> are not the purpose of this method. See the
-     *        <code>ConverterRegistry</code> class for a more generic method.}
-     *
      * @param  <T> The requested type.
-     * @param  type The requested type.
      * @param  value the value to parse.
+     * @param  type The requested type.
      * @return The value object, or {@code null} if {@code value} was null.
      * @throws IllegalArgumentException if {@code type} is not a recognized type.
      * @throws NumberFormatException if {@code type} is a subclass of {@link Number} and the
      *         string value is not parseable as a number of the specified type.
      */
     @SuppressWarnings("unchecked")
-    public static <T> T valueOf(final Class<T> type, String value)
+    public static <T> T valueOf(final String value, final Class<T> type)
             throws IllegalArgumentException, NumberFormatException
     {
         if (value == null || type == String.class) {
             return (T) value;
         }
-        if (type == Character.class) {
-            /*
-             * If the string is empty, returns 0 which means "end of string" in C/C++
-             * and NULL in Unicode standard. If non-empty, take only the first char.
-             * This is somewhat consistent with Boolean.valueOf(...) which is quite
-             * lenient about the parsing as well, and throwing a NumberFormatException
-             * for those would not be appropriate.
-             */
-            return (T) Character.valueOf(value.isEmpty() ? 0 : value.charAt(0));
-        }
-        value = CharSequences.trimWhitespaces(value);
-        if (type == Double .class) return (T) Double .valueOf(value);
-        if (type == Float  .class) return (T) Float  .valueOf(value);
-        if (type == Long   .class) return (T) Long   .valueOf(value);
-        if (type == Integer.class) return (T) Integer.valueOf(value);
-        if (type == Short  .class) return (T) Short  .valueOf(value);
-        if (type == Byte   .class) return (T) Byte   .valueOf(value);
-        if (type == Boolean.class) return (T) Boolean.valueOf(value);
-        throw unknownType(type);
+        switch (getEnumConstant(type)) {
+            case CHARACTER: {
+                /*
+                 * If the string is empty, returns 0 which means "end of string" in C/C++
+                 * and NULL in Unicode standard. If non-empty, take only the first char.
+                 * This is somewhat consistent with Boolean.valueOf(...) which is quite
+                 * lenient about the parsing as well, and throwing a NumberFormatException
+                 * for those would not be appropriate.
+                 */
+                return (T) Character.valueOf(value.isEmpty() ? 0 : value.charAt(0));
+            }
+            // Do not trim whitespaces. It is up to the caller to do that if he wants.
+            // For such low level function, we are better to avoid hidden initiative.
+            case BOOLEAN:     return (T) Boolean.valueOf(value);
+            case BYTE:        return (T) Byte   .valueOf(value);
+            case SHORT:       return (T) Short  .valueOf(value);
+            case INTEGER:     return (T) Integer.valueOf(value);
+            case LONG:        return (T) Long   .valueOf(value);
+            case FLOAT:       return (T) Float  .valueOf(value);
+            case DOUBLE:      return (T) Double .valueOf(value);
+            case BIG_INTEGER: return (T) new BigInteger(value);
+            case BIG_DECIMAL: return (T) new BigDecimal(value);
+            default: throw unknownType(type);
+        }
     }
 
     /**
@@ -642,8 +693,8 @@ public final class Numbers extends Stati
         } else if (type != null && type != Object.class) {
             if (type == Map      .class) return (T) Collections.EMPTY_MAP;
             if (type == List     .class) return (T) Collections.EMPTY_LIST;
-            if (type == Queue    .class) return (T) emptyQueue();
-            if (type == SortedSet.class) return (T) emptySortedSet();
+            if (type == Queue    .class) return (T) CollectionsExt.emptyQueue();
+            if (type == SortedSet.class) return (T) CollectionsExt.emptySortedSet();
             if (type.isAssignableFrom(Set.class)) {
                 return (T) Collections.EMPTY_SET;
             }
@@ -656,8 +707,10 @@ public final class Numbers extends Stati
     }
 
     /**
-     * Returns one of {@link #DOUBLE}, {@link #FLOAT}, {@link #LONG}, {@link #INTEGER},
-     * {@link #SHORT}, {@link #BYTE}, {@link #CHARACTER}, {@link #BOOLEAN} or {@link #OTHER}
+     * Returns a numeric constant for the given type.
+     * The constants are {@link #BIG_DECIMAL}, {@link #BIG_INTEGER},
+     * {@link #DOUBLE}, {@link #FLOAT}, {@link #LONG}, {@link #INTEGER},
+     * {@link #SHORT}, {@link #BYTE}, {@link #CHARACTER}, {@link #BOOLEAN}, or {@link #OTHER}
      * constants for the given type. This is a commodity for usage in {@code switch} statements.
      *
      * @param type A type (usually either a primitive type or its wrapper).
@@ -665,13 +718,7 @@ public final class Numbers extends Stati
      */
     public static byte getEnumConstant(final Class<?> type) {
         final Numbers mapping = MAPPING.get(type);
-        if (mapping != null) {
-            // Filter out the non-public enum for BigDecimal and BigInteger.
-            if (mapping.size >= 0) {
-                return mapping.ordinal;
-            }
-        }
-        return OTHER;
+        return (mapping != null) ? mapping.ordinal : OTHER;
     }
 
     /**

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Numbers.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java [UTF-8] Thu May  9 12:24:13 2013
@@ -25,23 +25,38 @@ import org.apache.sis.math.FunctionPrope
  * The source and target types may be the same, in which case the {@code ObjectConverter} actually converts
  * the values rather than the type.
  *
- * <p>The main method of this interface is {@link #convert(Object)}, which receive an object of type
- * <var>S</var> and returns an object of type <var>T</var>. Some characteristics about the <var>S</var>
- * to <var>T</var> mapping are given by the {@link #properties()} enumeration, together with the
- * {@link #getSourceClass()} and {@link #getTargetClass()} methods.</p>
- *
- * <p>The <cite>domain</cite> of this function is the set of all values of type <var>S</var> for
- * which the {@link #convert(Object)} method does not throw {@link UnconvertibleObjectException}.
- * Note that values for which {@code convert(S)} returns {@code null} are considered as part of
- * the domain, even if the {@code null} target value stands for unconvertible source values.</p>
+ * <p>The main method of this interface is {@link #convert(Object)}, which receives an object of type
+ * <var>S</var> and returns an object of type <var>T</var>. The set of all <var>S</var> values for which
+ * {@code convert(S)} does not throw {@link UnconvertibleObjectException} is called the <cite>domain</cite>
+ * of this function, regardless of whether the <var>T</var> result is {@code null} or not.</p>
+ *
+ * {@section Function properties}
+ * Some characteristics about the <var>S</var> to <var>T</var> mapping are given by the
+ * {@link #properties()} enumeration, together with the {@link #getSourceClass()} and
+ * {@link #getTargetClass()} methods. Some possible function properties are:
  *
- * <p>The above definition affects the function {@linkplain #properties() properties}
- * that this converter can declare:</p>
+ * <ul>
+ *   <li>{@linkplain FunctionProperty#INJECTIVE Injective} if no pair of <var>S</var> can produce
+ *       the same <var>T</var> value (e.g.: conversions from {@link Integer} to {@code String}).</li>
+ *   <li>{@linkplain FunctionProperty#SURJECTIVE Surjective} if every values of <var>T</var> can be
+ *       created from one or many values of <var>S</var> (e.g.: conversions from {@link String} to
+ *       {@link Integer}).</li>
+ *   <li>{@linkplain FunctionProperty#isBijective Bijective} if there is a one-to-one
+ *       relationship between the <var>S</var> and <var>T</var> values.</li>
+ *   <li>{@linkplain FunctionProperty#ORDER_PRESERVING Order preserving} if any sequence of
+ *       increasing <var>S</var> values (in the sense of {@link Comparable}) is mapped to a
+ *       sequence of increasing <var>T</var> values.</li>
+ *   <li>{@linkplain FunctionProperty#ORDER_REVERSING Order reversing} if any sequence of
+ *       increasing <var>S</var> values (in the sense of {@link Comparable}) is mapped to
+ *       a sequence of decreasing <var>T</var> values.</li>
+ * </ul>
+ *
+ * Below are some guidelines about the function properties that a converter can declare:
  *
  * <ul>
  *   <li>If {@code convert(S)} returns {@code null} for unconvertible objects, then this {@code ObjectConverter}
- *       can not declare {@link FunctionProperty#INJECTIVE} in its set of {@linkplain #properties() properties},
- *       because more than one source value can produce the same target value (namely {@code null}).</li>
+ *       can not be declared injective because more than one <var>S</var> value can produce the same
+ *       <var>T</var> value (namely {@code null}).</li>
  *   <li>If {@code convert(S)} throws an exception for unconvertible objects, then this {@code ObjectConverter}
  *       can be declared as an injective function if the other values meet the criteria.
  * </ul>

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java [UTF-8] Thu May  9 12:24:13 2013
@@ -18,10 +18,44 @@ package org.apache.sis.util;
 
 import java.util.Map;
 import java.util.Set;
+import org.apache.sis.util.collection.Containers;
+import org.apache.sis.internal.converter.IdentityConverter;
+import org.apache.sis.internal.converter.SystemRegistry;
 
 
 /**
  * Creates {@link ObjectConverter} instances, or uses them for creating collection views.
+ * Converters are created by the following methods:
+ *
+ * <ul>
+ *   <li>{@link #identity(Class)}</li>
+ *   <li>{@link #find(Class, Class)}</li>
+ * </ul>
+ *
+ * Converters can be used for creating derived collections by the following methods:
+ *
+ * <ul>
+ *   <li>{@link #derivedSet(Set, ObjectConverter)}</li>
+ *   <li>{@link #derivedMap(Map, ObjectConverter, ObjectConverter)}</li>
+ *   <li>{@link #derivedKeys(Map, ObjectConverter, Class)}</li>
+ *   <li>{@link #derivedValues(Map, Class, ObjectConverter)}</li>
+ * </ul>
+ *
+ * {@section Example}
+ * The following code convert instances in a collection from type {@code S} to type {@code T},
+ * where the types are unknown at compile-time. Note that the converter is obtained only once
+ * before to be applied to every elements in the loop.
+ *
+ * {@preformat java
+ *     Class<S> sourceType = ...
+ *     Class<T> targetType = ...
+ *     Collection<S> sources = ...;
+ *     Collection<T> targets = ...;
+ *     ObjectConverter<S,T> converter = ObjectConverters.find(sourceType, targetType);
+ *     for (S source : sources) {
+ *         targets.add(converter.convert(source));
+ *     }
+ * }
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-3.00)
@@ -44,7 +78,46 @@ public final class ObjectConverters exte
      */
     public static <T> ObjectConverter<T,T> identity(final Class<T> type) {
         ArgumentChecks.ensureNonNull("type", type);
-        return IdentityConverter.create(type);
+        return new IdentityConverter<T,T>(type, type, null).unique();
+    }
+
+    /**
+     * Returns a converter for the specified source and target classes.
+     *
+     * @param  <S> The source class.
+     * @param  <T> The target class.
+     * @param  source The source class.
+     * @param  target The target class, or {@code Object.class} for any.
+     * @return The converter from the specified source class to the target class.
+     * @throws UnconvertibleObjectException if no converter is found.
+     */
+    public static <S,T> ObjectConverter<? super S, ? extends T> find(final Class<S> source, final Class<T> target)
+            throws UnconvertibleObjectException
+    {
+        ArgumentChecks.ensureNonNull("source", source);
+        ArgumentChecks.ensureNonNull("target", target);
+        return SystemRegistry.INSTANCE.find(source, target);
+    }
+
+    /**
+     * Converts the given value to the given type. This convenience method shall be used only for
+     * rare conversions. For converting many instances between the same source and target classes,
+     * consider invoking {@link #find(Class, Class)} instead in order to reuse the same converter
+     * for all values to convert.
+     *
+     * @param  <T>    The type of the {@code target} class.
+     * @param  value  The value to convert, or {@code null}.
+     * @param  target The target class.
+     * @return The converted value (may be {@code null}).
+     * @throws UnconvertibleObjectException if the given value can not be converted.
+     */
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public static <T> T convert(Object value, final Class<T> target) throws UnconvertibleObjectException {
+        ArgumentChecks.ensureNonNull("target", target);
+        if (!target.isInstance(value) && value != null) {
+            value = ((ObjectConverter) SystemRegistry.INSTANCE.find(value.getClass(), target)).convert(value);
+        }
+        return (T) value;
     }
 
     /**
@@ -53,7 +126,7 @@ public final class ObjectConverters exte
      * by invoking the {@link ObjectConverter#convert(Object)} method on the given converter.
      *
      * <p>This convenience method delegates to
-     * {@link org.apache.sis.util.collection.Collections#derivedSet Collections.derivedSet(…)}.
+     * {@link Containers#derivedSet Containers.derivedSet(…)}.
      * See the javadoc of the above method for more information.
      *
      * @param  <S>       The type of elements in the storage (original) set.
@@ -64,10 +137,10 @@ public final class ObjectConverters exte
      * @return A view over the {@code storage} set containing all elements converted by the given
      *         converter, or {@code null} if {@code storage} was null.
      *
-     * @see org.apache.sis.util.collection.Collections#derivedSet(Set, ObjectConverter)
+     * @see Containers#derivedSet(Set, ObjectConverter)
      */
     public static <S,E> Set<E> derivedSet(final Set<S> storage, final ObjectConverter<S,E> converter) {
-        return org.apache.sis.util.collection.Collections.derivedSet(storage, converter);
+        return Containers.derivedSet(storage, converter);
     }
 
     /**
@@ -76,7 +149,7 @@ public final class ObjectConverters exte
      * by invoking the {@link ObjectConverter#convert(Object)} method on the given converters.
      *
      * <p>This convenience method delegates to
-     * {@link org.apache.sis.util.collection.Collections#derivedMap Collections.derivedMap(…)}.
+     * {@link Containers#derivedMap Containers.derivedMap(…)}.
      * See the javadoc of the above method for more information.
      *
      * @param <SK>         The type of keys   in the storage map.
@@ -89,13 +162,13 @@ public final class ObjectConverters exte
      * @return A view over the {@code storage} map containing all entries converted by the given
      *         converters, or {@code null} if {@code storage} was null.
      *
-     * @see org.apache.sis.util.collection.Collections#derivedMap(Map, ObjectConverter, ObjectConverter)
+     * @see Containers#derivedMap(Map, ObjectConverter, ObjectConverter)
      */
     public static <SK,SV,K,V> Map<K,V> derivedMap(final Map<SK,SV> storage,
                                                   final ObjectConverter<SK,K> keyConverter,
                                                   final ObjectConverter<SV,V> valueConverter)
     {
-        return org.apache.sis.util.collection.Collections.derivedMap(storage, keyConverter, valueConverter);
+        return Containers.derivedMap(storage, keyConverter, valueConverter);
     }
 
     /**
@@ -104,7 +177,7 @@ public final class ObjectConverters exte
      * invoking the {@link ObjectConverter#convert(Object)} method on the given converter.
      *
      * <p>This convenience method delegates to
-     * {@link org.apache.sis.util.collection.Collections#derivedMap Collections.derivedMap(…)}.
+     * {@link Containers#derivedMap Containers.derivedMap(…)}.
      * See the javadoc of the above method for more information.
      *
      * @param <SK>         The type of keys   in the storage map.
@@ -116,15 +189,14 @@ public final class ObjectConverters exte
      * @return A view over the {@code storage} map containing all entries with the keys converted
      *         by the given converter, or {@code null} if {@code storage} was null.
      *
-     * @see org.apache.sis.util.collection.Collections#derivedMap(Map, ObjectConverter, ObjectConverter)
+     * @see Containers#derivedMap(Map, ObjectConverter, ObjectConverter)
      */
     public static <SK,K,V> Map<K,V> derivedKeys(final Map<SK,V> storage,
                                                 final ObjectConverter<SK,K> keyConverter,
                                                 final Class<V> valueType)
     {
         ArgumentChecks.ensureNonNull("valueType", valueType);
-        return org.apache.sis.util.collection.Collections.derivedMap(storage,
-                keyConverter, IdentityConverter.create(valueType));
+        return Containers.derivedMap(storage, keyConverter, identity(valueType));
     }
 
     /**
@@ -133,7 +205,7 @@ public final class ObjectConverters exte
      * invoking the {@link ObjectConverter#convert(Object)} method on the given converter.
      *
      * <p>This convenience method delegates to
-     * {@link org.apache.sis.util.collection.Collections#derivedMap Collections.derivedMap(…)}.
+     * {@link Containers#derivedMap Containers.derivedMap(…)}.
      * See the javadoc of the above method for more information.
      *
      * @param <K>          The type of keys in the storage and derived map.
@@ -145,14 +217,13 @@ public final class ObjectConverters exte
      * @return A view over the {@code storage} map containing all entries with the values converted
      *         by the given converter, or {@code null} if {@code storage} was null.
      *
-     * @see org.apache.sis.util.collection.Collections#derivedMap(Map, ObjectConverter, ObjectConverter)
+     * @see Containers#derivedMap(Map, ObjectConverter, ObjectConverter)
      */
     public static <K,SV,V> Map<K,V> derivedValues(final Map<K,SV> storage,
                                                   final Class<K> keyType,
                                                   final ObjectConverter<SV,V> valueConverter)
     {
         ArgumentChecks.ensureNonNull("keyType", keyType);
-        return org.apache.sis.util.collection.Collections.derivedMap(storage,
-                IdentityConverter.create(keyType), valueConverter);
+        return Containers.derivedMap(storage, identity(keyType), valueConverter);
     }
 }

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Static.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Static.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Static.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Static.java [UTF-8] Thu May  9 12:24:13 2013
@@ -22,7 +22,7 @@ package org.apache.sis.util;
  * purpose only. The list below summarizes some of the utility classes:
  *
  * <table class="sis">
- * <tr><th colspan="2">Basic classes of the Java language</th></tr>
+ * <tr><th colspan="2">Classes of the Java language</th></tr>
  * <tr><td>{@link Characters}</td>
  *     <td>Find subscript and superscript digit characters.</td></tr>
  * <tr><td>{@link CharSequences}</td>
@@ -30,9 +30,15 @@ package org.apache.sis.util;
  * <tr><td>{@link StringBuilders}</td>
  *     <td>Methods modifying {@link StringBuilder} content in-place.</td></tr>
  * <tr><td>{@link Numbers}</td>
- *     <td>Conversions between different kind of {@link Number}.</td></tr>
+ *     <td>Methods working with {@link Number} instances (include conversions between different types).</td></tr>
  * <tr><td>{@link Classes}</td>
- *     <td>Methods working on {@link Class} instances.</td></tr>
+ *     <td>Methods working with {@link Class} instances.</td></tr>
+ * <tr><td>{@link org.apache.sis.util.collection.Containers}</td>
+ *     <td>Additions to the JDK {@link java.util.Collections} methods, also related to the
+ *         {@link org.apache.sis.util.collection.CheckedContainer} interface.</td></tr>
+ * <tr><td>{@link ArraysExt}</td>
+ *     <td>Additions to the JDK {@link java.util.Arrays} methods
+ *         (include insert or remove of elements in the middle of arrays).</td></tr>
  *
  * <tr><th colspan="2" class="hsep">Mathematics and units of measurement</th></tr>
  * <tr><td>{@link org.apache.sis.math.MathFunctions}</td>
@@ -41,11 +47,11 @@ package org.apache.sis.util;
  *     <td>Get a {@linkplain javax.measure.unit.Unit unit} from a symbol or EPSG code,
  *         and test if a unit is angular, linear or temporal.</td></tr>
  *
- * <tr><th colspan="2" class="hsep">Structures (trees, collections, arrays, parameters)</th></tr>
- * <tr><td>{@link org.apache.sis.util.collection.Collections}</td>
- *     <td>Additions to the JDK {@link java.util.Collections} methods.</td></tr>
- * <tr><td>{@link Arrays}</td>
- *     <td>Insert or remove elements in the middle of arrays.</td></tr>
+ * <tr><th colspan="2" class="hsep">OGC/ISO objects (metadata, referencing, geometries)</th></tr>
+ * <tr><td>{@link org.apache.sis.metadata.iso.extent.Extents}</td>
+ *     <td>Extract information from {@link org.opengis.metadata.extent.Extent} objects.</td></tr>
+ * <tr><td>{@link org.apache.sis.geometry.Envelopes}</td>
+ *     <td>Parse, format and transform {@linkplain org.opengis.geometry.Envelope envelopes}.</td></tr>
  *
  * <tr><th colspan="2" class="hsep">Input / Output (including CRS, XML, images)</th></tr>
  * <tr><td>{@link org.apache.sis.io.IO}</td>
@@ -74,9 +80,8 @@ package org.apache.sis.util;
  */
 public class Static {
     /**
-     * Do not allow instantiation. This construction is defined only in order to allow
-     * subclassing. Subclasses shall declare their own private constructor in order to
-     * prevent instantiation.
+     * For subclasses only.
+     * Subclasses shall declare a private constructor for preventing instantiation.
      */
     protected Static() {
     }

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Static.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnconvertibleObjectException.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnconvertibleObjectException.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnconvertibleObjectException.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnconvertibleObjectException.java [UTF-8] Thu May  9 12:24:13 2013
@@ -35,7 +35,7 @@ public class UnconvertibleObjectExceptio
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 3434744387048059588L;
+    private static final long serialVersionUID = 4436966248421454692L;
 
     /**
      * Constructs a new exception with no message.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnconvertibleObjectException.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnsupportedImplementationException.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnsupportedImplementationException.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnsupportedImplementationException.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnsupportedImplementationException.java [UTF-8] Thu May  9 12:24:13 2013
@@ -34,7 +34,7 @@ public class UnsupportedImplementationEx
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = -649050339146622730L;
+    private static final long serialVersionUID = 8871937175259200449L;
 
     /**
      * Constructs an exception with the specified detail message.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/UnsupportedImplementationException.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Utilities.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Utilities.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Utilities.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Utilities.java [UTF-8] Thu May  9 12:24:13 2013
@@ -24,7 +24,7 @@ import java.util.Map;
 import java.util.Set;
 
 // Related to JDK7
-import org.apache.sis.internal.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 
 
 /**
@@ -299,16 +299,15 @@ public final class Utilities extends Sta
      * <ul>
      *   <li>If the supplied object is {@code null}, then this method returns 0.</li>
      *   <li>Otherwise if the object is an array of objects, then
-     *       {@link java.util.Arrays#deepHashCode(Object[])} is invoked.</li>
+     *       {@link Arrays#deepHashCode(Object[])} is invoked.</li>
      *   <li>Otherwise if the object is an array of primitive type, then the corresponding
-     *       {@link java.util.Arrays#hashCode(double[]) Arrays.hashCode(...)} method is invoked.</li>
+     *       {@link Arrays#hashCode(double[]) Arrays.hashCode(...)} method is invoked.</li>
      *   <li>Otherwise {@link Object#hashCode()} is invoked.</li>
      * </ul>
      *
      * This method should be invoked <strong>only</strong> if the object type is declared
      * exactly as {@code Object}, not as some subtype like {@code Object[]}, {@code String} or
-     * {@code float[]}. In the later cases, use the appropriate {@link java.util.Arrays} method
-     * instead.
+     * {@code float[]}. In the later cases, use the appropriate {@link Arrays} method instead.
      *
      * @param object The object to compute hash code. May be {@code null}.
      * @return The hash code of the given object.
@@ -335,16 +334,15 @@ public final class Utilities extends Sta
      *
      * <ul>
      *   <li>If the object is an array of objects, then
-     *       {@link java.util.Arrays#deepToString(Object[])} is invoked.</li>
+     *       {@link Arrays#deepToString(Object[])} is invoked.</li>
      *   <li>Otherwise if the object is an array of primitive type, then the corresponding
-     *       {@link java.util.Arrays#toString(double[]) Arrays.toString(...)} method is invoked.</li>
+     *       {@link Arrays#toString(double[]) Arrays.toString(...)} method is invoked.</li>
      *   <li>Otherwise {@link String#valueOf(Object)} is invoked.</li>
      * </ul>
      *
      * This method should be invoked <strong>only</strong> if the object type is declared
      * exactly as {@code Object}, not as some subtype like {@code Object[]}, {@code Number} or
-     * {@code float[]}. In the later cases, use the appropriate {@link java.util.Arrays} method
-     * instead.
+     * {@code float[]}. In the later cases, use the appropriate {@link Arrays} method instead.
      *
      * @param object The object to format as a string. May be {@code null}.
      * @return A string representation of the given object.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Utilities.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Version.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Version.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Version.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Version.java [UTF-8] Thu May  9 12:24:13 2013
@@ -42,7 +42,7 @@ public class Version implements CharSequ
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = -6793384507333713770L;
+    private static final long serialVersionUID = 8402041502662929792L;
 
     /**
      * The version of this Apache SIS distribution.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Version.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/Workaround.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java [UTF-8] Thu May  9 12:24:13 2013
@@ -41,6 +41,13 @@ import java.sql.SQLException;
  *     }
  * }
  *
+ * {@section Relationship with <code>java.io.UncheckedIOException</code>}
+ * JDK8 provides a {@link java.io.UncheckedIOException} which partially overlaps
+ * the purpose of this {@code BackingStoreException}. While Apache SIS still uses
+ * {@code BackingStoreException} as a general mechanism for any kind of checked
+ * exceptions, client code targeting JDK8 would be well advised to catch both kind
+ * of exceptions for robustness.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.3)
  * @version 0.3
@@ -50,7 +57,7 @@ public class BackingStoreException exten
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = -1714319767053628606L;
+    private static final long serialVersionUID = -4549821631559359838L;
 
     /**
      * Constructs a new exception with no detail message.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/BackingStoreException.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java [UTF-8] Thu May  9 12:24:13 2013
@@ -178,6 +178,15 @@ public class Cache<K,V> extends Abstract
     private final boolean soft;
 
     /**
+     * {@code true} if different values may be assigned to the same key. This is usually
+     * an error, so the default {@code Cache} behavior is to thrown an exception in such
+     * case.
+     *
+     * @see #isKeyCollisionAllowed()
+     */
+    private volatile boolean isKeyCollisionAllowed;
+
+    /**
      * A view over the entries in the cache.
      */
     private transient Set<Entry<K,V>> entries;
@@ -207,7 +216,7 @@ public class Cache<K,V> extends Abstract
     public Cache(int initialCapacity, final long costLimit, final boolean soft) {
         ArgumentChecks.ensureStrictlyPositive("initialCapacity", initialCapacity);
         ArgumentChecks.ensurePositive("costLimit", costLimit);
-        initialCapacity = Collections.hashMapCapacity(initialCapacity);
+        initialCapacity = Containers.hashMapCapacity(initialCapacity);
         this.map        = new ConcurrentHashMap<K,Object>(initialCapacity);
         this.costs      = new LinkedHashMap<K,Integer>((int) Math.min(initialCapacity, costLimit), 0.75f, true);
         this.costLimit  = costLimit;
@@ -423,7 +432,7 @@ public class Cache<K,V> extends Abstract
     /**
      * Gets a lock for the entry at the given key and returns a handler to be used by the caller
      * for unlocking and storing the result. This method <strong>must</strong> be used together
-     * with a {@link Handler#putAndUnlock(Object) putAndUnlock} call in {@code try} … {@code catch}
+     * with a {@link Handler#putAndUnlock(Object) putAndUnlock} call in {@code try} … {@code catch}
      * blocks as in the example below:
      *
      * {@preformat java
@@ -511,6 +520,18 @@ public class Cache<K,V> extends Abstract
             @SuppressWarnings("unchecked")
             final Work work = (Work) value;
             if (work.lock.isHeldByCurrentThread()) {
+                if (isKeyCollisionAllowed()) {
+                    /*
+                     * Example of key collision: the EPSG database defines the CoordinateOperation
+                     * 8653 ("ED50 to WGS84" using polynomial equations).  The EPSG factory sets a
+                     * lock for this code, then searches for OperationParameters associated to this
+                     * operation. One of those parameters ("Bu0v4") has the same key (EPSG:8653).
+                     * So we get a key collision. If we ignore the second occurrence, its value will
+                     * not be cached. This is okay since the value that we really want to cache is
+                     * CoordinateOperation, which is associated to the first occurrence of that key.
+                     */
+                    return new Simple<V>(null);
+                }
                 throw new IllegalStateException(Errors.format(Errors.Keys.RecursiveCreateCallForKey_1, key));
             }
             return work.new Wait();
@@ -527,7 +548,7 @@ public class Cache<K,V> extends Abstract
 
     /**
      * The handler returned by {@link Cache#lock}, to be used for unlocking and storing the
-     * result. This handler should be used as below (note the {@code try} … {@code catch}
+     * result. This handler should be used as below (note the {@code try} … {@code catch}
      * blocks, which are <strong>mandatory</strong>):
      *
      * {@preformat java
@@ -612,7 +633,7 @@ public class Cache<K,V> extends Abstract
          */
         @Override
         public void putAndUnlock(final V result) throws IllegalStateException {
-            if (result != value) {
+            if (result != value && !isKeyCollisionAllowed()) {
                 throw new IllegalStateException(Errors.format(Errors.Keys.KeyCollision_1, "<unknown>"));
             }
         }
@@ -723,7 +744,7 @@ public class Cache<K,V> extends Abstract
              */
             @Override
             public void putAndUnlock(final V result) throws IllegalStateException {
-                if (result != get()) {
+                if (result != get() && !isKeyCollisionAllowed()) {
                     throw new IllegalStateException(Errors.format(Errors.Keys.KeyCollision_1, key));
                 }
             }
@@ -853,6 +874,40 @@ public class Cache<K,V> extends Abstract
     }
 
     /**
+     * Returns {@code true} if different values may be assigned to the same key.
+     * The default value is {@code false}.
+     *
+     * @return {@code true} if key collisions are allowed.
+     */
+    public boolean isKeyCollisionAllowed() {
+        return isKeyCollisionAllowed;
+    }
+
+    /**
+     * If set to {@code true}, different values may be assigned to the same key. This is usually an
+     * error, so the default {@code Cache} behavior is to thrown an {@link IllegalStateException}
+     * in such cases, typically when {@link Handler#putAndUnlock(Object)} is invoked. However in
+     * some cases we may want to relax this check. For example the EPSG database sometime assigns
+     * the same key to different kind of objects.
+     *
+     * <p>If key collisions are allowed and two threads invoke {@link #lock(Object)} concurrently
+     * for the same key, then the value to be stored in the map will be the one computed by the
+     * first thread who got the lock. The value computed by any other concurrent thread will be
+     * ignored by this {@code Cache} class. However those threads still return their computed
+     * values to their callers.</p>
+     *
+     * <p>This property can also be set in order to allow some recursivity. If during the creation
+     * of an object, the program asks to this {@code Cache} for the same object (using the same key),
+     * then the default {@code Cache} implementation will consider this situation as a key collision
+     * unless this property has been set to {@code true}.</p>
+     *
+     * @param allowed {@code true} if key collisions should be allowed.
+     */
+    public void setKeyCollisionAllowed(final boolean allowed) {
+        isKeyCollisionAllowed = allowed;
+    }
+
+    /**
      * Computes an estimation of the cost of the given value. The default implementation returns 1
      * in all cases. Subclasses should override this method if they have some easy way to measure
      * the relative cost of value objects.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/Cache.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/CacheEntries.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/CheckedContainer.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] Thu May  9 12:24:13 2013
@@ -16,22 +16,25 @@
  */
 package org.apache.sis.util.collection;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.LinkedHashMap;
+import java.util.Collection;
 import java.util.Collections;
 import java.io.Serializable;
 import net.jcip.annotations.NotThreadSafe;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.Cloner;
+import org.apache.sis.internal.util.UnmodifiableArrayList;
 
 import static org.apache.sis.util.CharSequences.trimWhitespaces;
-import static org.apache.sis.util.collection.Collections.isNullOrEmpty;
-import static org.apache.sis.util.collection.Collections.hashMapCapacity;
+import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
+import static org.apache.sis.util.collection.Containers.hashMapCapacity;
 
 // Related to JDK7
-import org.apache.sis.internal.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 
 
 /**
@@ -58,7 +61,7 @@ import org.apache.sis.internal.util.Obje
  *     }
  * }
  *
- * The {@code setRoot(…)} method accepts arbitrary {@link TreeTable.Node} implementations.
+ * The {@code setRoot(…)} method accepts arbitrary {@link TreeTable.Node} implementations.
  * However it is likely to be safer and more memory efficient when used together with the
  * implementation provided in the {@link Node} inner class.
  *
@@ -66,13 +69,16 @@ import org.apache.sis.internal.util.Obje
  * @since   0.3
  * @version 0.3
  * @module
+ *
+ * @see Node
+ * @see TableColumn
  */
 @NotThreadSafe
 public class DefaultTreeTable implements TreeTable, Cloneable, Serializable {
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 1951201018202846555L;
+    private static final long serialVersionUID = 7991792044044382191L;
 
     /**
      * The root node, or {@code null} if not yet specified.
@@ -93,7 +99,7 @@ public class DefaultTreeTable implements
     /**
      * The index of values associated to each column. This is used by the {@link Node}
      * implementation for storing values in a single flat array. After creation, this
-     * map shall be read-only since many {@code Node} instances may share it.
+     * map shall be read-only since many {@code Node} instances may share it.
      *
      * {@note This field and the {@link #columns} field could be computed from each other.
      *        But we serialize this field anyway because children nodes will typically hold
@@ -121,7 +127,9 @@ public class DefaultTreeTable implements
         if (columns.length == 0) {
             throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "columns"));
         }
-        columns = columns.clone();
+        // Copy the array for safety against user changes, and also for forcing the element type
+        // to TableColumn, not a subclass, because of the UnmodifiableArrayList.wrap(E[]) contract.
+        columns = Arrays.copyOf(columns, columns.length, TableColumn[].class);
         this.columnIndices = createColumnIndices(columns);
         this.columns = UnmodifiableArrayList.wrap(columns);
     }
@@ -168,6 +176,10 @@ public class DefaultTreeTable implements
     /**
      * Returns all columns in the given map, sorted by increasing index value.
      * This method relies on {@link LinkedHashSet} preserving insertion order.
+     *
+     * @return The columns in an array of elements of type {@code TableColumn},
+     *         <strong>not a subtype</strong> for allowing usage in
+     *         {@link UnmodifiableArrayList#wrap(E[])}.
      */
     static TableColumn<?>[] getColumns(final Map<TableColumn<?>,Integer> columnIndices) {
         return columnIndices.keySet().toArray(new TableColumn<?>[columnIndices.size()]);
@@ -275,7 +287,7 @@ public class DefaultTreeTable implements
 
     /**
      * Returns a string representation of this tree table.
-     * The default implementation performs the same work than {@link TreeTables#toString(TreeTable)}.
+     * The current implementation uses a shared instance of {@link TreeTableFormat}.
      * This is okay for debugging or occasional usages. However for more extensive usages,
      * developers are encouraged to create and configure their own {@link TreeTableFormat}
      * instance.
@@ -308,13 +320,16 @@ public class DefaultTreeTable implements
      * @since   0.3
      * @version 0.3
      * @module
+     *
+     * @see DefaultTreeTable
+     * @see TableColumn
      */
     @NotThreadSafe
     public static class Node implements TreeTable.Node, Cloneable, Serializable {
         /**
          * For cross-version compatibility.
          */
-        private static final long serialVersionUID = 2931274954865719140L;
+        private static final long serialVersionUID = -5729029633479218691L;
 
         /**
          * Implementation of {@link Node} children list. This list updates automatically the
@@ -378,7 +393,7 @@ public class DefaultTreeTable implements
          * {@link #getValue(TableColumn)} and {@link #setValue(TableColumn, Object)}
          * methods for identifying the index where to store values in the {@link #values} array.
          *
-         * <p>This map shall be read-only since many {@code Node} instances may share it.</p>
+         * <p>This map shall be read-only since many {@code Node} instances may share it.</p>
          *
          * @see DefaultTreeTable#columnIndices
          */
@@ -443,7 +458,7 @@ public class DefaultTreeTable implements
         }
 
         /**
-         * Creates a node with a single column for object names (c<cite>convenience constructor</cite>).
+         * Creates a node with a single column for object names (<cite>convenience constructor</cite>).
          * The node will have the following columns:
          *
          * <table class="sis">
@@ -488,9 +503,27 @@ public class DefaultTreeTable implements
         }
 
         /**
-         * Returns the node children. This list is modifiable and updates automatically the
-         * {@linkplain #getParent() parent} reference of any {@code Node} instance added to
-         * ore removed from this list.
+         * Returns {@code true} if this node can not have any children. The default implementation
+         * unconditionally returns {@code false} even if the list of children is empty, because the
+         * list is allowed to grow at any time.
+         *
+         * <p>Subclasses can override this method if they can determine which nodes are leaves.
+         * In the current implementation, the return value shall be stable (i.e. a node can not
+         * alternate between leaf and non-leaf state). However this restriction may be relaxed
+         * in a future SIS version.</p>
+         */
+        @Override
+        public boolean isLeaf() {
+            return false;
+        }
+
+        /**
+         * Returns the children of this node. For non-leaf nodes, the list is modifiable and will
+         * automatically updates the {@linkplain #getParent() parent} reference of any {@code Node}
+         * instance added to or removed from the list.
+         *
+         * <p>For leaf nodes, this method returns an unmodifiable
+         * {@linkplain Collections#emptyList() empty list}.</p>
          */
         /* NOTE: If a future version removes the "final" keyword, then search for calls to
          * this method where the return value is casted to TreeNodeList. Any unconditional
@@ -499,15 +532,20 @@ public class DefaultTreeTable implements
         @Override
         public final List<TreeTable.Node> getChildren() {
             if (children == null) {
-                children = new Children(this);
+                if (isLeaf()) {
+                    children = Collections.emptyList();
+                } else {
+                    children = new Children(this);
+                }
             }
             return children;
         }
 
         /**
          * Adds a new child in the {@linkplain #getChildren() children list}.
-         * The default implementation delegates to {@link #Node(Node)}, which
-         * has the following implications:
+         * The default implementation first checks that this node is not a leaf,
+         * then delegates to the {@code Node(Node)} constructor.
+         * That constructor call has the following implications:
          *
          * <ul>
          *   <li>The new node inherits the columns of this node, on the assumption that
@@ -516,14 +554,19 @@ public class DefaultTreeTable implements
          * </ul>
          *
          * Subclasses may override this method with different behavior.
+         *
+         * @throws UnsupportedOperationException If this node {@linkplain #isLeaf() is a leaf}.
          */
         @Override
         public Node newChild() {
+            if (isLeaf()) {
+                throw new UnsupportedOperationException(Errors.format(Errors.Keys.NodeIsLeaf_1, this));
+            }
             return new Node(this);
         }
 
         /**
-         * Returns the value in the given column, or {@code null} if none.
+         * Returns the value in the given column, or {@code null} if none.
          *
          * @param  <V>    The base type of values in the given column.
          * @param  column Identifier of the column from which to get the value.
@@ -554,7 +597,7 @@ public class DefaultTreeTable implements
          * @see #isEditable(TableColumn)
          */
         @Override
-        public <V> void setValue(final TableColumn<V> column, final V value) {
+        public <V> void setValue(final TableColumn<V> column, final V value) throws IllegalArgumentException {
             ArgumentChecks.ensureNonNull("column", column);
             final Integer index = columnIndices.get(column);
             if (index == null) {
@@ -720,7 +763,10 @@ public class DefaultTreeTable implements
             }
             String name = getClass().getSimpleName();
             if (parent != null) {
-                name = name + '-' + parent.getChildren().indexOf(this);
+                final Collection<TreeTable.Node> children = parent.getChildren();
+                if (children instanceof List<?>) {
+                    name = name + '-' + ((List<TreeTable.Node>) children).indexOf(this);
+                }
             }
             return name;
         }

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedIterator.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedMap.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedMap.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedMap.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedMap.java [UTF-8] Thu May  9 12:24:13 2013
@@ -73,7 +73,7 @@ class DerivedMap<SK,SV,K,V> extends Abst
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -6994867383669885934L;
+    private static final long serialVersionUID = -4760466188643114727L;
 
     /**
      * The storage map whose keys are derived from.
@@ -200,7 +200,7 @@ class DerivedMap<SK,SV,K,V> extends Abst
      * to the {@linkplain #storage} map instead than iterating over all entries.
      */
     private static class InvertibleKey<SK,SV,K,V> extends DerivedMap<SK,SV,K,V> {
-        private static final long serialVersionUID = -7770446176017835821L;
+        private static final long serialVersionUID = 3499911507293121425L;
 
         /** The inverse of {@link #keyConverter}. */
         protected final ObjectConverter<K,SK> keyInverse;
@@ -238,7 +238,7 @@ class DerivedMap<SK,SV,K,V> extends Abst
      * to the {@linkplain #storage} map instead than iterating over all entries.
      */
     private static final class InvertibleValue<SK,SV,K,V> extends DerivedMap<SK,SV,K,V> {
-        private static final long serialVersionUID = 6249800498911409046L;
+        private static final long serialVersionUID = -8290698486357636366L;
 
         /** The inverse of {@link #valueConverter}. */
         private final ObjectConverter<V,SV> valueInverse;
@@ -264,7 +264,7 @@ class DerivedMap<SK,SV,K,V> extends Abst
      * to the {@linkplain #storage} map instead than iterating over all entries.
      */
     private static final class Invertible<SK,SV,K,V> extends InvertibleKey<SK,SV,K,V> {
-        private static final long serialVersionUID = 3830322680676020356L;
+        private static final long serialVersionUID = -6625938922337246124L;
 
         /** The inverse of {@link #valueConverter}. */
         private final ObjectConverter<V,SV> valueInverse;

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedMap.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java [UTF-8] Thu May  9 12:24:13 2013
@@ -67,7 +67,7 @@ class DerivedSet<S,E> extends AbstractSe
     /**
      * Serial number for inter-operability with different versions.
      */
-    private static final long serialVersionUID = -4662336508586424581L;
+    private static final long serialVersionUID = 6309535868745970619L;
 
     /**
      * The storage set whose values are derived from.
@@ -198,7 +198,7 @@ class DerivedSet<S,E> extends AbstractSe
         /**
          * For cross-version compatibility.
          */
-        private static final long serialVersionUID = 5957167307119709856L;
+        private static final long serialVersionUID = -5336633027232952482L;
 
         /**
          * The converter from the derived to the storage type.

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/DerivedSet.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java [UTF-8] Thu May  9 12:24:13 2013
@@ -108,6 +108,22 @@ public class TableColumn<V> implements C
             CharSequence.class, Vocabulary.Keys.Name);
 
     /**
+     * Frequently-used constant for a column of object identifiers.
+     * The column {@linkplain #getHeader() header} is "<cite>Identifier</cite>" (eventually localized)
+     * and the column elements are instances of {@link String}.
+     */
+    public static final TableColumn<String> IDENTIFIER = new Constant<String>("IDENTIFIER",
+            String.class, Vocabulary.Keys.Identifier);
+
+    /**
+     * Frequently-used constant for a column of index values.
+     * The column {@linkplain #getHeader() header} is "<cite>Index</cite>" (eventually localized)
+     * and the column elements are instances of {@link Integer}.
+     */
+    public static final TableColumn<Integer> INDEX = new Constant<Integer>("INDEX",
+            Integer.class, Vocabulary.Keys.Index);
+
+    /**
      * Frequently-used constant for a column of object types.
      * The column {@linkplain #getHeader() header} is "<cite>Type</cite>" (eventually localized).
      */
@@ -116,12 +132,22 @@ public class TableColumn<V> implements C
             (Class) Class.class, Vocabulary.Keys.Type);
 
     /**
+     * Frequently-used constant for a column of object values.
+     * The column {@linkplain #getHeader() header} is "<cite>Value</cite>" (eventually localized) and
+     * the column elements can be instance of any kind of objects.
+     *
+     * @see #VALUE_AS_TEXT
+     * @see #VALUE_AS_NUMBER
+     */
+    public static final TableColumn<Object> VALUE = new Constant<Object>("VALUE",
+            Object.class, Vocabulary.Keys.Value);
+
+    /**
      * Frequently-used constant for a column of object textual values.
      * The column {@linkplain #getHeader() header} is "<cite>Value</cite>" (eventually localized) and
      * the column elements are typically instances of {@link String} or {@link InternationalString},
      * depending on whether the data provide localization support or not.
      */
-    @SuppressWarnings("unchecked")
     public static final TableColumn<CharSequence> VALUE_AS_TEXT = new Constant<CharSequence>("VALUE_AS_TEXT",
             CharSequence.class, Vocabulary.Keys.Value);
 
@@ -129,13 +155,12 @@ public class TableColumn<V> implements C
      * Frequently-used constant for a column of object numerical values.
      * The column {@linkplain #getHeader() header} is "<cite>Value</cite>" (eventually localized).
      */
-    @SuppressWarnings("unchecked")
     public static final TableColumn<Number> VALUE_AS_NUMBER = new Constant<Number>("VALUE_AS_NUMBER",
             Number.class, Vocabulary.Keys.Value);
 
     /**
      * A map containing only the {@link #NAME} column.
-     * This is the default set of columns when parsing a table tree.
+     * This is the default set of columns when parsing a tree table.
      */
     static final Map<TableColumn<?>,Integer> NAME_MAP =
             Collections.<TableColumn<?>,Integer>singletonMap(NAME, 0);
@@ -166,7 +191,7 @@ public class TableColumn<V> implements C
         /**
          * For cross-version compatibility.
          */
-        private static final long serialVersionUID = -2486202389234601560L;
+        private static final long serialVersionUID = -3460868641711391888L;
 
         /**
          * The programmatic name of the static final field holding this constant.
@@ -212,7 +237,7 @@ public class TableColumn<V> implements C
         private Object readResolve() throws InvalidObjectException {
             try {
                 return TableColumn.class.getField(field).get(null);
-            } catch (Exception cause) { // Many exceptions, including unchecked ones.
+            } catch (Exception cause) { // (ReflectiveOperationException) on JDK7 branch.
                 InvalidObjectException e = new InvalidObjectException(cause.toString());
                 e.initCause(cause);
                 throw e;
@@ -249,7 +274,6 @@ public class TableColumn<V> implements C
     public TableColumn(final Class<V> type, final CharSequence header) {
         ArgumentChecks.ensureNonNull("type",   this.type   = type);
         ArgumentChecks.ensureNonNull("header", this.header = header);
-        this.header = Types.toInternationalString(header);
     }
 
     /**

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8

Modified: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java
URL: http://svn.apache.org/viewvc/sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java?rev=1480602&r1=1480601&r2=1480602&view=diff
==============================================================================
--- sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java [iso-8859-1] (original)
+++ sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java [UTF-8] Thu May  9 12:24:13 2013
@@ -69,7 +69,7 @@ abstract class TreeNodeList extends Abst
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 9210230622796007350L;
+    private static final long serialVersionUID = -8723469207489667631L;
 
     /**
      * Enumeration constant for {@link #setParentOf(TreeTable.Node, int)}.
@@ -119,7 +119,7 @@ abstract class TreeNodeList extends Abst
 
     /**
      * Sets or clears the parent of the given node. This method doesn't need to care about the
-     * current node parent, since {@code TreeNodeList} will take care of removing the tree node
+     * current node parent, since {@code TreeNodeList} will take care of removing the tree node
      * from its previous parent before to invoke this method.
      *
      * <p>The {@code mode} argument specifies the parent value to set, as one of the following

Propchange: sis/branches/Android/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java
------------------------------------------------------------------------------
--- svn:mime-type (original)
+++ svn:mime-type Thu May  9 12:24:13 2013
@@ -1 +1 @@
-text/plain
+text/plain;charset=UTF-8



Mime
View raw message