You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2012/11/22 09:57:28 UTC
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/
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);