Author: oheger
Date: Mon Nov 26 20:39:40 2012
New Revision: 1413819

URL: http://svn.apache.org/viewvc?rev=1413819&view=rev
Log:
[CONFIGURATION-517] Added methods to HierarchicalConfiguration for retrieving 
sub configurations for all child elements of a given key.

Modified:
    commons/proper/configuration/trunk/src/changes/changes.xml
    
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/BaseHierarchicalConfiguration.java
    
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/HierarchicalConfiguration.java
    
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ImmutableHierarchicalConfiguration.java
    
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/TestHierarchicalConfiguration.java

Modified: commons/proper/configuration/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/changes/changes.xml?rev=1413819&r1=1413818&r2=1413819&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/changes/changes.xml (original)
+++ commons/proper/configuration/trunk/src/changes/changes.xml Mon Nov 26 
20:39:40 2012
@@ -27,6 +27,10 @@
   <body>
     <release version="2.0" date="in SVN"
       description="TBD">
+      <action dev="oheger" type="add" issue="CONFIGURATION-517">
+        Hierarchical configurations now provide methods to obtain sub
+        configurations for all child elements of a given key.
+      </action>
       <action dev="oheger" type="add" issue="CONFIGURATION-514">
         Bean declarations now support constructor invocations.
       </action>

Modified: 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/BaseHierarchicalConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/BaseHierarchicalConfiguration.java?rev=1413819&r1=1413818&r2=1413819&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/BaseHierarchicalConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/BaseHierarchicalConfiguration.java
 Mon Nov 26 20:39:40 2012
@@ -224,6 +224,14 @@ public class BaseHierarchicalConfigurati
     }
 
     /**
+     * {@inheritDoc} This implementation just returns the name of the root 
node.
+     */
+    public String getRootElementName()
+    {
+        return getRootNode().getName();
+    }
+
+    /**
      * Returns the default expression engine.
      *
      * @return the default expression engine
@@ -629,14 +637,42 @@ public class BaseHierarchicalConfigurati
     public List<ImmutableHierarchicalConfiguration> immutableConfigurationsAt(
             String key)
     {
-        List<SubnodeConfiguration> subs = configurationsAt(key);
-        List<ImmutableHierarchicalConfiguration> res =
-                new ArrayList<ImmutableHierarchicalConfiguration>(subs.size());
-        for (SubnodeConfiguration sub : subs)
+        return toImmutable(configurationsAt(key));
+    }
+
+    /**
+     * {@inheritDoc} This implementation resolves the node(s) selected by the
+     * given key. If not a single node is selected, an empty list is returned.
+     * Otherwise, sub configurations for each child of the node are created.
+     */
+    public List<SubnodeConfiguration> childConfigurationsAt(String key)
+    {
+        List<ConfigurationNode> nodes = fetchNodeList(key);
+        if (nodes.size() != 1)
         {
-            res.add(ConfigurationUtils.unmodifiableConfiguration(sub));
+            return Collections.emptyList();
         }
-        return res;
+
+        ConfigurationNode parent = nodes.get(0);
+        List<SubnodeConfiguration> subs =
+                new ArrayList<SubnodeConfiguration>(parent.getChildrenCount());
+        for (ConfigurationNode c : parent.getChildren())
+        {
+            subs.add(createSubnodeConfiguration(c));
+        }
+        return subs;
+    }
+
+    /**
+     * {@inheritDoc} This implementation first delegates to
+     * {@code childConfigurationsAt()} to create a list of mutable child
+     * configurations. Then a list with immutable wrapper configurations is
+     * created.
+     */
+    public List<ImmutableHierarchicalConfiguration> 
immutableChildConfigurationsAt(
+            String key)
+    {
+        return toImmutable(childConfigurationsAt(key));
     }
 
     /**
@@ -1073,6 +1109,24 @@ public class BaseHierarchicalConfigurati
     }
 
     /**
+     * Creates a list with immutable configurations from the given input list.
+     *
+     * @param subs a list with mutable configurations
+     * @return a list with corresponding immutable configurations
+     */
+    private static List<ImmutableHierarchicalConfiguration> toImmutable(
+            List<? extends HierarchicalConfiguration> subs)
+    {
+        List<ImmutableHierarchicalConfiguration> res =
+                new ArrayList<ImmutableHierarchicalConfiguration>(subs.size());
+        for (HierarchicalConfiguration sub : subs)
+        {
+            res.add(ConfigurationUtils.unmodifiableConfiguration(sub));
+        }
+        return res;
+    }
+
+    /**
      * A specialized visitor that checks if a node is defined.
      * &quot;Defined&quot; in this terms means that the node or at least one of
      * its sub nodes is associated with a value.

Modified: 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/HierarchicalConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/HierarchicalConfiguration.java?rev=1413819&r1=1413818&r2=1413819&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/HierarchicalConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/HierarchicalConfiguration.java
 Mon Nov 26 20:39:40 2012
@@ -173,6 +173,18 @@ public interface HierarchicalConfigurati
     List<SubnodeConfiguration> configurationsAt(String key);
 
     /**
+     * Returns a list with sub configurations for all child nodes of the node
+     * selected by the given key. This method works like
+     * {@link #immutableChildConfigurationsAt(String)}, but returns a list with
+     * {@code SubnodeConfiguration} objects.
+     *
+     * @param key the key for selecting the desired parent node
+     * @return a collection with {@code SubnodeConfiguration} objects for all
+     *         child nodes of the selected parent node
+     */
+    List<SubnodeConfiguration> childConfigurationsAt(String key);
+
+    /**
      * Removes all values of the property with the given name and of keys that
      * start with this name. So if there is a property with the key
      * &quot;foo&quot; and a property with the key &quot;foo.bar&quot;, a call

Modified: 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ImmutableHierarchicalConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ImmutableHierarchicalConfiguration.java?rev=1413819&r1=1413818&r2=1413819&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ImmutableHierarchicalConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/ImmutableHierarchicalConfiguration.java
 Mon Nov 26 20:39:40 2012
@@ -62,6 +62,18 @@ public interface ImmutableHierarchicalCo
     int getMaxIndex(String key);
 
     /**
+     * Returns the name of the root element of this configuration. This
+     * information may be of use in some cases, e.g. for sub configurations
+     * created using the {@code immutableConfigurationsAt()} method. The exact
+     * meaning of the string returned by this method is specific to a concrete
+     * implementation. For instance, an XML configuration might return the name
+     * of the document element.
+     *
+     * @return the name of the root element of this configuration
+     */
+    String getRootElementName();
+
+    /**
      * <p>
      * Returns an immutable hierarchical configuration object that wraps the
      * configuration node specified by the given key. This method provides an
@@ -128,4 +140,20 @@ public interface ImmutableHierarchicalCo
      * configuration represents one of the nodes selected by the passed in key
      */
     List<ImmutableHierarchicalConfiguration> immutableConfigurationsAt(String 
key);
+
+    /**
+     * Returns a list of immutable configurations for all direct child elements
+     * of the node selected by the given key. With this method it is possible 
to
+     * inspect the content of a hierarchical structure; all children of a given
+     * node can be queried without having to know their exact names. If the
+     * passed in key does not point to a single node, an empty list is 
returned.
+     * This is also the result if the node referred to by the key does not have
+     * child elements.
+     *
+     * @param key the key for selecting the desired parent node
+     * @return a collection with immutable configurations for all child nodes 
of
+     *         the selected parent node
+     */
+    List<ImmutableHierarchicalConfiguration> immutableChildConfigurationsAt(
+            String key);
 }

Modified: 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/TestHierarchicalConfiguration.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/TestHierarchicalConfiguration.java?rev=1413819&r1=1413818&r2=1413819&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/TestHierarchicalConfiguration.java
 (original)
+++ 
commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/TestHierarchicalConfiguration.java
 Mon Nov 26 20:39:40 2012
@@ -1080,6 +1080,64 @@ public class TestHierarchicalConfigurati
     }
 
     /**
+     * Tests whether immutable configurations for the children of a given node
+     * can be queried.
+     */
+    @Test
+    public void testImmutableChildConfigurationsAt()
+    {
+        List<ImmutableHierarchicalConfiguration> children =
+                config.immutableChildConfigurationsAt("tables.table(0)");
+        assertEquals("Wrong number of elements", 2, children.size());
+        ImmutableHierarchicalConfiguration c1 = children.get(0);
+        assertEquals("Wrong name (1)", "name", c1.getRootElementName());
+        assertEquals("Wrong table name", tables[0], c1.getString(null));
+        ImmutableHierarchicalConfiguration c2 = children.get(1);
+        assertEquals("Wrong name (2)", "fields", c2.getRootElementName());
+        assertEquals("Wrong field name", fields[0][0],
+                c2.getString("field(0).name"));
+    }
+
+    /**
+     * Tests whether sub configurations for the children of a given node can be
+     * queried.
+     */
+    @Test
+    public void testChildConfigurationsAt()
+    {
+        List<SubnodeConfiguration> children =
+                config.childConfigurationsAt("tables.table(0)");
+        assertEquals("Wrong number of elements", 2, children.size());
+        SubnodeConfiguration sub = children.get(0);
+        String newTabName = "otherTabe";
+        sub.setProperty(null, newTabName);
+        assertEquals("Table name not changed", newTabName,
+                config.getString("tables.table(0).name"));
+    }
+
+    /**
+     * Tests the result of childConfigurationsAt() if the key selects multiple
+     * nodes.
+     */
+    @Test
+    public void testChildConfigurationsAtNoUniqueKey()
+    {
+        assertTrue("Got children", config.childConfigurationsAt("tables.table")
+                .isEmpty());
+    }
+
+    /**
+     * Tests the result of childConfigurationsAt() if the key does not point to
+     * an existing node.
+     */
+    @Test
+    public void testChildConfigurationsAtNotFound()
+    {
+        assertTrue("Got children",
+                config.childConfigurationsAt("not.existing.key").isEmpty());
+    }
+
+    /**
      * Helper method for testing the getKeys(String) method.
      *
      * @param prefix the key to pass into getKeys()


Reply via email to