sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1478216 [2/2] - in /sis/branches/JDK6: ./ sis-metadata/src/main/java/org/apache/sis/metadata/ sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/ sis-metadata/src/main/java/org/apache/sis/metadata/iso/doc-files/ sis-metadata/s...
Date Wed, 01 May 2013 22:11:03 GMT
Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java [UTF-8] Wed May  1 22:11:02 2013
@@ -17,12 +17,8 @@
 package org.apache.sis.internal.util;
 
 import java.util.Set;
-import java.util.Iterator;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
-import java.util.NoSuchElementException;
-import org.apache.sis.util.Decorator;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.collection.CheckedContainer;
 
@@ -34,12 +30,11 @@ import static org.apache.sis.util.Argume
  * The type checks are performed at run-time in addition to the compile-time checks.
  *
  * <p>Using this class is similar to wrapping a {@link LinkedHashSet} using the methods provided
- * in the standard {@link Collections} class, except for the following advantages:</p>
+ * in the standard {@link Collections} class, except for the following differences:</p>
  *
  * <ul>
  *   <li>Avoid one level of indirection.</li>
- *   <li>Checks for write permission.</li>
- *   <li>Overrideable methods for controlling the type checks and write permission checks.</li>
+ *   <li>Does not accept null elements.</li>
  * </ul>
  *
  * @param <E> The type of elements in the set.
@@ -51,7 +46,7 @@ import static org.apache.sis.util.Argume
  *
  * @see Collections#checkedSet(Set, Class)
  */
-public class CheckedHashSet<E> extends LinkedHashSet<E> implements CheckedContainer<E>, Cloneable {
+public final class CheckedHashSet<E> extends LinkedHashSet<E> implements CheckedContainer<E> {
     /**
      * Serial version UID for compatibility with different versions.
      */
@@ -94,167 +89,23 @@ public class CheckedHashSet<E> extends L
     }
 
     /**
-     * Ensures that the given element can be added to this set.
-     * The default implementation ensures that the object is {@code null} or assignable
-     * to the type specified at construction time. Subclasses can override this method
-     * if they need to perform additional checks.
-     *
-     * @param  element the object to check, or {@code null}.
-     * @throws IllegalArgumentException if the specified element can not be added to this set.
-     */
-    protected void ensureValid(final E element) throws IllegalArgumentException {
-        if (element != null && !type.isInstance(element)) {
-            throw new IllegalArgumentException(Errors.format(
-                    Errors.Keys.IllegalArgumentClass_3, "element", type, element.getClass()));
-        }
-    }
-
-    /**
-     * Ensures that all elements of the given collection can be added to this set.
-     *
-     * @param  collection the collection to check, or {@code null}.
-     * @throws IllegalArgumentException if at least one element can not be added to this set.
-     */
-    private void ensureValidCollection(final Collection<? extends E> collection) throws IllegalArgumentException {
-        for (final E element : collection) {
-            ensureValid(element);
-        }
-    }
-
-    /**
-     * Checks if changes in this set are allowed. This method is automatically invoked before any
-     * operation that may change the content. If the write operation is allowed, then this method
-     * shall returns normally. Otherwise an {@link UnsupportedOperationException} is thrown.
-     *
-     * <p>The default implementation does nothing, thus allowing this set to be modified.
-     * Subclasses can override this method if they want to control write permissions.</p>
-     *
-     * @throws UnsupportedOperationException if this set is unmodifiable.
-     */
-    protected void checkWritePermission() throws UnsupportedOperationException {
-    }
-
-    /**
-     * An iterator with a check for write permission prior element removal.
-     * This class wraps the iterator provided by {@link LinkedHashSet#iterator()}.
-     *
-     * @see CheckedHashSet#iterator()
-     */
-    @Decorator(Iterator.class)
-    private final class Iter implements Iterator<E> {
-        /** The {@link LinkedHashSet} iterator. */
-        private final Iterator<E> iterator;
-
-        /** Creates a new wrapper for the given {@link LinkedHashSet} iterator. */
-        Iter(final Iterator<E> iterator) {
-            this.iterator = iterator;
-        }
-
-        /** Returns {@code true} if there is more elements in the iteration. */
-        @Override
-        public boolean hasNext() {
-            return iterator.hasNext();
-        }
-
-        /** Returns the next element in the iteration. */
-        @Override
-        public E next() throws NoSuchElementException {
-            return iterator.next();
-        }
-
-        /** Removes the previous element if the enclosing {@link CheckedHashSet} allows write operations. */
-        @Override
-        public void remove() throws UnsupportedOperationException {
-            checkWritePermission();
-            iterator.remove();
-        }
-    }
-
-    /**
-     * Returns an iterator over the elements in this set.
-     * The returned iterator will support {@linkplain Iterator#remove() element removal}
-     * only if the {@link #checkWritePermission()} method does not throw exception.
-     */
-    @Override
-    public Iterator<E> iterator() {
-        return new Iter(super.iterator());
-    }
-
-    /**
      * Adds the specified element to this set if it is not already present.
      *
      * @param  element element to be added to this set.
      * @return {@code true} if the set did not already contain the specified element.
      * @throws IllegalArgumentException if the specified element is not of the expected type.
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
      */
     @Override
-    public boolean add(final E element)
-            throws IllegalArgumentException, UnsupportedOperationException
-    {
-        ensureValid(element);
-        checkWritePermission();
+    public boolean add(final E element) throws IllegalArgumentException {
+        if (!type.isInstance(element)) {
+            ensureNonNull("element", element);
+            throw new IllegalArgumentException(Errors.format(
+                    Errors.Keys.IllegalArgumentClass_3, "element", type, element.getClass()));
+        }
         return super.add(element);
     }
 
-    /**
-     * Appends all of the elements in the specified collection to this set.
-     *
-     * @param  collection the elements to be inserted into this set.
-     * @return {@code true} if this set changed as a result of the call.
-     * @throws IllegalArgumentException if at least one element is not of the expected type.
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
-     */
-    @Override
-    public boolean addAll(final Collection<? extends E> collection)
-            throws IllegalArgumentException, UnsupportedOperationException
-    {
-        ensureValidCollection(collection);
-        checkWritePermission();
-        return super.addAll(collection);
-    }
-
-    /**
-     * Removes the specified element from this set.
-     *
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
-     */
-    @Override
-    public boolean remove(Object o) throws UnsupportedOperationException {
-        checkWritePermission();
-        return super.remove(o);
-    }
-
-    /**
-     * Removes all of this set's elements that are also contained in the specified collection.
-     *
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
-     */
-    @Override
-    public boolean removeAll(Collection<?> c) throws UnsupportedOperationException {
-        checkWritePermission();
-        return super.removeAll(c);
-    }
-
-    /**
-     * Retains only the elements in this set that are contained in the specified collection.
-     *
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
+    /*
+     * No need to override 'addAll', since it is implemented on top of 'add'.
      */
-    @Override
-    public boolean retainAll(Collection<?> c) throws UnsupportedOperationException {
-        checkWritePermission();
-        return super.retainAll(c);
-    }
-
-    /**
-     * Removes all of the elements from this set.
-     *
-     * @throws UnsupportedOperationException if this collection is unmodifiable.
-     */
-    @Override
-    public void clear() throws UnsupportedOperationException {
-        checkWritePermission();
-        super.clear();
-    }
 }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java [UTF-8] Wed May  1 22:11:02 2013
@@ -79,13 +79,17 @@ public class UnmodifiableArrayList<E> ex
      * <p>This constructor is for sub-classing only. Users should invoke the {@link #wrap(Object[])}
      * static method instead.</p>
      *
+     * <p>The argument type is intentionally {@code E[]} instead than {@code E...} in order to force
+     * the caller to instantiate the array explicitely, in order to make sure that the array type is
+     * the intended one.</p>
+     *
      * {@section WARNING! Type safety hole}
      * Callers <strong>must</strong> ensure that the type of array elements in exactly {@code E},
      * not a subtype of {@code E}. See class javadoc for more information.
      *
      * @param array The array to wrap.
      */
-    protected UnmodifiableArrayList(final E... array) {
+    protected UnmodifiableArrayList(final E[] array) { // NOT "E..." - see javadoc.
         this.array = Objects.requireNonNull(array);
     }
 
@@ -100,12 +104,16 @@ public class UnmodifiableArrayList<E> ex
      * should use {@link org.apache.sis.util.collection.Containers#unmodifiableList(E[])} instead.
      * See class javadoc for more information.
      *
+     * <p>The argument type is intentionally {@code E[]} instead than {@code E...} in order to force
+     * the caller to instantiate the array explicitely, in order to make sure that the array type is
+     * the intended one.</p>
+     *
      * @param  <E> The type of elements in the list.
      * @param  array The array to wrap, or {@code null} if none.
      * @return The given array wrapped in an unmodifiable list, or {@code null} if the given
      *         array was null.
      */
-    public static <E> UnmodifiableArrayList<E> wrap(final E... array) {
+    public static <E> UnmodifiableArrayList<E> wrap(final E[] array) { // NOT "E..." - see javadoc.
         return (array != null) ? new UnmodifiableArrayList<E>(array) : null;
     }
 
@@ -130,9 +138,7 @@ public class UnmodifiableArrayList<E> ex
      * @param  upper High endpoint (exclusive) of the sublist.
      * @return The given array wrapped in an unmodifiable list.
      */
-    public static <E> UnmodifiableArrayList<E> wrap(final E[] array, final int lower, final int upper)
-            throws IndexOutOfBoundsException
-    {
+    public static <E> UnmodifiableArrayList<E> wrap(final E[] array, final int lower, final int upper) {
         if (lower == 0 && upper == array.length) {
             return new UnmodifiableArrayList<E>(array);
         }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/About.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/About.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/About.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/About.java [UTF-8] Wed May  1 22:11:02 2013
@@ -454,7 +454,7 @@ pathTree:   for (int j=0; ; j++) {
                 }
             }
         }
-        TreeTables.valuesAsStrings(table, locale);
+        TreeTables.replaceCharSequences(table, locale);
         return table;
     }
 
@@ -600,15 +600,17 @@ pathTree:   for (int j=0; ; j++) {
      * node but lost all value of the parent node. For this reason, we perform the merge only if the
      * parent has no value.
      *
-     * <p>See the "<cite>Reduce the depth of a tree</cite>" example in {@link TreeTables}
-     * for more information.</p>
+     * <p>See the "<cite>Reduce the depth of a tree</cite>" example in {@link TreeTables} for more information.
+     * In particular, note that this implementation assumes that children collections are {@link List} (this is
+     * guaranteed for {@link DefaultTreeTable.Node} implementations).</p>
      *
      * @param  node The root of the node to simplify.
      * @param  skip {@code true} for disabling concatenation of root node.
      * @return The root of the simplified tree. May be the given {@code node} or a child.
      */
     private static TreeTable.Node concatenateSingletons(final TreeTable.Node node, final boolean skip) {
-        final List<TreeTable.Node> children = node.getChildren();
+        // DefaultTreeTable.Node instances are known to handle their children in a List.
+        final List<TreeTable.Node> children = (List<TreeTable.Node>) node.getChildren();
         final int size = children.size();
         for (int i=0; i<size; i++) {
             children.set(i, concatenateSingletons(children.get(i), false));

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Wed May  1 22:11:02 2013
@@ -1121,7 +1121,7 @@ search:     for (; fromIndex <= toIndex;
                 }
                 int upper = lower;
                 boolean forward = false;
-                do { // Do be run as long as we need to remove more characters.
+                do { // To be run as long as we need to remove more characters.
                     int nc=0, type=UNASSIGNED;
                     forward = !forward;
 searchWordBreak:    while (true) {
@@ -1176,6 +1176,47 @@ searchWordBreak:    while (true) {
     }
 
     /**
+     * Given a string in upper cases (typically a Java constant), returns a string formatted
+     * like an English sentence. This heuristic method performs the following steps:
+     *
+     * <ol>
+     *   <li>Replace all occurrences of {@code '_'} by spaces.</li>
+     *   <li>Converts all letters except the first one to lower case letters using
+     *       {@link Character#toLowerCase(int)}. Note that this method does not use
+     *       the {@link String#toLowerCase()} method. Consequently the system locale
+     *       is ignored. This method behaves as if the conversion were done in the
+     *       {@linkplain java.util.Locale#ROOT root} locale.</li>
+     * </ol>
+     *
+     * <p>Note that those heuristic rules may be modified in future SIS versions,
+     * depending on the practical experience gained.</p>
+     *
+     * @param  identifier The name of a Java constant, or {@code null}.
+     * @return The identifier like an English sentence, or {@code null}
+     *         if the given {@code identifier} argument was null.
+     */
+    public static CharSequence upperCaseToSentence(final CharSequence identifier) {
+        if (identifier == null) {
+            return null;
+        }
+        final StringBuilder buffer = new StringBuilder(identifier.length());
+        final int length = identifier.length();
+        for (int i=0; i<length;) {
+            int c = Character.codePointAt(identifier, i);
+            if (i != 0) {
+                if (c == '_') {
+                    c = ' ';
+                } else {
+                    c = Character.toLowerCase(c);
+                }
+            }
+            buffer.appendCodePoint(c);
+            i += Character.charCount(c);
+        }
+        return buffer;
+    }
+
+    /**
      * Given a string in camel cases (typically an identifier), returns a string formatted
      * like an English sentence. This heuristic method performs the following steps:
      *

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Classes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Classes.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Classes.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/Classes.java [UTF-8] Wed May  1 22:11:02 2013
@@ -61,7 +61,7 @@ public final class Classes extends Stati
     private static final Class<?>[] EMPTY_ARRAY = new Class<?>[0];
 
     /**
-     * Methods to be rejected by {@link #isGetter(Method)}. They are mostly methods inherited
+     * Methods to be rejected by {@link #isPossibleGetter(Method)}. They are mostly methods inherited
      * from {@link Object}. Only no-argument methods having a non-void return value need to be
      * declared in this list.
      *
@@ -560,20 +560,55 @@ cmp:    for (final Class<?> c : c1) {
     }
 
     /**
-     * Returns a short class name for the specified class. This method will
-     * omit the package name.  For example, it will return {@code "String"} instead
-     * of {@code "java.lang.String"} for a {@link String} object. It will also name
-     * array according Java language usage,  for example {@code "double[]"} instead
-     * of {@code "[D"}.
-     *
-     * <p>This method is similar to the {@link Class#getSimpleName()} method, except that
-     * if the given class is an inner class, then the returned value is prefixed with the
-     * outer class name. For example this method returns {@code "Point2D.Double"} instead
-     * of {@code "Double"}.</p>
+     * Returns the name of the given class without package name, but including the names of enclosing
+     * classes if any. This method is similar to the {@link Class#getSimpleName()} method, except that
+     * if the given class is an inner class, then the returned value is prefixed with the outer class
+     * name. An other difference is that if the given class is local or anonymous, then this method
+     * returns the name of the parent class.
+     *
+     * <p>The following table compares the various kind of names for some examples:</p>
+     *
+     * <table class="sis">
+     *   <tr>
+     *     <th>Class</th>
+     *     <th>{@code getName()}</th>
+     *     <th>{@code getSimpleName()}</th>
+     *     <th>{@code getCanonicalName()}</th>
+     *     <th>{@code getShortName()}</th>
+     *   </tr>
+     *   <tr>
+     *     <td>{@link String}</td>
+     *     <td>{@code "java.lang.String"}</td>
+     *     <td>{@code "String"}</td>
+     *     <td>{@code "java.lang.String"}</td>
+     *     <td>{@code "String"}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@link double[]}</td>
+     *     <td>{@code "[D"}</td>
+     *     <td>{@code "double[]"}</td>
+     *     <td>{@code "double[]"}</td>
+     *     <td>{@code "double[]"}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@link java.awt.geom.Point2D.Double}</td>
+     *     <td>{@code "java.awt.geom.Point2D$Double"}</td>
+     *     <td>{@code "Double"}</td>
+     *     <td>{@code "java.awt.geom.Point2D.Double"}</td>
+     *     <td>{@code "Point2D.Double"}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>Anonymous {@link Comparable}</td>
+     *     <td>{@code "com.mycompany.myclass$1"}</td>
+     *     <td>{@code ""}</td>
+     *     <td>{@code null}</td>
+     *     <td>{@code "Object"}</td>
+     *   </tr>
+     * </table>
      *
      * @param  classe The object class (may be {@code null}).
-     * @return A short class name for the specified object, or {@code "<*>"} if the
-     *         given class was null.
+     * @return The simple name with outer class name (if any) of the first non-anonymous
+     *         class in the hierarchy, or {@code "<*>"} if the given class is null.
      *
      * @see #getShortClassName(Object)
      * @see Class#getSimpleName()
@@ -594,12 +629,14 @@ cmp:    for (final Class<?> c : c1) {
     }
 
     /**
-     * Returns a short class name for the specified object. This method will
-     * omit the package name. For example, it will return {@code "String"}
-     * instead of {@code "java.lang.String"} for a {@link String} object.
+     * Returns the class name of the given object without package name, but including the enclosing class names
+     * if any. Invoking this method is equivalent to invoking {@code getShortName(object.getClass())} except for
+     * {@code null} value. See {@link #getShortName(Class)} for more information on the class name returned by
+     * this method.
      *
      * @param  object The object (may be {@code null}).
-     * @return A short class name for the specified object.
+     * @return The simple class name with outer class name (if any) of the first non-anonymous
+     *         class in the hierarchy, or {@code "<*>"} if the given object is null.
      *
      * @see #getShortName(Class)
      */

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java [UTF-8] Wed May  1 22:11:02 2013
@@ -20,6 +20,7 @@ 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;
@@ -286,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.
@@ -502,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
@@ -513,7 +532,11 @@ 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;
         }
@@ -568,7 +591,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) {
@@ -734,7 +757,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;
         }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java [UTF-8] Wed May  1 22:11:02 2013
@@ -108,6 +108,14 @@ 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 object types.
      * The column {@linkplain #getHeader() header} is "<cite>Type</cite>" (eventually localized).
      */
@@ -116,6 +124,17 @@ 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},

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java [UTF-8] Wed May  1 22:11:02 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.util.collection;
 
+import java.util.Collection;
 import java.util.List;
 
 
@@ -124,10 +125,10 @@ public interface TreeTable {
         /**
          * Returns the parent node, or {@code null} if this node is the root of the tree.
          *
-         * <p>There is intentionally no {@code setParent(Node)} method, as children and parent
-         * managements are highly implementation-dependant. If the {@linkplain #getChildren()
-         * children list} is modifiable, then implementations are encouraged to update automatically
-         * the parent when a child is <em>added to</em> or <em>removed from</em> the children list.</p>
+         * <p>There is intentionally no {@code setParent(Node)} method, as children and parent managements
+         * are highly implementation-dependant. If the {@linkplain #getChildren() children collection} is
+         * modifiable, then implementations are encouraged to update automatically the parent when a child
+         * is <em>added to</em> or <em>removed from</em> that collection.</p>
          *
          * @return The parent, or {@code null} if none.
          * @category tree
@@ -135,9 +136,21 @@ public interface TreeTable {
         Node getParent();
 
         /**
-         * Returns the children of this node. The returned list may or may not be modifiable, at
-         * implementation choice. If the list is modifiable, then it shall be <cite>live</cite>,
-         * i.e. any modification to the returned list are reflected immediately in the tree.
+         * Returns {@code true} if this node can not have any children. The {@linkplain #getChildren() children
+         * collection} of a leaf node can only be empty, and adding {@linkplain #newChild() new child}
+         * is an unsupported operation.
+         *
+         * <p>This value is provided as a tip for graphical user interfaces, in order to determine if
+         * a node is expandable (even if empty). {@link TreeTableFormat} does not use this value.</p>
+         *
+         * @return {@code true} if this node can not have any children.
+         */
+        boolean isLeaf();
+
+        /**
+         * Returns the children of this node. The returned collection may or may not be modifiable, at
+         * implementation choice. If the collection is modifiable, then it shall be <cite>live</cite>,
+         * i.e. any modification to the returned collection are reflected immediately in the tree.
          * This allows addition or removal of child nodes as below:
          *
          * {@preformat java
@@ -145,20 +158,25 @@ public interface TreeTable {
          *     parent.getChildren().add(newNode);
          * }
          *
-         * @return The children, or an empty list if none.
+         * The collection is often a {@link List}, but not necessarily. For some implementations like the
+         * {@linkplain org.apache.sis.metadata.AbstractMetadata#asTreeTable() metadata tree table view},
+         * compliance to the {@code List} contract is impractical or inefficient.
+         *
+         * @return The children, or an empty collection if none.
          * @category tree
          */
-        List<Node> getChildren();
+        Collection<Node> getChildren();
 
         /**
-         * Creates a new child with the same columns than the other children, and add it to
-         * the {@linkplain #getChildren() children list}. The new child is typically added at
-         * the end of the list, but this is not mandatory: implementations can add the child
+         * Creates a new child with the same columns than the other children, and adds it to
+         * the {@linkplain #getChildren() children collection}. The new child is typically added at
+         * the end of the collection, but this is not mandatory: implementations can add the child
          * at whatever position they see fit.
          *
          * @return The new child.
+         * @throws UnsupportedOperationException If this node can not add new children.
          */
-        Node newChild();
+        Node newChild() throws UnsupportedOperationException;
 
         /**
          * Returns the value in the given column, or {@code null} if none.
@@ -187,7 +205,7 @@ public interface TreeTable {
          * @see #isEditable(TableColumn)
          * @category table
          */
-        <V> void setValue(TableColumn<V> column, V value);
+        <V> void setValue(TableColumn<V> column, V value) throws IllegalArgumentException, UnsupportedOperationException;
 
         /**
          * Determines whether the value in the specified column is editable. If the given

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java [UTF-8] Wed May  1 22:11:02 2013
@@ -17,6 +17,7 @@
 package org.apache.sis.util.collection;
 
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.List;
 import java.util.Locale;
@@ -27,10 +28,13 @@ import java.text.ParsePosition;
 import java.text.ParseException;
 import java.util.regex.Matcher;
 import net.jcip.annotations.NotThreadSafe;
+import org.opengis.util.CodeList;
+import org.opengis.util.InternationalString;
 import org.apache.sis.io.LineAppender;
 import org.apache.sis.io.TableAppender;
 import org.apache.sis.io.TabularFormat;
 import org.apache.sis.io.CompoundFormat;
+import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Workaround;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
@@ -581,6 +585,12 @@ public class TreeTableFormat extends Tab
                     return;
                 }
                 text = format.format(value);
+            } else if (value instanceof InternationalString) {
+                text = ((InternationalString) value).toString(locale);
+            } else if (value instanceof CodeList<?>) {
+                text = Types.getCodeTitle((CodeList<?>) value).toString(locale);
+            } else if (value instanceof Enum<?>) {
+                text = CharSequences.upperCaseToSentence(((Enum<?>) value).name());
             } else {
                 text = String.valueOf(value);
             }
@@ -626,11 +636,13 @@ public class TreeTableFormat extends Tab
             if (level >= isLast.length) {
                 isLast = Arrays.copyOf(isLast, level*2);
             }
-            final List<? extends TreeTable.Node> children = node.getChildren();
-            final int count = children.size();
-            for (int i=0; i<count; i++) {
-                isLast[level] = (i == count-1);
-                format(children.get(i), level+1);
+            final Iterator<? extends TreeTable.Node> it = node.getChildren().iterator();
+            boolean hasNext = it.hasNext();
+            while (hasNext) {
+                final TreeTable.Node child = it.next();
+                hasNext = it.hasNext();
+                isLast[level] = !hasNext; // Must be set before the call to 'format' below.
+                format(child, level+1);
             }
         }
     }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java [UTF-8] Wed May  1 22:11:02 2013
@@ -37,16 +37,14 @@ import org.apache.sis.util.ArgumentCheck
  * Developers can copy and adapt those examples as they see fit.</p>
  *
  * {@section Example 1: Reduce the depth of a tree}
- * For every branch containing only one child and no value, the following method merges in-place
- * that branch and the node together. This method can be used for simplifying depth trees into
- * something less verbose. However for any column other than {@code NAME}, this method preserves
- * the values of the child node but lost all value of the parent node. For this reason, we perform
- * the merge only if the parent has no value.
- *
- * <p>For example given the tree on the left side, this method transforms it into the tree on the
- * right side:</p>
- *
- * <table class="compact"><tr><td>
+ * For every branch containing exactly one child, the following method concatenates in-place
+ * that branch and its child together. This method can be used for simplifying depth trees into
+ * something less verbose. For example given the tree on the left side, this method transforms
+ * it into the tree on the right side:
+ *
+ * <table class="sis">
+ * <tr><th>Before</th><th class="sep">After</th></tr>
+ * <tr><td>
  * {@preformat text
  *   root
  *     ├─users
@@ -56,7 +54,7 @@ import org.apache.sis.util.ArgumentCheck
  *     │       └─document
  *     └─lib
  * }
- * </td><td>
+ * </td><td class="sep">
  * {@preformat text
  *   root
  *     ├─users/alice
@@ -65,38 +63,45 @@ import org.apache.sis.util.ArgumentCheck
  *     └─lib
  * }
  * </td></tr></table>
+ * There is no pre-defined method for this task because there is too many parameters that
+ * developers may want to customize (columns to merge, conditions for accepting the merge,
+ * kind of objects to merge, name separator, <i>etc.</i>). In the following code snippet,
+ * the content of the {@code NAME} columns are concatenated only if the {@code VALUE} column
+ * has no value (for avoiding data lost when the node is discarded) and use the system file
+ * separator as name separator:
+ *
  * {@preformat java
- *   import static org.apache.sis.util.collection.TableColumn.NAME;          // The column to merge
- *   import static org.apache.sis.util.collection.TableColumn.VALUE_AS_TEXT; // The column which must be empty
+ *     final TableColumn columnToProtect = TableColumn.VALUE;
+ *     final TableColumn columnToConcatenate = TableColumn.NAME;
  *
- *   public class MyClass {
- *       private static TreeTable.Node concatenateSingletons(final TreeTable.Node node) {
- *           final List<TreeTable.Node> children = node.getChildren();
- *           final int size = children.size();
- *           for (int i=0; i<size; i++) {
- *               children.set(i, concatenateSingletons(children.get(i)));
- *           }
- *           if (size == 1) {
- *               final TreeTable.Node child = children.get(0);
- *               if (node.getValue(VALUE_AS_TEXT) == null) {
- *                   children.remove(0);
- *                   child.setValue(NAME, node.getValue(NAME) + File.separator + child.getValue(NAME));
- *                   return child;
- *               }
- *           }
- *           return node;
- *       }
- *   }
+ *     TreeTable.Node concatenateSingletons(final TreeTable.Node node) {
+ *         // This simple example is restricted to nodes which are known to handle
+ *         // their children in a list instead than some other kind of collection.
+ *         final List<TreeTable.Node> children = (List<TreeTable.Node>) node.getChildren();
+ *         final int size = children.size();
+ *         for (int i=0; i<size; i++) {
+ *             children.set(i, concatenateSingletons(children.get(i)));
+ *         }
+ *         if (size == 1) {
+ *             final TreeTable.Node child = children.get(0);
+ *             if (node.getValue(columnToProtect) == null) {
+ *                 children.remove(0);
+ *                 child.setValue(columnToConcatenate,
+ *                         node .getValue(columnToConcatenate) + File.separator +
+ *                         child.getValue(columnToConcatenate));
+ *                 return child;
+ *             }
+ *         }
+ *         return node;
+ *     }
  * }
  *
- * There is no pre-defined method for this task because there is too many parameters that
- * developers may want to customize (columns to merge, conditions for accepting the merge,
- * kind of objects to merge, name separator).
- *
  * @author  Martin Desruisseaux
  * @since   0.3
  * @version 0.3
  * @module
+ *
+ * @see TreeTable
  */
 public final class TreeTables extends Static {
     /**
@@ -108,7 +113,7 @@ public final class TreeTables extends St
     /**
      * Finds the node for the given path, or creates a new node if none exists.
      * First, this method searches in the node {@linkplain TreeTable.Node#getChildren()
-     * children list} for the root element of the given path. If no such node is found,
+     * children collection} for the root element of the given path. If no such node is found,
      * a {@linkplain TreeTable.Node#newChild() new child} is created. Then this method
      * repeats the process (searching in the children of the child for the second path
      * element), until the last path element is reached.
@@ -151,8 +156,8 @@ public final class TreeTables extends St
     }
 
     /**
-     * For every columns having values {@linkplain Class#isAssignableFrom(Class) assignable from}
-     * {@code String}, converts the values to {@code String}s. During conversions, this method also
+     * For every columns having values of type {@link CharSequence} or {@link String},
+     * converts the values to localized {@code String}s. During conversions, this method also
      * replaces duplicated {@code String} instances by references to the same singleton instance.
      *
      * <p>This method may be invoked before to serialize the table in order to reduce the
@@ -163,7 +168,7 @@ public final class TreeTables extends St
      * @return Number of replacements done.
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
-    public static int valuesAsStrings(final TreeTable table, final Locale locale) {
+    public static int replaceCharSequences(final TreeTable table, final Locale locale) {
         ArgumentChecks.ensureNonNull("table", table);
         final List<TableColumn<?>> columns = table.getColumns();
         TableColumn<? super String>[] filtered = new TableColumn[columns.size()];
@@ -174,11 +179,11 @@ public final class TreeTables extends St
             }
         }
         filtered = ArraysExt.resize(filtered, count);
-        return valuesAsStrings(table.getRoot(), filtered, locale, new HashMap<String,String>());
+        return replaceCharSequences(table.getRoot(), filtered, locale, new HashMap<String,String>());
     }
 
     /**
-     * Implementation of the public {@link #valuesAsStrings(TreeTable, Locale)} method.
+     * Implementation of the public {@link #replaceCharSequences(TreeTable, Locale)} method.
      *
      * @param  node    The node in which to replace values by their string representations.
      * @param  columns The columns where to perform the replacements.
@@ -186,12 +191,12 @@ public final class TreeTables extends St
      * @param  pool    An initially empty pool of string representations, to be filled by this method.
      * @return Number of replacements done.
      */
-    private static int valuesAsStrings(final TreeTable.Node node, final TableColumn<? super String>[] columns,
+    private static int replaceCharSequences(final TreeTable.Node node, final TableColumn<? super String>[] columns,
             final Locale locale, final Map<String,String> pool)
     {
         int changes = 0;
         for (final TreeTable.Node child : node.getChildren()) {
-            changes += valuesAsStrings(child, columns, locale, pool);
+            changes += replaceCharSequences(child, columns, locale, pool);
         }
         for (final TableColumn<? super String> column : columns) {
             final Object value = node.getValue(column);
@@ -218,7 +223,7 @@ public final class TreeTables extends St
 
     /**
      * Returns a string representation of the given tree table.
-     * The default implementation uses a shared instance of {@link TreeTableFormat}.
+     * 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 {@code TreeTableFormat}
      * instance.
@@ -238,27 +243,27 @@ public final class TreeTables extends St
      * This helper method is sometime useful for quick tests or debugging purposes.
      * For more extensive use, consider using {@link TreeTableFormat} instead.
      *
-     * @param  text   The string representation to parse.
-     * @param  nodes  The columns where to store the node labels. This is often {@link TableColumn#NAME}.
-     * @param  values Optional columns where to store the values, if any.
+     * @param  tree         The string representation of the tree to parse.
+     * @param  labelColumn  The columns where to store the node labels. This is often {@link TableColumn#NAME}.
+     * @param  otherColumns Optional columns where to store the values, if any.
      * @return A tree parsed from the given string.
      * @throws ParseException If an error occurred while parsing the tree.
      */
-    public static TreeTable parse(final String text, final TableColumn<?> nodes,
-            final TableColumn<?>... values) throws ParseException
+    public static TreeTable parse(final String tree, final TableColumn<?> labelColumn,
+            final TableColumn<?>... otherColumns) throws ParseException
     {
-        ArgumentChecks.ensureNonNull("text",  text);
-        ArgumentChecks.ensureNonNull("nodes", nodes);
+        ArgumentChecks.ensureNonNull("tree", tree);
+        ArgumentChecks.ensureNonNull("labelColumn", labelColumn);
         TableColumn<?>[] columns = null; // Default to singleton(NAME).
-        if (values.length != 0 || nodes != TableColumn.NAME) {
-            columns = ArraysExt.insert(values, 0, 1);
-            columns[0] = nodes;
+        if (otherColumns.length != 0 || labelColumn != TableColumn.NAME) {
+            columns = ArraysExt.insert(otherColumns, 0, 1);
+            columns[0] = labelColumn;
         }
         final TreeTableFormat format = TreeTableFormat.INSTANCE;
         synchronized (format) {
             try {
                 format.setColumns(columns);
-                return format.parseObject(text);
+                return format.parseObject(tree);
             } finally {
                 format.setColumns((TableColumn<?>[]) null);
             }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/AbstractInternationalString.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/AbstractInternationalString.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/AbstractInternationalString.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/AbstractInternationalString.java [UTF-8] Wed May  1 22:11:02 2013
@@ -100,14 +100,7 @@ public abstract class AbstractInternatio
      */
     @Override
     public CharSequence subSequence(final int start, final int end) {
-        final String text = toString();
-        if (text == null) {
-            if (start == 0 && end == 0) {
-                return "";
-            }
-            throw new StringIndexOutOfBoundsException();
-        }
-        return text.substring(start, end);
+        return toString().substring(start, end);
     }
 
     /**

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/ResourceInternationalString.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/ResourceInternationalString.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/ResourceInternationalString.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/iso/ResourceInternationalString.java [UTF-8] Wed May  1 22:11:02 2013
@@ -173,7 +173,7 @@ public class ResourceInternationalString
     public boolean equals(final Object object) {
         if (object != null && object.getClass() == getClass()) {
             final ResourceInternationalString that = (ResourceInternationalString) object;
-            return key.equals(that.key) && resources.equals(resources);
+            return key.equals(that.key) && resources.equals(that.resources);
         }
         return false;
     }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Wed May  1 22:11:02 2013
@@ -451,6 +451,11 @@ public final class Errors extends Indexe
         public static final int UnmodifiableAffineTransform = 23;
 
         /**
+         * The cell at column “{1}” of row “{0}” is unmodifiable.
+         */
+        public static final int UnmodifiableCellValue_2 = 89;
+
+        /**
          * This geometry is unmodifiable.
          */
         public static final int UnmodifiableGeometry = 24;

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Wed May  1 22:11:02 2013
@@ -102,6 +102,7 @@ UnexpectedEndOfString_1         = More c
 UnknownType_1                   = Type \u2018{0}\u2019 is unknown in this context.
 UnknownTypeForProperty_1        = Type of the \u201c{0}\u201d property is unknown.
 UnmodifiableAffineTransform     = This affine transform is unmodifiable.
+UnmodifiableCellValue_2         = The cell at column \u201c{1}\u201d of row \u201c{0}\u201d is unmodifiable.
 UnmodifiableGeometry            = This geometry is unmodifiable.
 UnmodifiableMetadata            = This metadata is unmodifiable.
 UnmodifiableObject_1            = Object \u2018{0}\u2019 is unmodifiable.

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Wed May  1 22:11:02 2013
@@ -91,6 +91,7 @@ UnexpectedEndOfString_1         = D\u201
 UnknownType_1                   = Le type \u2018{0}\u2019 n\u2019est pas reconnu dans ce contexte.
 UnknownTypeForProperty_1        = Le type de la propri\u00e9t\u00e9 \u201c{0}\u201d est inconnu.
 UnmodifiableAffineTransform     = Cette transformation affine n\u2019est pas modifiable.
+UnmodifiableCellValue_2         = La cellule \u00e0 la colonne \u201c{1}\u201d de la ligne \u201c{0}\u201d n\u2019est pas modifiable.
 UnmodifiableGeometry            = Cette g\u00e9om\u00e9trie n\u2019est pas modifiable.
 UnmodifiableMetadata            = Cette m\u00e9ta-donn\u00e9e n\u2019est pas modifiable.
 UnmodifiableObject_1            = L\u2019objet \u2018{0}\u2019 n\u2019est pas modifiable.

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java [UTF-8] Wed May  1 22:11:02 2013
@@ -115,6 +115,11 @@ public final class Vocabulary extends In
         public static final int Directory = 36;
 
         /**
+         * Identifier
+         */
+        public static final int Identifier = 42;
+
+        /**
          * Java extensions
          */
         public static final int JavaExtensions = 26;
@@ -185,6 +190,11 @@ public final class Vocabulary extends In
         public static final int NumberOfValues = 2;
 
         /**
+         * {0} ({1} of {2})
+         */
+        public static final int Of_3 = 43;
+
+        /**
          * Offset
          */
         public static final int Offset = 22;
@@ -330,4 +340,34 @@ public final class Vocabulary extends In
     public static InternationalString formatInternational(final int key) {
         return new International(key);
     }
+
+    /**
+     * Gets an international string for the given key. This method does not check for the key
+     * validity. If the key is invalid, then a {@link MissingResourceException} may be thrown
+     * when a {@link InternationalString#toString(Locale)} method is invoked.
+     *
+     * {@note This method is redundant with the one expecting <code>Object...</code>, but avoid
+     *        the creation of a temporary array. There is no risk of confusion since the two
+     *        methods delegate their work to the same <code>format</code> method anyway.}
+     *
+     * @param  key The key for the desired string.
+     * @param  arg Values to substitute to "{0}".
+     * @return An international string for the given key.
+     */
+    public static InternationalString formatInternational(final int key, final Object arg) {
+        return new International(key, arg);
+    }
+
+    /**
+     * Gets an international string for the given key. This method does not check for the key
+     * validity. If the key is invalid, then a {@link MissingResourceException} may be thrown
+     * when a {@link InternationalString#toString(Locale)} method is invoked.
+     *
+     * @param  key  The key for the desired string.
+     * @param  args Values to substitute to "{0}", "{1}", <i>etc</i>.
+     * @return An international string for the given key.
+     */
+    public static InternationalString formatInternational(final int key, final Object... args) {
+        return new International(key, args);
+    }
 }

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties [ISO-8859-1] Wed May  1 22:11:02 2013
@@ -26,6 +26,7 @@ CurrentDirectory   = Current directory
 DaylightTime       = Daylight time
 Destination        = Destination
 Directory          = Directory
+Identifier         = Identifier
 JavaExtensions     = Java extensions
 JavaHome           = Java home directory
 Latitude           = Latitude
@@ -40,6 +41,7 @@ MinimumValue       = Minimum value
 Name               = Name
 NumberOfValues     = Number of values
 NumberOfNaN        = Number of \u2018NaN\u2019
+Of_3               = {0} ({1} of {2})
 Offset             = Offset
 OperatingSystem    = Operating system
 Others             = Others

Modified: sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK6/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties [ISO-8859-1] Wed May  1 22:11:02 2013
@@ -26,6 +26,7 @@ CurrentDirectory   = R\u00e9pertoire cou
 DaylightTime       = Heure normale
 Destination        = Destination
 Directory          = R\u00e9pertoire
+Identifier         = Identifiant
 JavaExtensions     = Extensions du Java
 JavaHome           = R\u00e9pertoire du Java
 Latitude           = Latitude
@@ -40,6 +41,7 @@ MinimumValue       = Valeur minimale
 Name               = Nom
 NumberOfValues     = Nombre de valeurs
 NumberOfNaN        = Nombre de \u2018NaN\u2019
+Of_3               = {0} ({1} de {2})
 Offset             = D\u00e9calage
 OperatingSystem    = Syst\u00e8me d'exploitation
 Others             = Autres

Copied: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java (from r1478202, sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java?p2=sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java&p1=sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java&r1=1478202&r2=1478216&rev=1478216&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java [UTF-8] Wed May  1 22:11:02 2013
@@ -181,7 +181,7 @@ public abstract strictfp class Annotatio
                     wrapper.isInherited = true;
                     return wrapper;
                 } catch (ClassNotFoundException e2) {
-                    e.addSuppressed(e2);
+                    // JDK7 branch does: e.addSuppressed(e2);
                 }
             }
             throw e;
@@ -404,7 +404,7 @@ public abstract strictfp class Annotatio
      */
     @Test
     public void testPackageAnnotations() {
-        final Set<Package> packages = new HashSet<>();
+        final Set<Package> packages = new HashSet<Package>();
         for (final Class<?> type : types) {
             if (!CodeList.class.isAssignableFrom(type)) {
                 testingClass = type.getCanonicalName();

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java [UTF-8] Wed May  1 22:11:02 2013
@@ -200,6 +200,20 @@ public final strictfp class TestUtilitie
     }
 
     /**
+     * Returns the single element from the given array. If the given array is null or
+     * does not contains exactly one element, then an {@link AssertionError} is thrown.
+     *
+     * @param  <E> The type of array elements.
+     * @param  array The array from which to get the singleton.
+     * @return The singleton element from the array.
+     */
+    public static <E> E getSingleton(final E[] array) {
+        assertNotNull("Null array.", array);
+        assertEquals("Not a singleton array.", 1, array.length);
+        return array[0];
+    }
+
+    /**
      * Returns the single element from the given collection. If the given collection is null
      * or does not contains exactly one element, then an {@link AssertionError} is thrown.
      *

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java [UTF-8] Wed May  1 22:11:02 2013
@@ -275,6 +275,15 @@ public final strictfp class CharSequence
     }
 
     /**
+     * Tests the {@link CharSequences#upperCaseToSentence(CharSequence)} method.
+     */
+    @Test
+    public void testUpperCaseToSentence() {
+        final CharSequence convert = upperCaseToSentence("HALF_DOWN");
+        assertEquals("Half down", convert.toString());
+    }
+
+    /**
      * Tests the {@link CharSequences#camelCaseToWords(CharSequence, boolean)} method.
      */
     @Test

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java [UTF-8] Wed May  1 22:11:02 2013
@@ -43,6 +43,7 @@ import java.io.ObjectStreamException;
 import java.io.InvalidObjectException;
 import java.io.NotSerializableException;
 import java.io.Serializable;
+import java.awt.geom.Point2D;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.GeographicCRS;
@@ -224,4 +225,36 @@ public final strictfp class ClassesTest 
         public void setter2(Set<? extends Short> dummy) {}
         public void setter3(Set<? super  Double> dummy) {}
     }
+
+    /**
+     * Tests the {@link Classes#getShortName(Class)}, in particular the example values
+     * given in the javadoc.
+     */
+    @Test
+    public void testGetShortName() {
+        assertEquals("java.lang.String", String.class.getName());
+        assertEquals("String",           String.class.getSimpleName());
+        assertEquals("java.lang.String", String.class.getCanonicalName());
+        assertEquals("String",           getShortName(String.class));
+
+        assertEquals("[D",       double[].class.getName());
+        assertEquals("double[]", double[].class.getSimpleName());
+        assertEquals("double[]", double[].class.getCanonicalName());
+        assertEquals("double[]", getShortName(double[].class));
+
+        assertEquals("java.awt.geom.Point2D$Double", Point2D.Double.class.getName());
+        assertEquals("Double",                       Point2D.Double.class.getSimpleName());
+        assertEquals("java.awt.geom.Point2D.Double", Point2D.Double.class.getCanonicalName());
+        assertEquals("Point2D.Double",               getShortName(Point2D.Double.class));
+
+        final Class<?> anonymous = new Comparable<Object>() {
+            @Override public int compareTo(final Object o) {
+                return 0; // Not the purpose of this test.
+            }
+        }.getClass();
+        assertTrue(anonymous.getName().startsWith("org.apache.sis.util.ClassesTest$"));
+        assertEquals("",       anonymous.getSimpleName());
+        assertEquals(null,     anonymous.getCanonicalName());
+        assertEquals("Object", getShortName(anonymous));
+    }
 }

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java [UTF-8] Wed May  1 22:11:02 2013
@@ -17,6 +17,7 @@
 package org.apache.sis.util.collection;
 
 import java.util.List;
+import java.util.Collection;
 import org.junit.Test;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.TestStep;
@@ -114,7 +115,7 @@ public final strictfp class DefaultTreeT
      */
     @TestStep
     private static void testNodeDisplacement(final TreeTable.Node root) {
-        final List<TreeTable.Node> rootChildren, nodeChildren;
+        final Collection<TreeTable.Node> rootChildren, nodeChildren;
         final TreeTable.Node node1 = getSingleton(rootChildren = root .getChildren());
         final TreeTable.Node node2 = getSingleton(nodeChildren = node1.getChildren());
         try {
@@ -149,7 +150,7 @@ public final strictfp class DefaultTreeT
         assertNotSame("clone", table, newTable);
         assertEquals("newTable.equals(table)", table, newTable);
         assertEquals("hashCode", table.hashCode(), newTable.hashCode());
-        newTable.getRoot().getChildren().get(1).setValue(NAME, "New name");
+        getChildrenList(newTable).get(1).setValue(NAME, "New name");
         assertFalse("newTable.equals(table)", newTable.equals(table));
     }
 
@@ -162,11 +163,22 @@ public final strictfp class DefaultTreeT
     @TestStep
     private void testSerialization(final TreeTable table) {
         final TreeTable newTable = assertSerializedEquals(table);
-        newTable.getRoot().getChildren().get(1).setValue(NAME, "New name");
+        getChildrenList(newTable).get(1).setValue(NAME, "New name");
         assertFalse("newTable.equals(table)", newTable.equals(table));
     }
 
     /**
+     * Returns the children of the root of the given table as a list.
+     * Instances of {@link DefaultTreeTable.Node} shall be guaranteed
+     * to store their children in a list.
+     */
+    private static List<TreeTable.Node> getChildrenList(final TreeTable table) {
+        final Collection<TreeTable.Node> children = table.getRoot().getChildren();
+        assertInstanceOf("TreeTable.Node.getChildren()", List.class, children);
+        return (List<TreeTable.Node>) children;
+    }
+
+    /**
      * Tests the creation of a tree table with a few nodes, and tests the displacement of a node
      * from one branch to another. Finally tests the serialization of that table and the comparison
      * with the original object.

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java [UTF-8] Wed May  1 22:11:02 2013
@@ -16,11 +16,15 @@
  */
 package org.apache.sis.util.collection;
 
+import java.util.Locale;
+import java.math.RoundingMode;
 import java.text.ParseException;
-import org.junit.Test;
+import org.opengis.metadata.citation.Role;
+import org.apache.sis.util.iso.DefaultInternationalString;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.DependsOnMethod;
+import org.junit.Test;
 
 import static org.apache.sis.test.Assert.*;
 import static org.apache.sis.util.collection.TableColumn.*;
@@ -196,4 +200,55 @@ public final strictfp class TreeTableFor
         assertEquals("?……[…] /\\w*│+\\w*", tf.getColumnSeparatorPattern());
         assertEquals(table, tf.parseObject(text));
     }
+
+    /**
+     * Tests the parsing of a tree containing a code list, an enumeration and an international string.
+     * Those types shall be handled in a special way.
+     */
+    @Test
+    @DependsOnMethod("testTreeTableFormat")
+    public void testLocalizedFormat() {
+        final DefaultInternationalString i18n = new DefaultInternationalString();
+        i18n.add(Locale.ENGLISH,  "An English sentence");
+        i18n.add(Locale.FRENCH,   "Une phrase en français");
+        i18n.add(Locale.JAPANESE, "日本語の言葉");
+
+        final DefaultTreeTable table  = new DefaultTreeTable(NAME, VALUE);
+        final TreeTable.Node   root   = table.getRoot();
+        root.setValue(NAME, "Root");
+
+        TreeTable.Node child;
+        child = root.newChild();
+        child.setValue(NAME, "CodeList");
+        child.setValue(VALUE, Role.POINT_OF_CONTACT);
+
+        child = root.newChild();
+        child.setValue(NAME, "Enum");
+        child.setValue(VALUE, RoundingMode.HALF_DOWN);
+
+        child = root.newChild();
+        child.setValue(NAME, "i18n");
+        child.setValue(VALUE, i18n);
+
+        TreeTableFormat tf = new TreeTableFormat(null, null);
+        assertMultilinesEquals(
+                "Root\n" +
+                "  ├─CodeList…… Point of contact\n" +
+                "  ├─Enum……………… Half down\n" +
+                "  └─i18n……………… An English sentence\n", tf.format(table));
+
+        tf = new TreeTableFormat(Locale.FRENCH, null);
+        assertMultilinesEquals(
+                "Root\n" +
+                "  ├─CodeList…… Point of contact\n" + // Not yet localized.
+                "  ├─Enum……………… Half down\n" +        // No localization provided.
+                "  └─i18n……………… Une phrase en français\n", tf.format(table));
+
+        tf = new TreeTableFormat(Locale.JAPANESE, null);
+        assertMultilinesEquals(
+                "Root\n" +
+                "  ├─CodeList…… Point of contact\n" + // Not yet localized.
+                "  ├─Enum……………… Half down\n" +        // No localization provided.
+                "  └─i18n……………… 日本語の言葉\n", tf.format(table));
+    }
 }

Modified: sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTablesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTablesTest.java?rev=1478216&r1=1478215&r2=1478216&view=diff
==============================================================================
--- sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTablesTest.java [UTF-8] (original)
+++ sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTablesTest.java [UTF-8] Wed May  1 22:11:02 2013
@@ -42,13 +42,14 @@ import static org.apache.sis.util.collec
 })
 public final strictfp class TreeTablesTest extends TestCase {
     /**
-     * The example documented in the {@code TreeTable} javadoc.
+     * The {@code concatenateSingletons(…)} example documented in the {@link TreeTables} class javadoc.
+     * This simple code assumes that the children collection in the given node is a {@link List}.
      *
      * @param  node The root of the node to simplify.
      * @return The root of the simplified tree. May be the given {@code node} or a child.
      */
     public static TreeTable.Node concatenateSingletons(final TreeTable.Node node) {
-        final List<TreeTable.Node> children = node.getChildren();
+        final List<TreeTable.Node> children = (List<TreeTable.Node>) node.getChildren();
         final int size = children.size();
         for (int i=0; i<size; i++) {
             children.set(i, concatenateSingletons(children.get(i)));
@@ -115,10 +116,10 @@ public final strictfp class TreeTablesTe
     }
 
     /**
-     * Tests the {@link TreeTables#valuesAsStrings(TreeTable, Locale)} method.
+     * Tests the {@link TreeTables#replaceCharSequences(TreeTable, Locale)} method.
      */
     @Test
-    public void testValuesAsStrings() {
+    public void testReplaceCharSequences() {
         final TreeTable table = new DefaultTreeTable(NAME, VALUE_AS_NUMBER);
         final TreeTable.Node root   = table .getRoot();
         final TreeTable.Node parent = root  .newChild();
@@ -132,11 +133,11 @@ public final strictfp class TreeTablesTe
         parent.setValue(VALUE_AS_NUMBER, 4);
 
         final String asString = table.toString();
-        assertEquals(3, valuesAsStrings(table, null));
-        assertInstanceOf("valuesAsStrings:", String.class, root  .getValue(NAME));
-        assertInstanceOf("valuesAsStrings:", String.class, parent.getValue(NAME));
-        assertInstanceOf("valuesAsStrings:", String.class, child1.getValue(NAME));
-        assertInstanceOf("valuesAsStrings:", String.class, child2.getValue(NAME));
+        assertEquals(3, replaceCharSequences(table, null));
+        assertInstanceOf("replaceCharSequences:", String.class, root  .getValue(NAME));
+        assertInstanceOf("replaceCharSequences:", String.class, parent.getValue(NAME));
+        assertInstanceOf("replaceCharSequences:", String.class, child1.getValue(NAME));
+        assertInstanceOf("replaceCharSequences:", String.class, child2.getValue(NAME));
         assertSame("Expected unique instance of String.", child1.getValue(NAME), child2.getValue(NAME));
         assertEquals("String representation shall be the same.", asString, table.toString());
     }



Mime
View raw message