Author: oheger Date: Tue Apr 8 13:34:47 2008 New Revision: 646066 URL: http://svn.apache.org/viewvc?rev=646066&view=rev Log: BaseConfiguration now extends AbstractFlatConfiguration
Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/flat/BaseConfiguration.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/flat/TestBaseConfiguration.java Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java?rev=646066&r1=646065&r2=646066&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java Tue Apr 8 13:34:47 2008 @@ -26,6 +26,7 @@ import org.apache.commons.configuration2.event.ConfigurationEvent; import org.apache.commons.configuration2.event.ConfigurationListener; +import org.apache.commons.configuration2.flat.AbstractFlatConfiguration; import org.apache.commons.lang.StringUtils; /** @@ -518,6 +519,7 @@ clear(); break; case AbstractConfiguration.EVENT_SET_PROPERTY: + case AbstractFlatConfiguration.EVENT_PROPERTY_CHANGED: fetchLayoutData(event.getPropertyName()); break; } Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/flat/BaseConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/flat/BaseConfiguration.java?rev=646066&r1=646065&r2=646066&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/flat/BaseConfiguration.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/flat/BaseConfiguration.java Tue Apr 8 13:34:47 2008 @@ -18,19 +18,19 @@ package org.apache.commons.configuration2.flat; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.commons.configuration2.AbstractConfiguration; import org.apache.commons.configuration2.ConfigurationRuntimeException; import org.apache.commons.configuration2.ConfigurationUtils; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.XMLConfiguration; /** - * Basic configuration classe. Stores the configuration data but does not + * Basic configuration class. Stores the configuration data but does not * provide any load or save functions. If you want to load your Configuration * from a file use [EMAIL PROTECTED] PropertiesConfiguration} or [EMAIL PROTECTED] XMLConfiguration}. * @@ -53,7 +53,7 @@ * @author Oliver Heger * @version $Id$ */ -public class BaseConfiguration extends AbstractConfiguration implements Cloneable +public class BaseConfiguration extends AbstractFlatConfiguration implements Cloneable { /** stores the configuration key-value pairs */ private Map<String, Object> store = new LinkedHashMap<String, Object>(); @@ -178,6 +178,104 @@ { // should not happen throw new ConfigurationRuntimeException(cex); + } + } + + /** + * Returns the maximum index for the property with the given index. If the + * property has multiple values, the maximum index is the number of values + * minus 1 (indices are 0-based). If the property has a single value, the + * maximum index is 0. If the passed in key cannot be resolved, result is + * -1. + * + * @param key the key of the property in question + * @return the maximum index for this property + */ + @Override + public int getMaxIndex(String key) + { + Object value = getProperty(key); + + if (value == null) + { + return -1; + } + else if (value instanceof Collection) + { + return ((Collection<?>) value).size() - 1; + } + else + { + return 0; + } + } + + /** + * Removes a value of a property with multiple values. The value to remove + * is specified using its (0-based) index. If the index is invalid or if the + * property does not have multiple values, this method has no effect. + * + * @param key the key of the property + * @param index the index of the value to be removed + * @return a flag whether the value could be removed + */ + @Override + protected boolean clearPropertyValueDirect(String key, int index) + { + Object value = getProperty(key); + + if (value instanceof List && index >= 0) + { + List<?> col = (List<?>) value; + if (index < col.size()) + { + col.remove(index); + return true; + } + } + + return false; + } + + /** + * Modifies a value of a property with multiple values. The value to be + * changed is specified using its (0-based) index. If the property does not + * exist or the index is invalid, the value is added as if + * <code>addProperty()</code> was called. If the property has a single + * value, the passed in index determines what happens: if it is 0, the + * single value is replaced by the new one; all other indices cause the new + * value to be added to the old one. + * + * @param key the key of the property + * @param index the index of the value to be manipulated + * @param value the new value + */ + @SuppressWarnings("unchecked") + @Override + protected void setPropertyValueDirect(String key, int index, Object value) + { + Object oldValue = getProperty(key); + + if (oldValue instanceof List) + { + List<Object> col = (List<Object>) oldValue; + if (index >= 0 && index < col.size()) + { + col.set(index, value); + } + else + { + addPropertyDirect(key, value); + } + } + + else if (oldValue == null || index != 0) + { + addPropertyDirect(key, value); + } + else + { + store.put(key, value); } } } Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java?rev=646066&r1=646065&r2=646066&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java Tue Apr 8 13:34:47 2008 @@ -680,10 +680,8 @@ { PropertiesConfiguration copy = (PropertiesConfiguration) conf.clone(); assertNotSame("Copy has same layout object", conf.getLayout(), copy.getLayout()); - assertEquals("Wrong number of event listeners for original", 1, conf.getConfigurationListeners().size()); - assertEquals("Wrong number of event listeners for clone", 1, copy.getConfigurationListeners().size()); - assertSame("Wrong event listener for original", conf.getLayout(), conf.getConfigurationListeners().iterator().next()); - assertSame("Wrong event listener for clone", copy.getLayout(), copy.getConfigurationListeners().iterator().next()); + assertTrue("Wrong event listener for original", conf.getConfigurationListeners().contains(conf.getLayout())); + assertTrue("Wrong event listener for clone", copy.getConfigurationListeners().contains(copy.getLayout())); StringWriter outConf = new StringWriter(); conf.save(outConf); StringWriter outCopy = new StringWriter(); Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java?rev=646066&r1=646065&r2=646066&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java Tue Apr 8 13:34:47 2008 @@ -19,12 +19,12 @@ import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; -import java.util.Iterator; - -import org.apache.commons.configuration2.event.ConfigurationEvent; import junit.framework.TestCase; +import org.apache.commons.configuration2.event.ConfigurationEvent; +import org.apache.commons.configuration2.flat.AbstractFlatConfiguration; + /** * Test class for PropertiesConfigurationLayout. * @@ -73,10 +73,15 @@ { assertTrue("Object contains keys", layout.getKeys().isEmpty()); assertNull("Header comment not null", layout.getHeaderComment()); - Iterator<?> it = config.getConfigurationListeners().iterator(); - assertTrue("No event listener registered", it.hasNext()); - assertSame("Layout not registered as event listener", layout, it.next()); - assertFalse("Multiple event listeners registered", it.hasNext()); + boolean foundListener = false; + for (Object l : config.getConfigurationListeners()) + { + if (layout == l) + { + foundListener = true; + } + } + assertTrue("Layout not registered as event listener", foundListener); assertSame("Configuration not stored", config, layout .getConfiguration()); assertFalse("Force single line flag set", layout.isForceSingleLine()); @@ -301,6 +306,20 @@ ConfigurationEvent event = new ConfigurationEvent(this, AbstractConfiguration.EVENT_SET_PROPERTY, TEST_KEY, TEST_VALUE, false); + layout.configurationChanged(event); + assertTrue("New property was not found", layout.getKeys().contains( + TEST_KEY)); + } + + /** + * Tests if a change property event for a non existing property is correctly + * handled. + */ + public void testEventChangeNonExisting() + { + ConfigurationEvent event = new ConfigurationEvent(this, + AbstractFlatConfiguration.EVENT_PROPERTY_CHANGED, TEST_KEY, + TEST_VALUE, false); layout.configurationChanged(event); assertTrue("New property was not found", layout.getKeys().contains( TEST_KEY)); Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/flat/TestBaseConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/flat/TestBaseConfiguration.java?rev=646066&r1=646065&r2=646066&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/flat/TestBaseConfiguration.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/flat/TestBaseConfiguration.java Tue Apr 8 13:34:47 2008 @@ -48,6 +48,9 @@ /** Constant for the number key.*/ static final String KEY_NUMBER = "number"; + /** Constant for the key of a test property.*/ + private static final String TEST_KEY = "testKey"; + protected BaseConfiguration config = null; protected static Class<?> missingElementException = NoSuchElementException.class; @@ -755,7 +758,165 @@ assertTrue("Wrong value of original property", config .getBoolean("original")); - assertEquals("Event listener was copied", 0, config2 + assertEquals("Event listener was copied", config + .getConfigurationListeners().size() - 1, config2 .getConfigurationListeners().size()); + } + + /** + * Tests the getMaxIndex() method for a non existing property. + */ + public void testGetMaxIndexNonExisting() + { + assertEquals("Wrong max index for non-existing property", -1, config + .getMaxIndex("nonExistingProperty")); + } + + /** + * Tests querying the maximum index for a property with a single value. + */ + public void testGetMaxIndexSingleValue() + { + config.addProperty(TEST_KEY, "A value"); + assertEquals("Wrong max index for single value", 0, config + .getMaxIndex(TEST_KEY)); + } + + /** + * Tests querying the maximum index for a property with multiple values. + */ + public void testGetMaxIndexMulti() + { + final int count = 10; + for (int i = 0; i < count; i++) + { + config.addProperty(TEST_KEY, i); + } + assertEquals("Wrong max index for multiple values", count - 1, config + .getMaxIndex(TEST_KEY)); + } + + /** + * Tests removing a value of a property with multiple values. + */ + public void testClearPropertyValue() + { + config.addProperty(TEST_KEY, new Integer[] { + 1, 2, 3 + }); + assertTrue("Value not removed", config.clearPropertyValue(TEST_KEY, 1)); + List<?> lst = config.getList(TEST_KEY); + assertEquals("Wrong number of values", 2, lst.size()); + assertEquals("Wrong value 1", Integer.valueOf(1), lst.get(0)); + assertEquals("Wrong value 2", Integer.valueOf(3), lst.get(1)); + } + + /** + * Tries to remove a property value with an invalid index. This should be a + * no-op. + */ + public void testClearPropertyValueInvalidIndex() + { + config.addProperty(TEST_KEY, new Integer[] { + 1, 2, 3 + }); + assertFalse("Can remove value with negative index", config + .clearPropertyValue(TEST_KEY, -1)); + assertFalse("Can remove value with index too big", config + .clearPropertyValue(TEST_KEY, 1000)); + assertEquals("Wrong number of values", 3, config.getList(TEST_KEY) + .size()); + } + + /** + * Tries to remove a single property value with an index. This should not + * work. + */ + public void testClearPropertyValueSingle() + { + config.addProperty(TEST_KEY, "A value"); + assertFalse("Can removing single value", config.clearPropertyValue( + TEST_KEY, 0)); + assertEquals("Wrong value", "A value", config.getString(TEST_KEY)); + } + + /** + * Tries to remove a value of a non existing property. + */ + public void testClearPropertyValueNonExisting() + { + assertFalse("Can remove non existing value", config.clearPropertyValue( + TEST_KEY, 0)); + } + + /** + * Tests setting the value of a property. + */ + public void testSetPropertyValue() + { + config.addProperty(TEST_KEY, new Integer[] { + 1, 2, 3 + }); + config.setPropertyValue(TEST_KEY, 1, 4); + List<?> lst = config.getList(TEST_KEY); + assertEquals("Wrong number of values", 3, lst.size()); + assertEquals("Wrong value 1", Integer.valueOf(1), lst.get(0)); + assertEquals("Wrong value 2", Integer.valueOf(4), lst.get(1)); + assertEquals("Wrong value 3", Integer.valueOf(3), lst.get(2)); + } + + /** + * Tests setting the value of a non existing property. This should be a + * normal add operation. + */ + public void testSetPropertyValueNonExisting() + { + config.setPropertyValue(TEST_KEY, 0, "test"); + assertEquals("Value was not set", "test", config.getString(TEST_KEY)); + } + + /** + * Tests setting the value of a property using an invalid index. Then the + * value should simply be added. + */ + public void testSetPropertyValueInvalid() + { + config.addProperty(TEST_KEY, new Integer[] { + 1, 2, 3 + }); + config.setPropertyValue(TEST_KEY, -1, 4); + config.setPropertyValue(TEST_KEY, 1111, 5); + List<?> lst = config.getList(TEST_KEY); + assertEquals("Wrong number of values", 5, lst.size()); + for (int i = 1; i <= 5; i++) + { + assertEquals("Wrong value at " + i, Integer.valueOf(i), lst + .get(i - 1)); + } + } + + /** + * Tests setting the value of a property with a single value. If the index + * is 0, the value must be replaced. + */ + public void testSetPropertyValueSingle0() + { + config.addProperty(TEST_KEY, 1); + config.setPropertyValue(TEST_KEY, 0, 2); + assertEquals("Wrong value", 2, config.getInt(TEST_KEY)); + } + + /** + * Tests setting the value of a property with a single value using an + * invalid index. In this case, the new value must be added to the property. + */ + public void testSetPropertyValueSingle1() + { + config.addProperty(TEST_KEY, 1); + config.setPropertyValue(TEST_KEY, 1, 2); + List<?> lst = config.getList(TEST_KEY); + assertEquals("Wrong number of values", 2, lst.size()); + assertEquals("Wrong value 1", Integer.valueOf(1), lst.get(0)); + assertEquals("Wrong value 2", Integer.valueOf(2), lst.get(1)); } }