Author: oheger Date: Sun Apr 30 09:19:51 2006 New Revision: 398368 URL: http://svn.apache.org/viewcvs?rev=398368&view=rev Log: Updated DefaultConfigurationBuilder to deal with an extended header section
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/java/org/apache/commons/configuration/beanutils/XMLBeanDeclaration.java jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/beanutils/TestXMLBeanDeclaration.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=398368&r1=398367&r2=398368&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml (original) +++ jakarta/commons/proper/configuration/trunk/conf/testComplexInitialization.xml Sun Apr 30 09:19:51 2006 @@ -2,6 +2,10 @@ <!-- Test configuration definition file that demonstrates complex initialization --> <configuration> <header> + <result delimiterParsingDisabled="true"> + <nodeCombiner config-class="org.apache.commons.configuration.tree.OverrideCombiner"/> + <expressionEngine config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/> + </result> <combiner> <override> <list-nodes> 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=398368&r1=398367&r2=398368&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 Sun Apr 30 09:19:51 2006 @@ -30,7 +30,6 @@ 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; @@ -119,8 +118,8 @@ * </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> + * <td>Declares a configuration as optional. This means that errors that occur + * when creating the configuration are silently ignored.</td> * </tr> * </table> * </p> @@ -222,6 +221,16 @@ static final String KEY_ADDITIONAL_LIST = SEC_HEADER + "/combiner/additional/list-nodes/node"; + /** + * Constant for the key of the result declaration. This key can point to a + * bean declaration, which defines properties of the resulting combined + * configuration. + */ + static final String KEY_RESULT = SEC_HEADER + "/result"; + + /** Constant for the key of the combiner in the result declaration.*/ + static final String KEY_COMBINER = KEY_RESULT + "/nodeCombiner"; + /** Constant for the XML file extension. */ static final String EXT_XML = ".xml"; @@ -424,54 +433,82 @@ load(); } - List overrides = configurationsAt(KEY_OVERRIDE1); - overrides.addAll(configurationsAt(KEY_OVERRIDE2)); - CombinedConfiguration result = createCombinedConfiguration(overrides, - new OverrideCombiner(), KEY_OVERRIDE_LIST); + CombinedConfiguration result = createOverrideConfiguration(); List additionals = configurationsAt(KEY_UNION); if (!additionals.isEmpty()) { - result.addConfiguration(createCombinedConfiguration(additionals, - new UnionCombiner(), KEY_ADDITIONAL_LIST), ADDITIONAL_NAME); + CombinedConfiguration addConfig = new CombinedConfiguration( + new UnionCombiner()); + initCombinedConfiguration(addConfig, additionals, + KEY_ADDITIONAL_LIST); + result.addConfiguration(addConfig, ADDITIONAL_NAME); } return result; } /** - * Creates a combined configuration for the configurations of a specific + * Creates the resulting combined configuration. This method is called by + * <code>getConfiguration()</code>. Its task is to construct the + * resulting (override) combined configuration and to add all declared + * override configurations to it. This implementation checks whether the + * <code>header</code> section of the configuration definition file + * contains a <code>result</code> element. If this is the case, it will be + * used to initialize the properties of the newly created configuration + * object. + * + * @return the override configuration object + * @throws ConfigurationException if an error occurs + */ + protected CombinedConfiguration createOverrideConfiguration() + throws ConfigurationException + { + XMLBeanDeclaration decl = new XMLBeanDeclaration(this, KEY_RESULT, true); + CombinedConfiguration result = (CombinedConfiguration) BeanHelper + .createBean(decl, CombinedConfiguration.class); + + if (getMaxIndex(KEY_COMBINER) < 0) + { + // No combiner defined => set default + result.setNodeCombiner(new OverrideCombiner()); + } + + List overrides = configurationsAt(KEY_OVERRIDE1); + overrides.addAll(configurationsAt(KEY_OVERRIDE2)); + initCombinedConfiguration(result, overrides, KEY_OVERRIDE_LIST); + return result; + } + + /** + * Initializes 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 config the configuration to be initialized * @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 CombinedConfiguration createCombinedConfiguration( - List containedConfigs, NodeCombiner combiner, String keyListNodes) + protected void initCombinedConfiguration(CombinedConfiguration config, + List containedConfigs, String keyListNodes) throws ConfigurationException { List listNodes = getList(keyListNodes); for (Iterator it = listNodes.iterator(); it.hasNext();) { - combiner.addListNode((String) it.next()); + config.getNodeCombiner().addListNode((String) it.next()); } - CombinedConfiguration result = new CombinedConfiguration(combiner); for (Iterator it = containedConfigs.iterator(); it.hasNext();) { HierarchicalConfiguration conf = (HierarchicalConfiguration) it .next(); ConfigurationDeclaration decl = new ConfigurationDeclaration(this, conf); - result.addConfiguration(createConfigurationAt(decl), decl + config.addConfiguration(createConfigurationAt(decl), decl .attributeValueStr(ATTR_NAME), decl.getAt()); } - - return result; } /** @@ -792,7 +829,7 @@ * configurations. Ensures that the base path is correctly set and that the * load() method gets called. */ - static class FileConfigurationProvider extends ConfigurationProvider + public static class FileConfigurationProvider extends ConfigurationProvider { /** * Creates a new instance of <code>FileConfigurationProvider</code>. Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/XMLBeanDeclaration.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/XMLBeanDeclaration.java?rev=398368&r1=398367&r2=398368&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/XMLBeanDeclaration.java (original) +++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/XMLBeanDeclaration.java Sun Apr 30 09:19:51 2006 @@ -23,6 +23,7 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.PropertyConverter; import org.apache.commons.configuration.tree.ConfigurationNode; +import org.apache.commons.configuration.tree.DefaultConfigurationNode; /** * <p> @@ -117,18 +118,53 @@ * * @param config the configuration * @param key the key to the bean declaration (this key must point to - * exactly one bean declaration) + * exactly one bean declaration or a <code>IllegalArgumentException</code> + * exception will be thrown) */ public XMLBeanDeclaration(HierarchicalConfiguration config, String key) { + this(config, key, false); + } + + /** + * Creates a new instance of <code>XMLBeanDeclaration</code> and + * initializes it from the given configuration. The passed in key points to + * the bean declaration. If the key does not exist and the boolean argument + * is <b>true</b>, the declaration is initialized with an empty + * configuration. It is possible to create objects from such an empty + * declaration if a default class is provided. If the key on the other hand + * has multiple values or is undefined and the boolean argument is <b>false</b>, + * a <code>IllegalArgumentException</code> exception will be thrown. + * + * @param config the configuration + * @param key the key to the bean declaration + * @param optional a flag whether this declaration is optional; if set to + * <b>true</b>, no exception will be thrown if the passed in key is + * undefined + */ + public XMLBeanDeclaration(HierarchicalConfiguration config, String key, + boolean optional) + { if (config == null) { throw new IllegalArgumentException( "Configuration must not be null!"); } - node = (key == null) ? config.getRoot() : config.configurationAt(key) - .getRoot(); + try + { + node = (key == null) ? config.getRoot() : config.configurationAt( + key).getRoot(); + } + catch (IllegalArgumentException iex) + { + // If we reach this block, the key does not have exactly one value + if (!optional || config.getMaxIndex(key) > 0) + { + throw iex; + } + node = new DefaultConfigurationNode(); + } configuration = 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=398368&r1=398367&r2=398368&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 Sun Apr 30 09:19:51 2006 @@ -23,6 +23,7 @@ import org.apache.commons.configuration.beanutils.XMLBeanDeclaration; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.apache.commons.configuration.tree.DefaultConfigurationNode; +import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; import junit.framework.TestCase; @@ -480,6 +481,11 @@ .getString("element2/subelement/subsubelement")); assertEquals("List index not found", "two", xmlConf .getString("list[0]/item[1]")); + + assertTrue("Delimiter flag was not set", cc + .isDelimiterParsingDisabled()); + assertTrue("Expression engine was not set", + cc.getExpressionEngine() instanceof XPathExpressionEngine); } /** Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/beanutils/TestXMLBeanDeclaration.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/beanutils/TestXMLBeanDeclaration.java?rev=398368&r1=398367&r2=398368&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/beanutils/TestXMLBeanDeclaration.java (original) +++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/beanutils/TestXMLBeanDeclaration.java Sun Apr 30 09:19:51 2006 @@ -304,6 +304,59 @@ } /** + * Tests constructing a bean declaration from an undefined key. This should + * cause an exception. + */ + public void testInitFromUndefinedKey() + { + HierarchicalConfiguration config = new HierarchicalConfiguration(); + setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES); + try + { + decl = new XMLBeanDeclaration(config, "undefined_key"); + fail("Could create declaration from an undefined key!"); + } + catch (IllegalArgumentException iex) + { + // ok + } + } + + /** + * Tests constructing a bean declaration from a key, which is undefined when + * the optional flag is set. In this case an empty declaration should be + * created, which can be used for creating beans as long as a default class + * is provided. + */ + public void testInitFromUndefinedKeyOptional() + { + HierarchicalConfiguration config = new HierarchicalConfiguration(); + setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES); + decl = new XMLBeanDeclaration(config, "undefined_key", true); + assertNull("Found a bean class", decl.getBeanClassName()); + } + + /** + * Tests constructing a bean declaration from a key with multiple values. + * This should cause an exception because keys must be unique. + */ + public void testInitFromMultiValueKey() + { + HierarchicalConfiguration config = new HierarchicalConfiguration(); + config.addProperty(KEY, "myFirstKey"); + config.addProperty(KEY, "mySecondKey"); + try + { + decl = new XMLBeanDeclaration(config, KEY); + fail("Could create declaration from multi-valued property!"); + } + catch (IllegalArgumentException iex) + { + // ok + } + } + + /** * Initializes a configuration object with a bean declaration. Under the * specified key the given properties will be added. * --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]