You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/04/26 13:11:06 UTC

svn commit: r397175 - in /jakarta/commons/proper/configuration/trunk: conf/ src/java/org/apache/commons/configuration/ src/test/org/apache/commons/configuration/

Author: oheger
Date: Wed Apr 26 04:11:03 2006
New Revision: 397175

URL: http://svn.apache.org/viewcvs?rev=397175&view=rev
Log:
Integrated CombinedConfiguration into DefaultConfigurationBuilder

Modified:
    jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml
    jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java
    jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java

Modified: jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml?rev=397175&r1=397174&r2=397175&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml (original)
+++ jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml Wed Apr 26 04:11:03 2006
@@ -1,12 +1,27 @@
 <?xml version="1.0" encoding="ISO-8859-1" ?>
 <!-- Test configuration definition file that demonstrates complex initialization -->
 <configuration>
-  <properties fileName="test.properties" throwExceptionOnMissing="true">
+  <header>
+    <combiner>
+      <override>
+        <list-nodes>
+          <node>table</node>
+          <node>list</node>
+        </list-nodes>
+      </override>
+    </combiner>
+  </header>
+  <properties fileName="test.properties" throwExceptionOnMissing="true"
+    config-name="properties">
     <reloadingStrategy config-class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"
       refreshDelay="10000"/>
   </properties>
-  <xml fileName="test.xml">
+  <xml fileName="test.xml" config-name="xml">
     <expressionEngine config-class="org.apache.commons.configuration.tree.DefaultExpressionEngine"
       propertyDelimiter="/" indexStart="[" indexEnd="]"/>
   </xml>
+  <additional>
+    <xml config-name="combiner1" fileName="testcombine1.xml"/>
+    <xml config-name="combiner2" fileName="testcombine2.xml"/>
+  </additional>
 </configuration>

Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java?rev=397175&r1=397174&r2=397175&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java Wed Apr 26 04:11:03 2006
@@ -30,6 +30,9 @@
 import org.apache.commons.configuration.plist.PropertyListConfiguration;
 import org.apache.commons.configuration.plist.XMLPropertyListConfiguration;
 import org.apache.commons.configuration.tree.ConfigurationNode;
+import org.apache.commons.configuration.tree.NodeCombiner;
+import org.apache.commons.configuration.tree.OverrideCombiner;
+import org.apache.commons.configuration.tree.UnionCombiner;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 
 /**
@@ -57,13 +60,118 @@
  * is detected. For the default configuration classes providers are already
  * registered.
  * </p>
+ * <p>
+ * The configuration definition file has the following basic structure:
+ * </p>
+ * <p>
+ *
+ * <pre>
+ * &lt;configuration&gt;
+ *   &lt;header&gt;
+ *     &lt;!-- Optional meta information about the composite configuration --&gt;
+ *   &lt;/header&gt;
+ *   &lt;override&gt;
+ *     &lt;!-- Declarations for override configurations --&gt;
+ *   &lt;/override&gt;
+ *   &lt;additional&gt;
+ *     &lt;!-- Declarations for union configurations --&gt;
+ *   &lt;/additional&gt;
+ * &lt;/configuration&gt;
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * The name of the root element (here <code>configuration</code>) is
+ * arbitrary. There are two sections (both of them are optional) for declaring
+ * <em>override</em> and <em>additional</em> configurations. Configurations
+ * in the former section are evaluated in the order of their declaration, and
+ * properties of configurations declared earlier hide those of configurations
+ * declared later. Configurations in the latter section are combined to a union
+ * configuration, i.e. all of their properties are added to a large hierarchical
+ * configuration. Configuration declarations that occur as direct children of
+ * the root element are treated as override declarations.
+ * </p>
+ * <p>
+ * Each configuration declaration consists of a tag whose name is associated
+ * with a <code>ConfigurationProvider</code>. This can be one of the
+ * pre-defined tags like <code>properties</code>, or <code>xml</code>, or
+ * a custom tag, for which a configuration provider was registered. Attributes
+ * and sub elements with specific initialization parameters can be added. There
+ * are some reserved attributes with a special meaning that can be used in every
+ * configuration declaration:
+ * </p>
+ * <p>
+ * <table border="1">
+ * <tr>
+ * <th>Attribute</th>
+ * <th>Meaning</th>
+ * </tr>
+ * <tr>
+ * <td valign="top"><code>config-name</code></td>
+ * <td>Allows to specify a name for this configuration. This name can be used
+ * to obtain a reference to the configuration from the resulting combined
+ * configuration (see below).</td>
+ * </tr>
+ * <tr>
+ * <td valign="top"><code>config-at</code></td>
+ * <td>With this attribute an optional prefix can be specified for the
+ * properties of the corresponding configuration.</td>
+ * </tr>
+ * <tr>
+ * <td valign="top"><code>config-optional</code></td>
+ * <td>Declares a configuration as optional. This means that errors when
+ * creating the configuration are silently ignored.</td>
+ * </tr>
+ * </table>
+ * </p>
+ * <p>
+ * The optional <em>header</em> section can contain some meta data about the
+ * created configuration itself. For instance, it is possible to set further
+ * properties of the <code>NodeCombiner</code> objects used for constructing
+ * the resulting configuration.
+ * </p>
+ * <p>
+ * The configuration object returned by this builder is an instance of the
+ * <code>{@link CombinedConfiguration}</code> class. The return value of the
+ * <code>getConfiguration()</code> method can be casted to this type, and the
+ * <code>getConfiguration(boolean)</code> method directly declares
+ * <code>CombinedConfiguration</code> as return type. This allows for
+ * convenient access to the configuration objects maintained by the combined
+ * configuration (e.g. for updates of single configuration objects). It has also
+ * the advantage that the properties stored in all declared configuration
+ * objects are collected and transformed into a single hierarchical structure,
+ * which can be accessed using different expression engines.
+ * </p>
+ * <p>
+ * All declared override configurations are directly added to the resulting
+ * combined configuration. If they are given names (using the
+ * <code>config-name</code> attribute), they can directly be accessed using
+ * the <code>getConfiguration(String)</code> method of
+ * <code>CombinedConfiguration</code>. The additional configurations are
+ * alltogether added to another combined configuration, which uses a union
+ * combiner. Then this union configuration is added to the resulting combined
+ * configuration under the name defined by the <code>ADDITIONAL_NAME</code>
+ * constant.
+ * </p>
  *
  * @since 1.3
  * @author Oliver Heger
- * @version $Id$
+ * @version $Id: DefaultConfigurationBuilder.java 384601 2006-03-09 20:22:58Z
+ * oheger $
  */
-public class DefaultConfigurationBuilder extends XMLConfiguration implements ConfigurationBuilder
+public class DefaultConfigurationBuilder extends XMLConfiguration implements
+        ConfigurationBuilder
 {
+    /**
+     * Constant for the name of the additional configuration. If the
+     * configuration definition file contains an <code>additional</code>
+     * section, a special union configuration is created and added under this
+     * name to the resulting combined configuration.
+     */
+    public static final String ADDITIONAL_NAME = DefaultConfigurationBuilder.class
+            .getName()
+            + "/ADDITIONAL_CONFIG";
+
     /** Constant for the expression engine used by this builder. */
     static final XPathExpressionEngine EXPRESSION_ENGINE = new XPathExpressionEngine();
 
@@ -72,6 +180,9 @@
             .getName()
             + ".CONFIG_BEAN_FACTORY_NAME";
 
+    /** Constant for the reserved name attribute. */
+    static final String ATTR_NAME = XMLBeanDeclaration.RESERVED_PREFIX + "name";
+
     /** Constant for the reserved at attribute. */
     static final String ATTR_AT = "at";
 
@@ -81,11 +192,15 @@
     /** Constant for the file name attribute. */
     static final String ATTR_FILENAME = "fileName";
 
+    /** Constant for the name of the header section. */
+    static final String SEC_HEADER = "header";
+
     /** Constant for an expression that selects the union configurations. */
     static final String KEY_UNION = "/additional/*";
 
     /** Constant for an expression that selects override configurations. */
-    static final String KEY_OVERRIDE1 = "/*[local-name() != 'additional' and local-name() != 'override']";
+    static final String KEY_OVERRIDE1 = "/*[local-name() != 'additional' and local-name() != 'override' and local-name() != '"
+            + SEC_HEADER + "']";
 
     /**
      * Constant for an expression that selects override configurations in the
@@ -93,6 +208,20 @@
      */
     static final String KEY_OVERRIDE2 = "/override/*";
 
+    /**
+     * Constant for the key that points to the list nodes definition of the
+     * override combiner.
+     */
+    static final String KEY_OVERRIDE_LIST = SEC_HEADER
+            + "/combiner/override/list-nodes/node";
+
+    /**
+     * Constant for the key that points to the list nodes definition of the
+     * additional combiner.
+     */
+    static final String KEY_ADDITIONAL_LIST = SEC_HEADER
+            + "/combiner/additional/list-nodes/node";
+
     /** Constant for the XML file extension. */
     static final String EXT_XML = ".xml";
 
@@ -120,12 +249,12 @@
 
     /** An array with the names of the default tags. */
     private static final String[] DEFAULT_TAGS =
-    { "properties", "xml", "hierarchicalXml", "jndi", "system", "plist"};
+    { "properties", "xml", "hierarchicalXml", "jndi", "system", "plist" };
 
     /** An array with the providers for the default tags. */
     private static final ConfigurationProvider[] DEFAULT_PROVIDERS =
     { PROPERTIES_PROVIDER, XML_PROVIDER, XML_PROVIDER, JNDI_PROVIDER,
-            SYSTEM_PROVIDER, PLIST_PROVIDER};
+            SYSTEM_PROVIDER, PLIST_PROVIDER };
 
     /** Stores a map with the registered configuration providers. */
     private Map providers;
@@ -148,8 +277,8 @@
     }
 
     /**
-     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and sets
-     * the specified configuration definition file.
+     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
+     * sets the specified configuration definition file.
      *
      * @param file the configuration definition file
      */
@@ -160,8 +289,8 @@
     }
 
     /**
-     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and sets
-     * the specified configuration definition file.
+     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
+     * sets the specified configuration definition file.
      *
      * @param fileName the name of the configuration definition file
      * @throws ConfigurationException if an error occurs when the file is loaded
@@ -174,8 +303,8 @@
     }
 
     /**
-     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and sets
-     * the specified configuration definition file.
+     * Creates a new instance of <code>DefaultConfigurationBuilder</code> and
+     * sets the specified configuration definition file.
      *
      * @param url the URL to the configuration definition file
      * @throws ConfigurationException if an error occurs when the file is loaded
@@ -287,7 +416,7 @@
      * @return the configuration
      * @throws ConfigurationException if an error occurs
      */
-    public Configuration getConfiguration(boolean load)
+    public CombinedConfiguration getConfiguration(boolean load)
             throws ConfigurationException
     {
         if (load)
@@ -297,89 +426,52 @@
 
         List overrides = configurationsAt(KEY_OVERRIDE1);
         overrides.addAll(configurationsAt(KEY_OVERRIDE2));
-        CompositeConfiguration result = createOverrideConfiguration(overrides);
+        CombinedConfiguration result = createCombinedConfiguration(overrides,
+                new OverrideCombiner(), KEY_OVERRIDE_LIST);
         List additionals = configurationsAt(KEY_UNION);
         if (!additionals.isEmpty())
         {
-            result.addConfiguration(createUnionConfiguration(additionals));
+            result.addConfiguration(createCombinedConfiguration(additionals,
+                    new UnionCombiner(), KEY_ADDITIONAL_LIST), ADDITIONAL_NAME);
         }
 
         return result;
     }
 
     /**
-     * Creates a composite configuration for the passed in configuration
-     * declarations.
-     *
-     * @param subs a list with sub configurations that contain configuration
-     * declarations for override configurations
-     * @return the composite configuration
+     * Creates a combined configuration for the configurations of a specific
+     * section. This method is called for the override and for the additional
+     * section (if it exists).
+     *
+     * @param containedConfigs the list with the declaratinos of the contained
+     * configurations
+     * @param combiner the node combiner to use
+     * @param keyListNodes a list with the declaration of list nodes
+     * @return the new combined configuration
      * @throws ConfigurationException if an error occurs
      */
-    protected CompositeConfiguration createOverrideConfiguration(List subs)
+    protected CombinedConfiguration createCombinedConfiguration(
+            List containedConfigs, NodeCombiner combiner, String keyListNodes)
             throws ConfigurationException
     {
-        CompositeConfiguration cc = new CompositeConfiguration();
-
-        for (Iterator it = subs.iterator(); it.hasNext();)
+        List listNodes = getList(keyListNodes);
+        for (Iterator it = listNodes.iterator(); it.hasNext();)
         {
-            cc
-                    .addConfiguration(createConfigurationAt((HierarchicalConfiguration) it
-                            .next()));
+            combiner.addListNode((String) it.next());
         }
 
-        return cc;
-    }
-
-    /**
-     * Creates a union configuration for the passed in configuration
-     * declarations. This method will create configuration objects for the
-     * passed in descriptions and combine them into a single union
-     * configuration.
-     *
-     * @param subs a list with sub configurations that contain configuration
-     * declarations
-     * @return the union configuration
-     * @throws ConfigurationException if an error occurs
-     */
-    protected HierarchicalConfiguration createUnionConfiguration(List subs)
-            throws ConfigurationException
-    {
-        HierarchicalConfiguration union = new HierarchicalConfiguration();
-
-        for (Iterator it = subs.iterator(); it.hasNext();)
+        CombinedConfiguration result = new CombinedConfiguration(combiner);
+        for (Iterator it = containedConfigs.iterator(); it.hasNext();)
         {
             HierarchicalConfiguration conf = (HierarchicalConfiguration) it
                     .next();
             ConfigurationDeclaration decl = new ConfigurationDeclaration(this,
                     conf);
-            union.addNodes(decl.getAt(), convertToHierarchical(
-                    createConfigurationAt(decl)).getRoot().getChildren());
+            result.addConfiguration(createConfigurationAt(decl), decl
+                    .attributeValueStr(ATTR_NAME), decl.getAt());
         }
 
-        return union;
-    }
-
-    /**
-     * Converts the passed in configuration to a hierarchical one. If the
-     * configuration is already hierarchical, it is directly returned. Otherwise
-     * all properties are copied into a new hierarchical configuration.
-     *
-     * @param conf the configuration to convert
-     * @return the new hierarchical configuration
-     */
-    protected HierarchicalConfiguration convertToHierarchical(Configuration conf)
-    {
-        if (conf instanceof HierarchicalConfiguration)
-        {
-            return (HierarchicalConfiguration) conf;
-        }
-        else
-        {
-            HierarchicalConfiguration hc = new HierarchicalConfiguration();
-            ConfigurationUtils.copy(conf, hc);
-            return hc;
-        }
+        return result;
     }
 
     /**
@@ -403,12 +495,12 @@
      * @return the new configuration object
      * @throws ConfigurationException if an error occurs
      */
-    private Configuration createConfigurationAt(ConfigurationDeclaration decl)
-            throws ConfigurationException
+    private AbstractConfiguration createConfigurationAt(
+            ConfigurationDeclaration decl) throws ConfigurationException
     {
         try
         {
-            return (Configuration) BeanHelper.createBean(decl);
+            return (AbstractConfiguration) BeanHelper.createBean(decl);
         }
         catch (Exception ex)
         {
@@ -418,19 +510,6 @@
     }
 
     /**
-     * Creates a configuration object from the specified sub configuration.
-     *
-     * @param sub the sub configuration
-     * @return the new configuration object
-     * @throws ConfigurationException if an error occurs
-     */
-    private Configuration createConfigurationAt(HierarchicalConfiguration sub)
-            throws ConfigurationException
-    {
-        return createConfigurationAt(new ConfigurationDeclaration(this, sub));
-    }
-
-    /**
      * <p>
      * A base class for creating and initializing configuration sources.
      * </p>
@@ -444,6 +523,10 @@
      * <code>Configuration</code> object. It is up to a concrete
      * implementation how this object is created and initialized.
      * </p>
+     * <p>
+     * Note that at the moment only configuration classes derived from
+     * <code>{@link AbstractConfiguration}</code> are supported.
+     * </p>
      */
     public static class ConfigurationProvider extends DefaultBeanFactory
     {
@@ -502,11 +585,11 @@
          * @return the new configuration object
          * @throws Exception if an error occurs
          */
-        public Configuration getConfiguration(ConfigurationDeclaration decl)
-                throws Exception
+        public AbstractConfiguration getConfiguration(
+                ConfigurationDeclaration decl) throws Exception
         {
-            return (Configuration) createBean(getConfigurationClass(), decl,
-                    null);
+            return (AbstractConfiguration) createBean(getConfigurationClass(),
+                    decl, null);
         }
     }
 
@@ -647,8 +730,10 @@
             }
 
             return nd.isAttribute()
-                    && (ATTR_AT.equals(nd.getName()) || ATTR_OPTIONAL.equals(nd
-                            .getName()));
+                    && ((ATTR_AT.equals(nd.getName()) && nd.getParentNode()
+                            .getAttributeCount(RESERVED_PREFIX + ATTR_AT) == 0) || (ATTR_OPTIONAL
+                            .equals(nd.getName()) && nd.getParentNode()
+                            .getAttributeCount(RESERVED_PREFIX + ATTR_OPTIONAL) == 0));
         }
     }
 
@@ -737,8 +822,8 @@
          * @return the new configuration
          * @throws Exception if an error occurs
          */
-        public Configuration getConfiguration(ConfigurationDeclaration decl)
-                throws Exception
+        public AbstractConfiguration getConfiguration(
+                ConfigurationDeclaration decl) throws Exception
         {
             FileConfiguration config = (FileConfiguration) super
                     .getConfiguration(decl);
@@ -753,7 +838,7 @@
                     throw cex;
                 }
             }
-            return config;
+            return (AbstractConfiguration) config;
         }
 
         /**

Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java?rev=397175&r1=397174&r2=397175&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java Wed Apr 26 04:11:03 2006
@@ -17,6 +17,7 @@
 
 import java.io.File;
 import java.util.Collection;
+import java.util.Set;
 
 import org.apache.commons.configuration.beanutils.BeanHelper;
 import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
@@ -29,7 +30,8 @@
  * Test class for DefaultConfigurationBuilder.
  *
  * @author Oliver Heger
- * @version $Id$
+ * @version $Id: TestDefaultConfigurationBuilder.java 384601 2006-03-09
+ * 20:22:58Z oheger $
  */
 public class TestDefaultConfigurationBuilder extends TestCase
 {
@@ -72,23 +74,70 @@
         factory = new DefaultConfigurationBuilder();
         DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
                 factory, factory);
-        DefaultConfigurationNode nd = new DefaultConfigurationNode();
-        nd.setAttribute(true);
-        nd.setName("at");
+        DefaultConfigurationNode parent = new DefaultConfigurationNode();
+        DefaultConfigurationNode nd = new DefaultConfigurationNode("at");
+        parent.addAttribute(nd);
         assertTrue("Attribute at not recognized", decl.isReservedNode(nd));
-        nd.setName("optional");
+        nd = new DefaultConfigurationNode("optional");
+        parent.addAttribute(nd);
         assertTrue("Attribute optional not recognized", decl.isReservedNode(nd));
-        nd.setName(XMLBeanDeclaration.ATTR_BEAN_CLASS);
+        nd = new DefaultConfigurationNode(XMLBeanDeclaration.ATTR_BEAN_CLASS);
+        parent.addAttribute(nd);
         assertTrue("Inherited attribute not recognized", decl
                 .isReservedNode(nd));
-        nd.setName("different");
+        nd = new DefaultConfigurationNode("different");
+        parent.addAttribute(nd);
         assertFalse("Wrong reserved attribute", decl.isReservedNode(nd));
-        nd.setAttribute(false);
-        nd.setName("at");
+        nd = new DefaultConfigurationNode("at");
+        parent.addChild(nd);
         assertFalse("Node type not evaluated", decl.isReservedNode(nd));
     }
 
     /**
+     * Tests if the at attribute is correctly detected as reserved attribute.
+     */
+    public void testConfigurationDeclarationIsReservedAt()
+    {
+        checkOldReservedAttribute("at");
+    }
+
+    /**
+     * Tests if the optional attribute is correctly detected as reserved
+     * attribute.
+     */
+    public void testConfigurationDeclarationIsReservedOptional()
+    {
+        checkOldReservedAttribute("optional");
+    }
+
+    /**
+     * Tests if special reserved attributes are recognized by the
+     * isReservedNode() method. For compatibility reasons the attributes "at"
+     * and "optional" are also treated as reserved attributes, but only if there
+     * are no corresponding attributes with the "config-" prefix.
+     *
+     * @param name the attribute name
+     */
+    private void checkOldReservedAttribute(String name)
+    {
+        factory = new DefaultConfigurationBuilder();
+        DefaultConfigurationBuilder.ConfigurationDeclaration decl = new DefaultConfigurationBuilder.ConfigurationDeclaration(
+                factory, factory);
+        DefaultConfigurationNode parent = new DefaultConfigurationNode();
+        DefaultConfigurationNode nd = new DefaultConfigurationNode("config-"
+                + name);
+        parent.addAttribute(nd);
+        assertTrue("config-" + name + " attribute not recognized", decl
+                .isReservedNode(nd));
+        DefaultConfigurationNode nd2 = new DefaultConfigurationNode(name);
+        parent.addAttribute(nd2);
+        assertFalse(name + " is reserved though config- exists", decl
+                .isReservedNode(nd2));
+        assertTrue("config- attribute not recognized when " + name + " exists",
+                decl.isReservedNode(nd));
+    }
+
+    /**
      * Tests access to certain reserved attributes of a
      * ConfigurationDeclaration.
      */
@@ -259,10 +308,10 @@
      */
     private void checkConfiguration() throws ConfigurationException
     {
-        CompositeConfiguration compositeConfiguration = (CompositeConfiguration) factory
+        CombinedConfiguration compositeConfiguration = (CombinedConfiguration) factory
                 .getConfiguration();
 
-        assertEquals("Number of configurations", 4, compositeConfiguration
+        assertEquals("Number of configurations", 3, compositeConfiguration
                 .getNumberOfConfigurations());
         assertEquals(PropertiesConfiguration.class, compositeConfiguration
                 .getConfiguration(0).getClass());
@@ -292,9 +341,9 @@
     public void testLoadAdditional() throws ConfigurationException
     {
         factory.setFile(ADDITIONAL_FILE);
-        CompositeConfiguration compositeConfiguration = (CompositeConfiguration) factory
+        CombinedConfiguration compositeConfiguration = (CombinedConfiguration) factory
                 .getConfiguration();
-        assertEquals("Verify how many configs", 3, compositeConfiguration
+        assertEquals("Verify how many configs", 2, compositeConfiguration
                 .getNumberOfConfigurations());
 
         // Test if union was constructed correctly
@@ -367,9 +416,10 @@
         factory.setFile(MULTI_FILE);
         Configuration config = factory.getConfiguration();
         assertFalse(config.isEmpty());
-        assertTrue(config instanceof CompositeConfiguration);
-        CompositeConfiguration cc = (CompositeConfiguration) config;
-        assertTrue(cc.getNumberOfConfigurations() == 2);
+        assertTrue(config instanceof CombinedConfiguration);
+        CombinedConfiguration cc = (CombinedConfiguration) config;
+        assertEquals("Wrong number of configurations", 1, cc
+                .getNumberOfConfigurations());
 
         assertNotNull(config
                 .getProperty("tables.table(0).fields.field(2).name"));
@@ -413,7 +463,7 @@
     public void testComplexInitialization() throws ConfigurationException
     {
         factory.setFile(INIT_FILE);
-        CompositeConfiguration cc = (CompositeConfiguration) factory
+        CombinedConfiguration cc = (CombinedConfiguration) factory
                 .getConfiguration();
 
         PropertiesConfiguration c1 = (PropertiesConfiguration) cc
@@ -425,9 +475,67 @@
                 ((FileChangedReloadingStrategy) c1.getReloadingStrategy())
                         .getRefreshDelay());
 
-        assertEquals("Property not found", "I'm complex!", cc
+        Configuration xmlConf = cc.getConfiguration("xml");
+        assertEquals("Property not found", "I'm complex!", xmlConf
                 .getString("element2/subelement/subsubelement"));
-        assertEquals("List index not found", "two", cc
+        assertEquals("List index not found", "two", xmlConf
                 .getString("list[0]/item[1]"));
+    }
+
+    /**
+     * Tests if the returned combined configuration has the expected structure.
+     */
+    public void testCombinedConfiguration() throws ConfigurationException
+    {
+        factory.setFile(INIT_FILE);
+        CombinedConfiguration cc = (CombinedConfiguration) factory
+                .getConfiguration();
+        assertNotNull("Properties configuration not found", cc
+                .getConfiguration("properties"));
+        assertNotNull("XML configuration not found", cc.getConfiguration("xml"));
+        assertEquals("Wrong number of contained configs", 3, cc
+                .getNumberOfConfigurations());
+
+        CombinedConfiguration cc2 = (CombinedConfiguration) cc
+                .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME);
+        assertNotNull("No additional configuration found", cc2);
+        Set names = cc2.getConfigurationNames();
+        assertEquals("Wrong number of contained additional configs", 2, names
+                .size());
+        assertTrue("Config 1 not contained", names.contains("combiner1"));
+        assertTrue("Config 2 not contained", names.contains("combiner2"));
+    }
+
+    /**
+     * Tests the structure of the returned combined configuration if there is no
+     * additional section.
+     */
+    public void testCombinedConfigurationNoAdditional()
+            throws ConfigurationException
+    {
+        factory.setFile(TEST_FILE);
+        CombinedConfiguration cc = factory.getConfiguration(true);
+        assertNull("Additional configuration was found", cc
+                .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME));
+    }
+
+    /**
+     * Tests whether the list node definition was correctly processed.
+     */
+    public void testCombinedConfigurationListNodes()
+            throws ConfigurationException
+    {
+        factory.setFile(INIT_FILE);
+        CombinedConfiguration cc = factory.getConfiguration(true);
+        Set listNodes = cc.getNodeCombiner().getListNodes();
+        assertEquals("Wrong number of list nodes", 2, listNodes.size());
+        assertTrue("table node not a list node", listNodes.contains("table"));
+        assertTrue("list node not a list node", listNodes.contains("list"));
+
+        CombinedConfiguration cca = (CombinedConfiguration) cc
+                .getConfiguration(DefaultConfigurationBuilder.ADDITIONAL_NAME);
+        listNodes = cca.getNodeCombiner().getListNodes();
+        assertTrue("Found list nodes for additional combiner", listNodes
+                .isEmpty());
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org