sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1478202 - in /sis/branches/JDK7: sis-metadata/src/main/java/org/apache/sis/metadata/ sis-metadata/src/test/java/org/apache/sis/metadata/ sis-metadata/src/test/java/org/apache/sis/test/suite/ sis-utility/src/main/java/org/apache/sis/util/ s...
Date Wed, 01 May 2013 21:52:06 GMT
Author: desruisseaux
Date: Wed May  1 21:52:06 2013
New Revision: 1478202

URL: http://svn.apache.org/r1478202
Log:
Improved tree table formatting and added more tests.

Added:
    sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
  (with props)
Modified:
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
    sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
    sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/CharSequences.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/TreeTableFormat.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java
    sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java

Modified: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java?rev=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -31,6 +31,7 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
@@ -116,7 +117,7 @@ class MetadataTreeNode implements TreeTa
      *
      * @see #getName()
      */
-    private transient String name;
+    private transient CharSequence name;
 
     /**
      * The children of this node, or {@code null} if not yet computed. If and only if the
node
@@ -153,18 +154,30 @@ class MetadataTreeNode implements TreeTa
     }
 
     /**
+     * Returns the UML identifier defined by the standard. The default implementation is
suitable
+     * only for the root node, since it returns the class identifier. Subclasses must override
in
+     * order to return the property identifier instead.
+     */
+    String getIdentifier() {
+        final Class<?> type = table.standard.getInterface(metadata.getClass());
+        final String id = Types.getStandardName(type);
+        return (id != null) ? id : Classes.getShortName(type);
+    }
+
+    /**
      * Gets the name of this node. The name shall be stable, since it will be cached by the
caller.
      * The default implementation is suitable only for the root node - subclasses must override.
      */
-    String getName() {
-        final Class<?> type = metadata.getClass();
-        final String name = Types.getStandardName(type);
-        return (name != null) ? name : Classes.getShortName(type);
+    CharSequence getName() {
+        return Classes.getShortClassName(metadata);
     }
 
     /**
      * Appends an identifier for this node in the given buffer, for {@link #toString()} implementation.
-     * The default implementation is suitable only for the root node - subclasses must override.
+     * The appended value is similar to the value returned by {@link #getIdentifier()} (except
for the
+     * root node), but may contains additional information like the index in a collection.
+     *
+     * <p>The default implementation is suitable only for the root node - subclasses
must override.</p>
      */
     void appendIdentifier(final StringBuilder buffer) {
         buffer.append(Classes.getShortClassName(metadata));
@@ -253,6 +266,14 @@ class MetadataTreeNode implements TreeTa
         }
 
         /**
+         * The property identifier to be returned in the {@link TableColumn#IDENTIFIER} cells.
+         */
+        @Override
+        final String getIdentifier() {
+            return accessor.name(indexInData, KeyNamePolicy.UML_IDENTIFIER);
+        }
+
+        /**
          * Appends an identifier for this node in the given buffer, for {@link #toString()}
implementation.
          */
         @Override
@@ -268,8 +289,8 @@ class MetadataTreeNode implements TreeTa
          * node for each element in a collection.
          */
         @Override
-        String getName() {
-            return CharSequences.camelCaseToSentence(accessor.name(indexInData, KeyNamePolicy.UML_IDENTIFIER)).toString();
+        CharSequence getName() {
+            return CharSequences.camelCaseToSentence(getIdentifier()).toString();
         }
 
         /**
@@ -348,6 +369,22 @@ class MetadataTreeNode implements TreeTa
         }
 
         /**
+         * Appends the index of this property, if there is more than one.
+         */
+        @Override
+        CharSequence getName() {
+            CharSequence name = super.getName();
+            final Collection<?> values = (Collection<?>) super.getUserObject();
+            if (values != null) {
+                final int size = values.size();
+                if (size >= 2) {
+                    name = Vocabulary.formatInternational(Vocabulary.Keys.Of_3, name, indexInList+1,
size);
+                }
+            }
+            return name;
+        }
+
+        /**
          * Fetches the property value from the metadata object, which is expected to be a
collection,
          * then fetch the element at the index represented by this node.
          */
@@ -483,6 +520,8 @@ class MetadataTreeNode implements TreeTa
             }
         } else if (column == TableColumn.TYPE) {
             value = getElementType();
+        } else if (column == TableColumn.IDENTIFIER) {
+            value = getIdentifier();
         }
         return column.getElementType().cast(value);
     }

Modified: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java?rev=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -30,9 +30,10 @@ import org.apache.sis.internal.util.Unmo
  * The tree table is made of three columns:
  *
  * <ul>
- *   <li>{@link TableColumn#NAME}  - the metadata property name.</li>
- *   <li>{@link TableColumn#TYPE}  - the metadata element type.</li>
- *   <li>{@link TableColumn#VALUE} - the metadata property value.</li>
+ *   <li>{@link TableColumn#IDENTIFIER} - the property standard identifier.</li>
+ *   <li>{@link TableColumn#NAME}       - the property name.</li>
+ *   <li>{@link TableColumn#TYPE}       - the element type.</li>
+ *   <li>{@link TableColumn#VALUE}      - the property value.</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
@@ -50,6 +51,7 @@ final class MetadataTreeTable implements
      * The columns to be returned by {@link #getColumns()}.
      */
     static final List<TableColumn<?>> COLUMNS = UnmodifiableArrayList.wrap(new
TableColumn<?>[] {
+        TableColumn.IDENTIFIER,
         TableColumn.NAME,
         TableColumn.TYPE,
         TableColumn.VALUE

Modified: sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java?rev=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -24,8 +24,8 @@ import org.opengis.metadata.citation.Pre
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.collection.TreeTable;
-import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -52,6 +52,13 @@ import static org.apache.sis.test.TestUt
 public final strictfp class MetadataTreeChildrenTest extends TestCase {
     /**
      * Creates a shallow metadata object without collections.
+     *
+     * {@preformat text
+     *   DefaultCitation
+     *     ├─Title………………………………………………… Some title
+     *     ├─Edition…………………………………………… Some edition
+     *     └─Other citation details…… Some other details
+     * }
      */
     static DefaultCitation metadataWithoutCollections() {
         final DefaultCitation citation = new DefaultCitation("Some title");
@@ -62,6 +69,16 @@ public final strictfp class MetadataTree
 
     /**
      * Creates a shallow metadata object with singleton value in collections.
+     * This method creates the following metadata:
+     *
+     * {@preformat text
+     *   DefaultCitation
+     *     ├─Title………………………………………………… Some title
+     *     ├─Alternate title……………………… First alternate title
+     *     ├─Edition…………………………………………… Some edition
+     *     ├─Presentation form………………… Map digital
+     *     └─Other citation details…… Some other details
+     * }
      */
     static DefaultCitation metadataWithSingletonInCollections() {
         final DefaultCitation citation = metadataWithoutCollections();
@@ -71,8 +88,19 @@ public final strictfp class MetadataTree
     }
 
     /**
-     * Creates a shallow metadata object with multi-occurrences
-     * (i.e. more than one value in collections).
+     * Creates a shallow metadata object with multi-occurrences (i.e. more than one value
in collections).
+     * This method creates the following metadata:
+     *
+     * {@preformat text
+     *   DefaultCitation
+     *     ├─Title…………………………………………………………
Some title
+     *     ├─Alternate title (1 of 2)……… First alternate title
+     *     ├─Alternate title (2 of 2)……… Second alternate title
+     *     ├─Edition…………………………………………………… Some
edition
+     *     ├─Presentation form (1 of 2)… Map digital
+     *     ├─Presentation form (2 of 2)… map hardcopy
+     *     └─Other citation details…………… Some other details
+     * }
      */
     static DefaultCitation metadataWithMultiOccurrences() {
         final DefaultCitation citation = metadataWithSingletonInCollections();
@@ -82,7 +110,7 @@ public final strictfp class MetadataTree
     }
 
     /**
-     * Creates a list to be tested for the given metadata object and value policy.
+     * Creates a collection to be tested for the given metadata object and value policy.
      */
     private static MetadataTreeChildren create(final AbstractMetadata metadata, final ValueExistencePolicy
valuePolicy) {
         final MetadataStandard  standard = MetadataStandard.ISO_19115;

Added: sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java?rev=1478202&view=auto
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
(added)
+++ sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -0,0 +1,306 @@
+/*
+ * 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.metadata;
+
+import java.util.Locale;
+import org.opengis.metadata.citation.Address;
+import org.opengis.metadata.citation.Contact;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.citation.ResponsibleParty;
+import org.opengis.metadata.citation.PresentationForm;
+import org.opengis.metadata.citation.Role;
+import org.opengis.util.InternationalString;
+import org.apache.sis.metadata.iso.citation.DefaultAddress;
+import org.apache.sis.metadata.iso.citation.DefaultContact;
+import org.apache.sis.metadata.iso.citation.DefaultCitation;
+import org.apache.sis.metadata.iso.citation.DefaultResponsibleParty;
+import org.apache.sis.util.iso.SimpleInternationalString;
+import org.apache.sis.util.collection.TableColumn;
+import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link MetadataTreeNode} class.
+ * Unless otherwise specified, all tests use the {@link MetadataStandard#ISO_19115} constant.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+@DependsOn(MetadataTreeChildrenTest.class)
+public final strictfp class MetadataTreeNodeTest extends TestCase {
+    /**
+     * Creates a metadata hierarchy to be used for the tests.
+     * This method creates the following metadata:
+     *
+     * {@preformat text
+     *   DefaultCitation
+     *     ├─Title……………………………………………………………………………………
Some title
+     *     ├─Alternate title (1 of 2)………………………………… First
alternate title
+     *     ├─Alternate title (2 of 2)………………………………… Second
alternate title
+     *     ├─Edition………………………………………………………………………………
Some edition
+     *     ├─Cited responsible party (1 of 2)
+     *     │   ├─Organisation name…………………………………………
Some organisation
+     *     │   └─Role……………………………………………………………………………
Distributor
+     *     ├─Cited responsible party (2 of 2)
+     *     │   ├─Individual name………………………………………………
Some person of contact
+     *     │   ├─Contact info
+     *     │   │   └─Address
+     *     │   │       └─Electronic mail address…… Some email
+     *     │   └─Role……………………………………………………………………………
Point of contact
+     *     ├─Presentation form (1 of 2)…………………………… Map digital
+     *     ├─Presentation form (2 of 2)…………………………… map hardcopy
+     *     └─Other citation details……………………………………… Some
other details
+     * }
+     */
+    static DefaultCitation metadataWithHierarchy() {
+        final DefaultCitation citation = MetadataTreeChildrenTest.metadataWithMultiOccurrences();
+        DefaultResponsibleParty party = new DefaultResponsibleParty(Role.DISTRIBUTOR);
+        party.setOrganisationName(new SimpleInternationalString("Some organisation"));
+        citation.getCitedResponsibleParties().add(party);
+
+        // Add a second responsible party with deeper hierarchy.
+        party = new DefaultResponsibleParty(Role.POINT_OF_CONTACT);
+        party.setIndividualName("Some person of contact");
+        final DefaultContact contact = new DefaultContact();
+        final DefaultAddress address = new DefaultAddress();
+        address.getElectronicMailAddresses().add("Some email");
+        contact.setAddress(address);
+        party.setContactInfo(contact);
+        citation.getCitedResponsibleParties().add(party);
+        return citation;
+    }
+
+    /**
+     * Creates a node to be tested for the given metadata object and value policy.
+     */
+    private static MetadataTreeNode create(final AbstractMetadata metadata, final ValueExistencePolicy
valuePolicy) {
+        final MetadataStandard  standard = MetadataStandard.ISO_19115;
+        final MetadataTreeTable table    = new MetadataTreeTable(standard, metadata, valuePolicy);
+        return (MetadataTreeNode) table.getRoot();
+    }
+
+    /**
+     * Tests the properties of the root node.
+     */
+    @Test
+    public void testRootNode() {
+        final DefaultCitation citation = MetadataTreeChildrenTest.metadataWithoutCollections();
+        final MetadataTreeNode node = create(citation, ValueExistencePolicy.NON_EMPTY);
+        assertEquals("getName()",        "DefaultCitation", node.getName());
+        assertEquals("getIdentifier()",  "CI_Citation",     node.getIdentifier());
+        assertEquals("getElementType()", Citation.class,    node.getElementType());
+        assertSame  ("getUserObject()",  citation,          node.getUserObject());
+        assertFalse ("isWritable()",                        node.isWritable());
+        assertNull  ("getParent()",                         node.getParent());
+        assertFalse ("isLeaf()",                            node.isLeaf());
+
+        final MetadataTreeChildren children = (MetadataTreeChildren) node.getChildren();
+        assertSame ("children.metadata", citation, children.metadata);
+        assertFalse("children.isEmpty()", node.getChildren().isEmpty());
+        assertSame ("children.parent", node, children.iterator().next().getParent());
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getName()} on a metadata with only one entry in collections.
+     * Those names shall <em>not</em> contain numbering like "<cite>(1
of 2)</cite>".
+     */
+    @Test
+    @DependsOnMethod("testRootNode") // Because tested more basic methods than 'getValue(TableColumn)'.
+    public void testGetNameForSingleton() {
+        final DefaultCitation citation = MetadataTreeChildrenTest.metadataWithSingletonInCollections();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.NAME,
+            "DefaultCitation",
+              "Title",
+              "Alternate title",
+              "Edition",
+              "Presentation form",
+              "Other citation details");
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getName()} on a metadata with more than one entry in
collections.
+     * Those names <em>shall</em> contain numbering like "<cite>(1 of 2)</cite>".
+     */
+    @Test
+    @DependsOnMethod("testGetNameForSingleton")
+    public void testGetNameForMultiOccurrences() {
+        final DefaultCitation citation = MetadataTreeChildrenTest.metadataWithMultiOccurrences();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.NAME,
+            "DefaultCitation",
+              "Title",
+              "Alternate title (1 of 2)",
+              "Alternate title (2 of 2)",
+              "Edition",
+              "Presentation form (1 of 2)",
+              "Presentation form (2 of 2)",
+              "Other citation details");
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getName()} on a metadata with a deeper hierarchy.
+     */
+    @Test
+    @DependsOnMethod("testGetNameForMultiOccurrences")
+    public void testGetNameForHierarchy() {
+        final DefaultCitation citation = metadataWithHierarchy();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.NAME,
+            "DefaultCitation",
+              "Title",
+              "Alternate title (1 of 2)",
+              "Alternate title (2 of 2)",
+              "Edition",
+              "Cited responsible party (1 of 2)",
+                "Organisation name",
+                "Role",
+              "Cited responsible party (2 of 2)",
+                "Individual name",
+                "Contact info",
+                  "Address",
+                    "Electronic mail address",
+                "Role",
+              "Presentation form (1 of 2)",
+              "Presentation form (2 of 2)",
+              "Other citation details");
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getIdentifier()} on a metadata with a hierarchy.
+     * Those names shall <em>not</em> contain numbering like "<cite>(1
of 2)</cite>", even if the same
+     * identifiers are repeated. Those identifiers are not intended to be unique in a list
of children.
+     * The repetition of the same identifier means that they shall be part of a collection.
+     */
+    @Test
+    @DependsOnMethod("testGetNameForMultiOccurrences") // Because similar to names, which
were tested progressively.
+    public void testGetIdentifier() {
+        final DefaultCitation citation = metadataWithHierarchy();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.IDENTIFIER,
+            "CI_Citation",
+              "title",
+              "alternateTitle",
+              "alternateTitle",
+              "edition",
+              "citedResponsibleParty",
+                "organisationName",
+                "role",
+              "citedResponsibleParty",
+                "individualName",
+                "contactInfo",
+                  "address",
+                    "electronicMailAddress",
+                "role",
+              "presentationForm",
+              "presentationForm",
+              "otherCitationDetails");
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getElementType()} on a metadata with a hierarchy.
+     */
+    @Test
+    @DependsOnMethod("testGetIdentifier") // Because if identifiers are wrong, we are looking
at wrong properties.
+    public void testGetElementType() {
+        final DefaultCitation citation = metadataWithHierarchy();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.TYPE,
+            Citation.class,
+              InternationalString.class,
+              InternationalString.class,
+              InternationalString.class,
+              InternationalString.class,
+              ResponsibleParty.class,
+                InternationalString.class,
+                Role.class,
+              ResponsibleParty.class,
+                String.class,
+                Contact.class,
+                  Address.class,
+                    String.class,
+                Role.class,
+              PresentationForm.class,
+              PresentationForm.class,
+              InternationalString.class);
+    }
+
+    /**
+     * Tests {@link MetadataTreeNode#getValue(TableColumn)} for the value column.
+     */
+    @Test
+    @DependsOnMethod("testGetIdentifier") // Because if identifiers are wrong, we are looking
at wrong properties.
+    public void testGetValue() {
+        final DefaultCitation citation = metadataWithHierarchy();
+        assertColumnEquals(create(citation, ValueExistencePolicy.NON_EMPTY), TableColumn.VALUE,
+            null, // Citation
+              "Some title",
+              "First alternate title",
+              "Second alternate title",
+              "Some edition",
+              null, // ResponsibleParty
+                "Some organisation",
+                Role.DISTRIBUTOR,
+              null, // ResponsibleParty
+                "Some person of contact",
+                null, // Contact
+                  null, // Address
+                    "Some email",
+                Role.POINT_OF_CONTACT,
+              PresentationForm.MAP_DIGITAL,
+              PresentationForm.MAP_HARDCOPY,
+              "Some other details");
+    }
+
+    /**
+     * Compares the result of the given getter method invoked on the given node, then invoked
+     * on all children of that given. In the particular case of the {@link #NAME} method,
+     * international strings are replaced by unlocalized strings before comparisons.
+     *
+     * @param node     The node for which to test the children.
+     * @param column   The column from which to get a value.
+     * @param values   The expected values. The first value is the result of the getter method
+     *                 applied on the given node, and all other values are the result of
the
+     *                 getter method applied on the children, in iteration order.
+     */
+    private static void assertColumnEquals(final MetadataTreeNode node,
+            final TableColumn<?> column, final Object... values)
+    {
+        assertEquals("Missing values in the tested metadata.", values.length,
+                assertColumnEquals(node, column, values, 0));
+    }
+
+    /**
+     * Implementation of the above {@code assertGetterReturns}, to be invoked recursively.
+     */
+    private static int assertColumnEquals(final TreeTable.Node node, final TableColumn<?>
column,
+            final Object[] values, int index)
+    {
+        Object actual = node.getValue(column);
+        if (actual instanceof InternationalString) {
+            actual = ((InternationalString) actual).toString(Locale.ROOT);
+        }
+        assertEquals("values[" + index + ']', values[index++], actual);
+        for (final TreeTable.Node child : node.getChildren()) {
+            index = assertColumnEquals(child, column, values, index);
+        }
+        return index;
+    }
+}

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

Propchange: sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -43,6 +43,7 @@ import org.junit.BeforeClass;
     org.apache.sis.metadata.InformationMapTest.class,
     org.apache.sis.metadata.ValueMapTest.class,
     org.apache.sis.metadata.MetadataTreeChildrenTest.class,
+    org.apache.sis.metadata.MetadataTreeNodeTest.class,
     org.apache.sis.metadata.MetadataStandardTest.class,
     org.apache.sis.metadata.PrunerTest.class,
     org.apache.sis.metadata.iso.AllMetadataTest.class

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

Modified: sis/branches/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=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -108,6 +108,14 @@ public class TableColumn<V> implements C
             CharSequence.class, Vocabulary.Keys.Name);
 
     /**
+     * Frequently-used constant for a column of object identifiers.
+     * The column {@linkplain #getHeader() header} is "<cite>Identifier</cite>"
(eventually localized)
+     * and the column elements are instances of {@link String}.
+     */
+    public static final TableColumn<String> IDENTIFIER = new Constant<>("IDENTIFIER",
+            String.class, Vocabulary.Keys.Identifier);
+
+    /**
      * Frequently-used constant for a column of object types.
      * The column {@linkplain #getHeader() header} is "<cite>Type</cite>" (eventually
localized).
      */

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1478202&r1=1478201&r2=1478202&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] Wed May  1 21:52:06 2013
@@ -28,10 +28,13 @@ import java.text.ParsePosition;
 import java.text.ParseException;
 import java.util.regex.Matcher;
 import net.jcip.annotations.NotThreadSafe;
+import org.opengis.util.CodeList;
+import org.opengis.util.InternationalString;
 import org.apache.sis.io.LineAppender;
 import org.apache.sis.io.TableAppender;
 import org.apache.sis.io.TabularFormat;
 import org.apache.sis.io.CompoundFormat;
+import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Workaround;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
@@ -579,6 +582,12 @@ public class TreeTableFormat extends Tab
                     return;
                 }
                 text = format.format(value);
+            } else if (value instanceof InternationalString) {
+                text = ((InternationalString) value).toString(locale);
+            } else if (value instanceof CodeList<?>) {
+                text = Types.getCodeTitle((CodeList<?>) value).toString(locale);
+            } else if (value instanceof Enum<?>) {
+                text = CharSequences.upperCaseToSentence(((Enum<?>) value).name());
             } else {
                 text = String.valueOf(value);
             }

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

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

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

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

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



Mime
View raw message