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/14 03:36:19 UTC

svn commit: r1409062 - in /sis/branches/JDK7/sis-utility/src: main/java/org/apache/sis/internal/util/ main/java/org/apache/sis/util/collection/ test/java/org/apache/sis/test/ test/java/org/apache/sis/test/suite/ test/java/org/apache/sis/util/collection/

Author: desruisseaux
Date: Wed Nov 14 02:36:18 2012
New Revision: 1409062

URL: http://svn.apache.org/viewvc?rev=1409062&view=rev
Log:
Added a test case for DefaultTreeTable.

Added:
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java   (with props)
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java   (with props)
Modified:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/ColumnConstant.java
    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/TreeNodeList.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/ColumnConstant.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/ColumnConstant.java?rev=1409062&r1=1409061&r2=1409062&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/ColumnConstant.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/ColumnConstant.java Wed Nov 14 02:36:18 2012
@@ -101,6 +101,14 @@ public final class ColumnConstant<T> imp
     }
 
     /**
+     * Returns the name of the field declaring this constant.
+     */
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    /**
      * Invoked on deserialization for resolving this instance to one of the predefined constants.
      *
      * @return One of the predefined constants.

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=1409062&r1=1409061&r2=1409062&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 Wed Nov 14 02:36:18 2012
@@ -179,7 +179,8 @@ public class DefaultTreeTable implements
     public void setRoot(final TreeTable.Node root) {
         ArgumentChecks.ensureNonNull("root", root);
         if (root instanceof Node) {
-            if (columnIndex.keySet().containsAll(((Node) root).columnIndex.keySet())) {
+            final Map<TableColumn<?>,Integer> other = ((Node) root).columnIndex;
+            if (other != columnIndex && !columnIndex.keySet().containsAll(other.keySet())) {
                 throw new IllegalArgumentException(Errors.format(Errors.Keys.InconsistentTableColumns));
             }
         }
@@ -286,6 +287,10 @@ public class DefaultTreeTable implements
          * 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.
          *
+         * <p>This method does not set the new node as the root of the given table. If desired, it
+         * is the caller responsibility to {@linkplain DefaultTreeTable#setRoot set the table root
+         * node}.</p>
+         *
          * @param table The table for which this node is created.
          */
         public Node(final TreeTable table) {
@@ -300,15 +305,23 @@ public class DefaultTreeTable implements
         }
 
         /**
-         * Creates a new node with the given parent. The new node will be able to store
-         * values for the same columns than the parent node.
+         * Creates a new node with the given parent. The new node is added to the parent
+         * {@linkplain #getChildren() list of children} at the given index. The new node
+         * will be able to store values for the same columns than the parent node.
          *
          * @param parent The parent of the new node.
+         * @param index  The index where to add the new node in the parent list of children,
+         *               or -1 for adding the new node at the end of the list.
          */
-        public Node(final Node parent) {
+        public Node(final Node parent, int index) {
             ArgumentChecks.ensureNonNull("parent", parent);
             this.parent = parent;
             columnIndex = parent.columnIndex;
+            final TreeNodeList addTo = (TreeNodeList) parent.getChildren();
+            if (index < 0) {
+                index = addTo.size();
+            }
+            addTo.addChild(index, this);
         }
 
         /**
@@ -317,7 +330,7 @@ public class DefaultTreeTable implements
          * added as a child of another {@code Node} instance.
          */
         @Override
-        public TreeTable.Node getParent() {
+        public final TreeTable.Node getParent() {
             return parent;
         }
 
@@ -327,7 +340,8 @@ public class DefaultTreeTable implements
          */
         final void setParent(final TreeTable.Node node) {
             if (node instanceof Node) {
-                if (((Node) node).columnIndex.keySet().containsAll(columnIndex.keySet())) {
+                final Map<TableColumn<?>,Integer> other = ((Node) node).columnIndex;
+                if (other != columnIndex && !other.keySet().containsAll(columnIndex.keySet())) {
                     throw new IllegalArgumentException(Errors.format(Errors.Keys.InconsistentTableColumns));
                 }
             }
@@ -339,8 +353,12 @@ public class DefaultTreeTable implements
          * {@linkplain #getParent() parent} reference of any {@code Node} instance added to
          * ore removed from this list.
          */
+        /* 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
+         * cast will need to be replaced by an "instanceof" check.
+         */
         @Override
-        public List<TreeTable.Node> getChildren() {
+        public final List<TreeTable.Node> getChildren() {
             if (children == null) {
                 children = new Children(this);
             }
@@ -410,5 +428,33 @@ public class DefaultTreeTable implements
         public Object getUserObject() {
             return null;
         }
+
+        /**
+         * Returns a string representation of this node, for identification in error message
+         * or in debugger.
+         *
+         * @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];
+                    if (value instanceof CharSequence) {
+                        return value.toString();
+                    }
+                }
+            }
+            String name = getClass().getSimpleName();
+            if (parent != null) {
+                name = name + '-' + parent.getChildren().indexOf(this);
+            }
+            return name;
+        }
     }
 }

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java?rev=1409062&r1=1409061&r2=1409062&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeNodeList.java Wed Nov 14 02:36:18 2012
@@ -216,6 +216,15 @@ abstract class TreeNodeList extends Abst
         } else {
             setParentOf(node, THIS);
         }
+        addChild(index, node);
+    }
+
+    /**
+     * Adds the given node at the given index in this list, without any check for the parent.
+     * The {@linkplain TreeTable.Node#getParent() parent} of the given node shall already be
+     * set to {@code this} before this method is invoked.
+     */
+    final void addChild(final int index, final TreeTable.Node node) {
         if (children == null) {
             children = new TreeTable.Node[4];
         } else if (size == children.length) {

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=1409062&r1=1409061&r2=1409062&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 Wed Nov 14 02:36:18 2012
@@ -97,7 +97,7 @@ public interface TreeTable {
          * @return The children, or an empty list if none.
          * @category tree
          */
-        List<? extends Node> getChildren();
+        List<Node> getChildren();
 
         /**
          * Returns the value in the given column, or {@code null} if none.

Added: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java?rev=1409062&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java (added)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java Wed Nov 14 02:36:18 2012
@@ -0,0 +1,43 @@
+/*
+ * 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.test;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * A test method producing an object to be used by another test method.
+ * Such methods are annotated with this {@code TestStep} annotation instead than the
+ * JUnit {@link org.junit.Test} one. However in current implementation, those methods
+ * must be explicitely invoked from another method. This is because JUnit 4 does not
+ * support tests chaining, so this annotation is currently used only for documentation
+ * purpose.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface TestStep {
+}

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/TestStep.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1409062&r1=1409061&r2=1409062&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java (original)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java Wed Nov 14 02:36:18 2012
@@ -51,6 +51,7 @@ import org.junit.runners.Suite;
   org.apache.sis.util.collection.CacheTest.class,
   org.apache.sis.util.collection.DerivedSetTest.class,
   org.apache.sis.util.collection.DerivedMapTest.class,
+  org.apache.sis.util.collection.DefaultTreeTableTest.class,
 
   // GeoAPI most basic types.
   org.apache.sis.util.type.TypesTest.class,

Added: 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=1409062&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java (added)
+++ sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java Wed Nov 14 02:36:18 2012
@@ -0,0 +1,149 @@
+/*
+ * 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.util.collection;
+
+import java.util.List;
+import org.junit.Test;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.test.TestStep;
+
+import static org.junit.Assert.*;
+import static org.apache.sis.test.TestUtilities.getSingleton;
+import static org.apache.sis.internal.util.ColumnConstant.*;
+
+
+/**
+ * Tests the {@link DefaultTreeTable} class.
+ * This will also test indirectly the {@link TreeNodeList} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+public final strictfp class DefaultTreeTableTest extends TestCase {
+    /**
+     * Tests the creation of an {@link DefaultTreeTable} with initially no root node.
+     * The columns are {@code NAME} and {@code TYPE}.
+     *
+     * <p>This method is part of a chain.
+     * The next method is {@link #testNodeCreation(DefaultTreeTable)}.</p>
+     *
+     * @return The created table, for chaining with methods testing the next step
+     *         after this one.
+     */
+    @TestStep
+    private static DefaultTreeTable testTableCreation() {
+        final DefaultTreeTable table = new DefaultTreeTable(NAME, TYPE);
+        assertEquals("Number of columns:",      2,                  table.columnIndex.size());
+        assertEquals("Index of first column:",  Integer.valueOf(0), table.columnIndex.get(NAME));
+        assertEquals("Index of second column:", Integer.valueOf(1), table.columnIndex.get(TYPE));
+        assertArrayEquals(new TableColumn<?>[] {NAME, TYPE}, table.getColumns().toArray());
+        try {
+            assertNull(table.getRoot());
+            fail("Expected an IllegalStateException.");
+        } catch (IllegalStateException e) {
+            // This is the expected exception.
+            assertTrue(e.getMessage().contains("root"));
+        }
+        return table;
+    }
+
+    /**
+     * Tests the creation of children nodes.
+     * The root node has only one child, which itself has only one child.
+     *
+     * <p>This method is part of a chain.
+     * The previous method is {@link #testTableCreation()} and
+     * the next method is {@link #testNodeDisplacement(TreeTable.Node)}.</p>
+     *
+     * @param  table An initially empty table where to set the root.
+     * @return The root node produced by this method.
+     */
+    @TestStep
+    private static DefaultTreeTable.Node testNodeCreation(final DefaultTreeTable table) {
+        /*
+         * Create a root node with an initially empty list of children.
+         */
+        final DefaultTreeTable.Node root = new DefaultTreeTable.Node(table);
+        assertSame("Internal table sharing:", table.columnIndex, root.columnIndex);
+        assertTrue("Initial children list:",  root.getChildren().isEmpty());
+        table.setRoot(root);
+        /*
+         * Create a first child node, which should be added automatically
+         * to the root list of children.
+         */
+        final DefaultTreeTable.Node node1 = new DefaultTreeTable.Node(root, -1);
+        assertSame("Internal table sharing:",  table.columnIndex, node1.columnIndex);
+        assertTrue("Initial children list:",   node1.getChildren().isEmpty());
+        assertSame("Specified parent:",        root, node1.getParent());
+        assertSame("Children list after add:", node1, getSingleton(root.getChildren()));
+        /*
+         * Create a child of the previous child.
+         */
+        final DefaultTreeTable.Node node2 = new DefaultTreeTable.Node(node1, 0);
+        assertSame("Internal table sharing:",    table.columnIndex, node2.columnIndex);
+        assertTrue("Initial children list:",     node2.getChildren().isEmpty());
+        assertSame("Specified parent:",          node1, node2.getParent());
+        assertSame("Children list after add:",   node2, getSingleton(node1.getChildren()));
+        assertSame("Independent children list:", node1, getSingleton(root.getChildren()));
+        /*
+         * For chaining with next tests.
+         */
+        assertSame(root, table.getRoot());
+        return root;
+    }
+
+    /**
+     * Tests the displacement of nodes, in particular ensures that the parent is updated.
+     *
+     * <p>This method is part of a chain.
+     * The previous method is {@link #testNodeCreation(DefaultTreeTable)}.</p>
+     *
+     * @param root The root node where to move children.
+     */
+    @TestStep
+    private static void testNodeDisplacement(final TreeTable.Node root) {
+        final List<TreeTable.Node> rootChildren, nodeChildren;
+        final TreeTable.Node node1 = getSingleton(rootChildren = root .getChildren());
+        final TreeTable.Node node2 = getSingleton(nodeChildren = node1.getChildren());
+        try {
+            assertTrue(rootChildren.add(node2));
+            fail("Should not be allowed to add a child before we removed it from its previous parent.");
+        } catch (IllegalArgumentException e) {
+            // This is the expected exception.
+            assertTrue(e.getMessage().contains("Node-0"));
+        }
+        assertSame("Initial parent:", node1,       node2.getParent());
+        assertTrue(                                nodeChildren.remove(node2));
+        assertTrue("Children list after removal:", nodeChildren.isEmpty());
+        assertNull("Parent after removal:",        node2.getParent());
+        assertTrue(                                rootChildren.add(node2));
+        assertSame("Parent after add:", root,      node2.getParent());
+        assertArrayEquals("Children list after add:",
+                new TreeTable.Node[] {node1, node2}, rootChildren.toArray());
+    }
+
+    /**
+     * Tests the creation of a tree table with a few nodes, and tests the displacement of a node
+     * from one branch to another. This test is actually a chain of {@link TestStep} methods.
+     */
+    @Test
+    public void testTreeTableCreation() {
+        testNodeDisplacement(testNodeCreation(testTableCreation()));
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain