sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1412454 - in /sis/branches/JDK7/sis-utility/src: main/java/org/apache/sis/internal/util/ main/java/org/apache/sis/util/collection/ main/java/org/apache/sis/util/resources/ test/java/org/apache/sis/util/collection/
Date Thu, 22 Nov 2012 08:57:28 GMT
Author: desruisseaux
Date: Thu Nov 22 08:57:27 2012
New Revision: 1412454

URL: http://svn.apache.org/viewvc?rev=1412454&view=rev
Log:
Added DefaultTreeTable.clone() method and added various documentation.

Added:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java 
 (with props)
Removed:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java
Modified:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java

Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java?rev=1412454&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java (added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java Thu
Nov 22 08:57:27 2012
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import org.apache.sis.util.Workaround;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Clones objects of arbitrary type using reflection methods. This is a workaround
+ * for the lack of public {@code clone()} method in the {@link Cloneable} interface.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.00)
+ * @version 0.3
+ * @module
+ */
+@Workaround(library="JDK", version="1.7")
+public final class Cloner {
+    /**
+     * The type of the object to clone, or {@code null} if not yet specified.
+     */
+    private Class<?> type;
+
+    /**
+     * The {@code clone()} method, or {@code null} if not yet determined.
+     */
+    private Method method;
+
+    /**
+     * Creates a new {@code Cloner} instance.
+     */
+    public Cloner() {
+    }
+
+    /**
+     * Clones the given object.
+     *
+     * @param  object The object to clone, or {@code null}.
+     * @return A clone of the given object, or {@code null} if {@code object} was null.
+     * @throws CloneNotSupportedException If the given object can not be cloned.
+     */
+    public Object clone(final Object object) throws CloneNotSupportedException {
+        if (object == null) {
+            return null;
+        }
+        final Class<?> valueType = object.getClass();
+        try {
+            if (valueType != type) {
+                method = valueType.getMethod("clone", (Class<?>[]) null);
+                type = valueType; // Set only if the above line succeed.
+            }
+            return method.invoke(object, (Object[]) null);
+        } catch (InvocationTargetException e) {
+            final Throwable cause = e.getCause();
+            if (cause instanceof CloneNotSupportedException) {
+                throw (CloneNotSupportedException) cause;
+            }
+            if (cause instanceof RuntimeException) {
+                throw (RuntimeException) cause;
+            }
+            if (cause instanceof Error) {
+                throw (Error) cause;
+            }
+            throw fail(e);
+        } catch (ReflectiveOperationException e) {
+            throw fail(e);
+        }
+    }
+
+    /**
+     * Returns an exception telling that the object can not be cloned because of the given
error.
+     * The {@link #clone(Object)} method must have been attempted before to invoke this method.
+     *
+     * @param  cause The cause for the failure to clone an object.
+     * @return An exception with an error message and the given cause.
+     */
+    public CloneNotSupportedException fail(final Throwable cause) {
+        CloneNotSupportedException e = new CloneNotSupportedException(
+                Errors.format(Errors.Keys.CloneNotSupported_1, type));
+        e.initCause(cause);
+        return e;
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
Thu Nov 22 08:57:27 2012
@@ -21,9 +21,11 @@ import java.util.Map;
 import java.util.LinkedHashMap;
 import java.util.Collections;
 import java.io.Serializable;
+import java.text.Format;
 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 static org.apache.sis.util.collection.Collections.isNullOrEmpty;
 import static org.apache.sis.util.collection.Collections.hashMapCapacity;
@@ -40,12 +42,12 @@ import java.util.Objects;
  * Example:
  *
  * {@preformat java
- *     class CityLocation {
- *         public static final TableColumn<String> CITY_NAME  = new MyColumn<>(String.class);
- *         public static final TableColumn<Float>  LATITUDE   = new MyColumn<>(Float
.class);
- *         public static final TableColumn<Float>  LONGTITUDE = new MyColumn<>(Float
.class);
+ *     public class CityLocation {
+ *         public static final TableColumn<String> CITY_NAME  = new TableColumn<>(String.class);
+ *         public static final TableColumn<Float>  LATITUDE   = new TableColumn<>(Float
.class);
+ *         public static final TableColumn<Float>  LONGTITUDE = new TableColumn<>(Float
.class);
  *
- *         TreeTable createTable() {
+ *         public TreeTable createTable() {
  *             DefaultTreeTable table = new DefaultTreeTable(CITY_NAME, LATITUDE, LONGITUDE);
  *             TreeTable.Node   city  = new DefaultTreeTable.Node(table);
  *             city.setValue(CITY_NAME, "Rimouski");
@@ -67,13 +69,18 @@ import java.util.Objects;
  * @module
  */
 @NotThreadSafe
-public class DefaultTreeTable implements TreeTable, Serializable {
+public class DefaultTreeTable implements TreeTable, Cloneable, Serializable {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = 1951201018202846555L;
 
     /**
+     * Shared {@code TreeTableFormat} instance for {@link #toString()} implementation.
+     */
+    private static Format format;
+
+    /**
      * The root node, or {@code null} if not yet specified.
      *
      * @see #getRoot()
@@ -116,7 +123,7 @@ public class DefaultTreeTable implements
      * <p>The {@linkplain #getRoot() root} node is initially {@code null}. Callers
can initialize
      * it after construction time by a call to the {@link #setRoot(TreeTable.Node)} method.</p>
      *
-     * @param columns The table columns.
+     * @param columns The list of table columns.
      */
     public DefaultTreeTable(TableColumn<?>... columns) {
         ArgumentChecks.ensureNonNull("columns", columns);
@@ -178,6 +185,9 @@ public class DefaultTreeTable implements
     /**
      * Returns the table columns given at construction time.
      * The returned list is never null neither empty.
+     *
+     * @see Node#getValue(TableColumn)
+     * @see Node#setValue(TableColumn, Object)
      */
     @Override
     public final List<TableColumn<?>> getColumns() {
@@ -222,13 +232,33 @@ public class DefaultTreeTable implements
     }
 
     /**
+     * Returns a clone of this table. This method clones the {@linkplain #getRoot() root}
node.
+     * If the root is an instance of {@link Node}, then cloning the root will recursively
clone
+     * all its {@linkplain Node#getChildren() children}.
+     *
+     * @return A clone of this table.
+     * @throws CloneNotSupportedException If this table, the root node or one of its children
+     *         can not be cloned.
+     *
+     * @see Node#clone()
+     */
+    @Override
+    public DefaultTreeTable clone() throws CloneNotSupportedException {
+        final DefaultTreeTable clone = (DefaultTreeTable) super.clone();
+        clone.root = (TreeTable.Node) new Cloner().clone(clone.root);
+        return clone;
+    }
+
+    /**
      * Compares the given object with this tree table for equality. This method compares
the
      * {@linkplain #getColumns() columns} and the {@linkplain #getRoot() root node}. If the
      * later is an instance of the {@link Node} inner class, then all node values and children
-     * will be {@linkplain Node#equals(Object) compared} recursively.
+     * will be compared recursively.
      *
      * @param  other The object to compare with this table.
      * @return {@code true} if the two objects are equal.
+     *
+     * @see Node#equals(Object)
      */
     @Override
     public boolean equals(final Object other) {
@@ -246,6 +276,8 @@ public class DefaultTreeTable implements
     /**
      * Returns a hash code value for this table.
      * This method is defined for consistency with {@link #equals(Object)} contract.
+     *
+     * @see Node#hashCode()
      */
     @Override
     public int hashCode() {
@@ -254,7 +286,7 @@ public class DefaultTreeTable implements
 
     /**
      * Returns a string representation of this tree table.
-     * The default implementation delegates to {@link TreeTables#toString(TreeTable)}.
+     * The default implementation delegates to {@link #toString(TreeTable)}.
      * 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.
@@ -263,7 +295,25 @@ public class DefaultTreeTable implements
      */
     @Override
     public String toString() {
-        return TreeTables.toString(this);
+        return toString(this);
+    }
+
+    /**
+     * Returns a string representation of the given tree table.
+     * The default 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.
+     *
+     * @param  table The tree table to format.
+     * @return A string representation of the given tree table.
+     */
+    public static synchronized String toString(final TreeTable table) {
+        ArgumentChecks.ensureNonNull("table", table);
+        if (format == null) {
+            format = new TreeTableFormat(null, null);
+        }
+        return format.format(table);
     }
 
 
@@ -284,7 +334,7 @@ public class DefaultTreeTable implements
      * @module
      */
     @NotThreadSafe
-    public static class Node implements TreeTable.Node, Serializable {
+    public static class Node implements TreeTable.Node, Cloneable, Serializable {
         /**
          * For cross-version compatibility.
          */
@@ -364,14 +414,6 @@ public class DefaultTreeTable implements
         private Object[] values;
 
         /**
-         * Creates a new node with the given shared map of columns and the given values.
-         */
-        Node(final Map<TableColumn<?>,Integer> columnIndices, final Object[]
values) {
-            this.columnIndices = columnIndices;
-            this.values = values;
-        }
-
-        /**
          * Creates a new node for the given table. The new node will be able to store a value
          * for each {@linkplain TreeTable#getColumns() columns} defined in the given table.
          *
@@ -425,9 +467,30 @@ public class DefaultTreeTable implements
         }
 
         /**
+         * Creates a node with a single column for object names (c<cite>convenience
constructor</cite>).
+         * The node will have the following columns:
+         *
+         * <table class="sis">
+         *   <tr><th>Header</th> <th>Type</th>            
    <th>Initial value</th></tr>
+         *   <tr><td>"Name"</td> <td>{@link CharSequence}</td>
<td>{@code name}</td></tr>
+         * </table>
+         *
+         * @param  name The initial value for the "Name" column (can be {@code null}).
+         */
+        public Node(final CharSequence name) {
+            columnIndices = TableColumn.NAME_MAP;
+            if (name != null) {
+                values = new CharSequence[] {name};
+            }
+        }
+
+        /**
          * Returns the parent of this node. On {@code Node} creation, this value may be initially
          * {@code null}. It will be automatically set to a non-null value when this node
will be
          * added as a child of another {@code Node} instance.
+         *
+         * <p>Note that the parent is ignored by {@link #clone()}, {@link #equals(Object)}
and
+         * {@link #hashCode()} operations.</p>
          */
         @Override
         public final TreeTable.Node getParent() {
@@ -530,13 +593,51 @@ public class DefaultTreeTable implements
         }
 
         /**
+         * Returns a clone of this node without parent.
+         * This method recursively clones all {@linkplain #getChildren() children},
+         * but does not clone the column {@linkplain #getValue(TableColumn) values}.
+         * The parent of the cloned node is set to {@code null}.
+         *
+         * @return A clone of this node without parent.
+         * @throws CloneNotSupportedException If this node or one of its children can not
be cloned.
+         */
+        @Override
+        public Node clone() throws CloneNotSupportedException {
+            final Node clone = (Node) super.clone();
+            clone.parent = null;
+            if (clone.values != null) {
+                clone.values = clone.values.clone();
+            }
+            if (clone.children != null) {
+                clone.children = new Children(clone);
+                for (final TreeTable.Node child : children) {
+                    /*
+                     * Implementation note: we could have used the Cloner for cloning arbitrary
+                     * node implementations, but children.add(...) would fail anyway because
it
+                     * can not set the parent of unknown implementation.
+                     */
+                    if (!(child instanceof Node)) {
+                        throw new CloneNotSupportedException(Errors.format(
+                                Errors.Keys.CloneNotSupported_1, child.getClass()));
+                    }
+                    clone.children.add(((Node) child).clone());
+                }
+            }
+            return clone;
+        }
+
+        /**
          * Compares the given object with this node for {@linkplain #getValue(TableColumn)
values}
          * and {@linkplain #getChildren() children} equality, ignoring the {@linkplain #getParent()
          * parent}. This method can be used for determining if two branches of a same tree
or of two
          * different trees are identical.
          *
-         * <p>This method compares children recursively, which is another reason why
the parents
-         * need to be ignored.</p>
+         * {@note This method ignores the parent because:
+         * <ul>
+         *   <li>When comparing the children recursively, comparing the parents would
cause infinite recursivity.</li>
+         *   <li>For consistency with the <code>clone()</code> method,
which can not clone the parent.</li>
+         *   <li>For making possible to compare branches instead than only whole trees.</li>
+         * </ul>}
          *
          * @param  other The object to compare with this node.
          * @return {@code true} if the two objects are equal, ignoring the parent node.
@@ -601,23 +702,25 @@ public class DefaultTreeTable implements
         }
 
         /**
-         * Returns a string representation of this node, for identification in error message
-         * or in debugger.
+         * Returns a string representation of this node for identification in error message
or in debugger.
+         * The default implementation returns the {@code toString()} value of the first non-empty
+         * {@link CharSequence} found in the {@linkplain #getValue(TableColumn) values},
if any.
+         * If no such value is found, then this method returns "<var>Node</var>-<var>i</var>"
+         * where <var>Node</var> is the {@linkplain Class#getSimpleName() simple
classname}
+         * and <var>i</var> is the index of this node in the parent node.
          *
          * @return A string representation of this node.
          */
         @Override
         public String toString() {
-            Object value = getUserObject();
-            if (value instanceof CharSequence) {
-                return value.toString();
-            }
             final Object[] values = this.values;
             if (values != null) {
-                for (int i=0; i<values.length; i++) {
-                    value = values[i];
+                for (final Object value : values) {
                     if (value instanceof CharSequence) {
-                        return value.toString();
+                        final String text = value.toString().trim();
+                        if (!text.isEmpty()) {
+                            return text;
+                        }
                     }
                 }
             }

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
Thu Nov 22 08:57:27 2012
@@ -33,13 +33,17 @@ import org.apache.sis.util.resources.Voc
  * as in the following example:
  *
  * {@preformat java
- *     class CityLocation {
+ *     public class CityLocation {
+ *         public static final ColumnTable<String> CITY_NAME = new ColumnTable<>(String.class,
"City name");
+ *         public static final ColumnTable<Float>  LATITUDE  = new ColumnTable<>(Float.class,
 "Latitude");
+ *         public static final ColumnTable<Float>  LONGITUDE = new ColumnTable<>(Float.class,
 "Longitude");
+ *
  *         private String name;
  *         private float  latitude;
  *         private float  longitude;
  *
  *         CityLocation(TreeTable.Node myNode) {
- *             name      = myNode.getValue(NAME);
+ *             name      = myNode.getValue(CITY_NAME);
  *             latitude  = myNode.getValue(LATITUDE);
  *             longitude = myNode.getValue(LONGITUDE);
  *         }
@@ -50,13 +54,43 @@ import org.apache.sis.util.resources.Voc
  * This base class relies on <cite>identity comparisons</cite> instead than defining
the
  * {@code equals(Object)} method, because the {@linkplain #getElementType() element type}
  * is not a sufficient criterion for differentiating the columns (many columns have values
- * of the same type) and the {@linkplain #getHeader() header} is arbitrary. Developers who
- * create their own instances are encouraged to declare them as static final constants.
+ * of the same type) and the {@linkplain #getHeader() header} is arbitrary. Consequently
+ * developers who create their own instances are encouraged to declare them as static final
+ * constants as in the above example, and use those constants consistently.
+ *
+ * <p>This base class is not serializable because the default deserialization mechanism
does
+ * not resolve automatically the deserialized instances to the above-cited singleton instances.
+ * Developers who need serialization support for their own instances have to resolve them
in
+ * their own subclass. The following example is one possible way to achieve that goal:</p>
+ *
+ * {@preformat java
+ *     public class CityLocation {
+ *         public static final ColumnTable<String> CITY_NAME = new MyColumn<>("CITY_NAME",
String.class, "City name");
+ *         public static final ColumnTable<Float>  LATITUDE  = new MyColumn<>("LATITUDE",
 Float.class,  "Latitude");
+ *         public static final ColumnTable<Float>  LONGITUDE = new MyColumn<>("LONGITUDE",
Float.class,  "Longitude");
+ *
+ *         private static final class MyColumn<V> extends TableColumn<V> implements
Serializable {
+ *             private final String field;
+ *
+ *             private MyColumn(String field, Class<V> type, CharSequence header) {
+ *                 super(type, header);
+ *                 this.field = field;
+ *             }
+ *
+ *             private Object readResolve() throws InvalidObjectException {
+ *                 try {
+ *                     return CityLocation.class.getField(field).get(null);
+ *                 } catch (Exception cause) { // Many exceptions, including unchecked ones.
+ *                     InvalidObjectException e = new InvalidObjectException(cause.toString());
+ *                     e.initCause(cause);
+ *                     throw e;
+ *                 }
+ *             }
+ *         }
+ *     }
+ * }
  *
- * <p>This base class is not {@linkplain Serializable serializable}. However the pre-defined
- * constants defined in this class are serializable. Developers who need custom serializable
- * columns are encouraged to create their own subclass and resolve to the singleton instance
- * on deserialization.</p>
+ * The constants defined in this class use a similar approach for providing serialization
support.
  *
  * @param <V> Base type of all values in the column identified by this instance.
  *
@@ -76,7 +110,6 @@ public class TableColumn<V> implements C
 
     /**
      * Frequently-used constant for a column of object types.
-     * The values are instances of {@link Class}.
      */
     @SuppressWarnings("unchecked")
     public static final TableColumn<Class<?>> TYPE = new Constant<>("TYPE",
@@ -173,22 +206,8 @@ public class TableColumn<V> implements C
      * Invoked on deserialization for creating an initially empty instance.
      * This constructor has {@code protected} visibility only because the Java deserialization
      * mechanism requires so; this constructor shall not be invoked in any other context.
-     *
-     * <p>Subclasses are responsible for resolving the deserialized instance to a singleton
-     * instance. This can be done by the following method, which assume that the subclass
-     * declares a public static field named {@code fieldName}:</p>
-     *
-     * {@preformat java
-     *     private Object readResolve() throws InvalidObjectException {
-     *         try {
-     *             return getClass().getField(fieldName).get(null);
-     *         } catch (Exception cause) { // Many exceptions, including unchecked ones.
-     *             InvalidObjectException e = new InvalidObjectException(cause.toString());
-     *             e.initCause(cause);
-     *             throw e;
-     *         }
-     *     }
-     * }
+     * See the <cite>Identity comparisons and serialization</cite> section in
the class
+     * javadoc for more information.
      */
     protected TableColumn() {
         type = null;
@@ -237,9 +256,11 @@ public class TableColumn<V> implements C
 
     /**
      * Returns a string representation of this table column.
+     * The default implementation returns the {@linkplain #getHeader() header}
+     * in its default locale.
      */
     @Override
     public String toString() {
-        return getHeader().toString(null);
+        return String.valueOf(getHeader());
     }
 }

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
Thu Nov 22 08:57:27 2012
@@ -20,10 +20,46 @@ import java.util.List;
 
 
 /**
- * The root of a tree of nodes, together with the definition of table columns.
- * The {@link #getColumns()} method gives the list of all columns that can be found
- * in a {@code TreeTable}. Usually some or all of those columns are also available as
- * {@link TableColumn} constants defined in {@link TreeTables}.
+ * Defines the structure (list of columns) of a table and provides the root of the tree
+ * containing the data. {@code TreeTable} can be seen as a table in which the first
+ * column contains a tree. Every row in this table is a {@link Node} instance, and each
+ * node can have an arbitrary number of {@linkplain Node#getChildren() children} nodes.
+ *
+ * <p>Below is an example of what a two-columns {@code TreeTable} instance may look
like
+ * when {@linkplain TreeTableFormat formatted as a text}:</p>
+ *
+ * {@preformat text
+ *   Citation
+ *   ├───Title……………………………………………………………
Open Geospatial Consortium
+ *   ├───Presentation Forms…………………………
document digital
+ *   ├───Cited Responsible Parties
+ *   │   ├───Organisation Name…………………
Open Geospatial Consortium
+ *   │   ├───Role……………………………………………………
resource provider
+ *   │   └───Contact Info
+ *   │       └───Online Resource
+ *   │           ├───Linkage………………………
http://www.opengeospatial.org/
+ *   │           └───Function……………………
information
+ *   └───Identifiers
+ *       └───Code……………………………………………………
OGC
+ * }
+ *
+ * <p>In many cases, the columns are known in advance as hard-coded static constants.
+ * Those column constants are typically documented close to the class producing the
+ * {@code TreeTable} instance. Using directly those static constants provides type
+ * safety, as in the following example:</p>
+ *
+ * {@preformat java
+ *     TreeTable table = ...; // Put here a TreeTable instance.
+ *     TreeTable.Node node = table.getRoot();
+ *     CharSequence   name = node.getValue(TableColumn.NAME);
+ *     Class<?>       type = node.getValue(TableColumn.TYPE);
+ * }
+ *
+ * In the above example, the type of value returned by the {@link Node#getValue(TableColumn)}
+ * method is determined by the column constant. However this approach is possible only when
+ * the table structure is known in advance. If a method needs to work with arbitrary tables,
+ * then that method can get the list of columns by a call to {@link #getColumns()}. However
+ * this column list does not provide the above type-safety.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
@@ -40,6 +76,7 @@ public interface TreeTable {
      * @return The union of all table columns in every tree node.
      *
      * @see Node#getValue(TableColumn)
+     * @see Node#setValue(TableColumn, Object)
      */
     List<TableColumn<?>> getColumns();
 
@@ -84,6 +121,11 @@ 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 added or removed to the list.</p>
+         *
          * @return The parent, or {@code null} if none.
          * @category tree
          */
@@ -93,6 +135,12 @@ public interface TreeTable {
          * 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.
+         * This allows addition or removal of child nodes as below:
+         *
+         * {@preformat java
+         *     TreeTable.Node newNode = new ...; // Create a new node here.
+         *     parent.getChildren().add(newNode);
+         * }
          *
          * @return The children, or an empty list if none.
          * @category tree

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
Thu Nov 22 08:57:27 2012
@@ -54,6 +54,11 @@ public final class Errors extends Indexe
         }
 
         /**
+         * Can not clone an object of type ‘{0}’.
+         */
+        public static final int CloneNotSupported_1 = 42;
+
+        /**
          * Value “{0}” is duplicated.
          */
         public static final int DuplicatedValue_1 = 38;

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
Thu Nov 22 08:57:27 2012
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+CloneNotSupported_1             = Can not clone an object of type \u2018{0}\u2019.
 DuplicatedValue_1               = Value \u201c{0}\u201d is duplicated.
 ElementAlreadyPresent_1         = Element \u201c{0}\u201d is already present.
 EmptyArgument_1                 = Argument \u2018{0}\u2019 shall not be empty.

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Thu Nov 22 08:57:27 2012
@@ -14,6 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+CloneNotSupported_1             = Un objet de type \u2018{0}\u2019 ne peut pas \u00eatre
clon\u00e9.
 DuplicatedValue_1               = La valeur \u201c{0}\u201d est dupliqu\u00e9e.
 ElementAlreadyPresent_1         = L\u2019\u00e9lement \u201c{0}\u201d est d\u00e9j\u00e0
pr\u00e9sent.
 EmptyArgument_1                 = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre vide.

Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
(original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
Thu Nov 22 08:57:27 2012
@@ -142,6 +142,25 @@ public final strictfp class DefaultTreeT
     }
 
     /**
+     * Tests {@link DefaultTreeTable#clone()}.
+     * This will also indirectly tests {@link DefaultTreeTable#equals(Object)}.
+     *
+     * <p>This method is part of a chain.
+     * The previous method is {@link #testNodeDisplacement(TreeTable.Node)}.</p>
+     *
+     * @throws CloneNotSupportedException Should never happen.
+     */
+    @TestStep
+    private void testClone(final DefaultTreeTable table) throws CloneNotSupportedException
{
+        final TreeTable newTable = table.clone();
+        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");
+        assertFalse("newTable.equals(table)", newTable.equals(table));
+    }
+
+    /**
      * Tests {@link DefaultTreeTable} serialization.
      *
      * <p>This method is part of a chain.
@@ -160,12 +179,15 @@ public final strictfp class DefaultTreeT
      * with the original object.
      *
      * <p>This test is actually a chain of {@link TestStep} methods.</p>
+     *
+     * @throws CloneNotSupportedException If the {@link DefaultTreeTable#clone()} method
failed.
      */
     @Test
-    public void testTreeTableCreation() {
+    public void testTreeTableCreation() throws CloneNotSupportedException {
         final DefaultTreeTable table = testTableCreation();
         final TreeTable.Node   root  = testNodeCreation(table);
         testNodeDisplacement(root);
+        testClone(table);
         testSerialization(table);
     }
 

Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java?rev=1412454&r1=1412453&r2=1412454&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
(original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
Thu Nov 22 08:57:27 2012
@@ -39,22 +39,15 @@ import static org.apache.sis.util.collec
 })
 public final strictfp class TreeTableFormatTest extends TestCase {
     /**
-     * Creates a node with a single column for object names.
-     */
-    private static DefaultTreeTable.Node createNode(final CharSequence name) {
-        return new DefaultTreeTable.Node(NAME_MAP, new CharSequence[] {name});
-    }
-
-    /**
      * Tests the formatting as a tree, with control on the indentation.
      */
     @Test
     public void testTreeFormat() {
-        final DefaultTreeTable.Node root   = createNode("Node #1");
-        final DefaultTreeTable.Node branch = createNode("Node #2");
+        final DefaultTreeTable.Node root   = new DefaultTreeTable.Node("Node #1");
+        final DefaultTreeTable.Node branch = new DefaultTreeTable.Node("Node #2");
         root.getChildren().add(branch);
-        root.getChildren().add(createNode("Node #3"));
-        branch.getChildren().add(createNode("Node #4"));
+        root.getChildren().add(new DefaultTreeTable.Node("Node #3"));
+        branch.getChildren().add(new DefaultTreeTable.Node("Node #4"));
 
         final TreeTableFormat tf = new TreeTableFormat(null, null);
         tf.setVerticalLinePosition(2);



Mime
View raw message