You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2009/04/08 21:56:10 UTC

svn commit: r763367 - in /commons/proper/configuration/trunk: src/java/org/apache/commons/configuration/MapConfiguration.java src/test/org/apache/commons/configuration/TestMapConfiguration.java xdocs/changes.xml

Author: oheger
Date: Wed Apr  8 19:56:10 2009
New Revision: 763367

URL: http://svn.apache.org/viewvc?rev=763367&view=rev
Log:
CONFIGURATION-374: Improved documentation of MapConfiguration and added a method for controlling trimming behavior.

Modified:
    commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java
    commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMapConfiguration.java
    commons/proper/configuration/trunk/xdocs/changes.xml

Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java?rev=763367&r1=763366&r2=763367&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java Wed Apr  8 19:56:10 2009
@@ -23,10 +23,55 @@
 import java.util.Map;
 
 /**
- * <p>A Map based Configuration.</p>
- * <p><em>Note:</em>Configuration objects of this type can be read concurrently
- * by multiple threads. However if one of these threads modifies the object,
- * synchronization has to be performed manually.</p>
+ * <p>
+ * A Map based Configuration.
+ * </p>
+ * <p>
+ * This implementation of the <code>Configuration</code> interface is
+ * initialized with a <code>java.util.Map</code>. The methods of the
+ * <code>Configuration</code> interface are implemented on top of the content of
+ * this map. The following storage scheme is used:
+ * </p>
+ * <p>
+ * Property keys are directly mapped to map keys, i.e. the
+ * <code>getProperty()</code> method directly performs a <code>get()</code> on
+ * the map. Analogously, <code>setProperty()</code> or
+ * <code>addProperty()</code> operations write new data into the map. If a value
+ * is added to an existing property, a <code>java.util.List</code> is created,
+ * which stores the values of this property.
+ * </p>
+ * <p>
+ * An important use case of this class is to treat a map as a
+ * <code>Configuration</code> allowing access to its data through the richer
+ * interface. This can be a bit problematic in some cases because the map may
+ * contain values that need not adhere to the default storage scheme used by
+ * typical configuration implementations, e.g. regarding lists. In such cases
+ * care must be taken when manipulating the data through the
+ * <code>Configuration</code> interface, e.g. by calling
+ * <code>addProperty()</code>; results may be different than expected.
+ * </p>
+ * <p>
+ * An important point is the handling of list delimiters: If delimiter parsing
+ * is enabled (which it is per default), <code>getProperty()</code> checks
+ * whether the value of a property is a string and whether it contains the list
+ * delimiter character. If this is the case, the value is split at the delimiter
+ * resulting in a list. This split operation typically also involves trimming
+ * the single values as the list delimiter character may be surrounded by
+ * whitespace. Trimming can be disabled with the
+ * {@link #setTrimmingDisabled(boolean)} method. The whole list splitting
+ * behavior can be disabled using the
+ * {@link #setDelimiterParsingDisabled(boolean)} method.
+ * </p>
+ * <p>
+ * Notice that list splitting is only performed for single string values. If a
+ * property has multiple values, the single values are not split even if they
+ * contain the list delimiter character.
+ * </p>
+ * <p>
+ * As the underlying <code>Map</code> is directly used as store of the property
+ * values, the thread-safety of this <code>Configuration</code> implementation
+ * depends on the map passed to the constructor.
+ * </p>
  *
  * @author Emmanuel Bourg
  * @version $Revision$, $Date$
@@ -37,6 +82,9 @@
     /** The Map decorated by this configuration. */
     protected Map map;
 
+    /** A flag whether trimming of property values should be disabled.*/
+    private boolean trimmingDisabled;
+
     /**
      * Create a Configuration decorator around the specified Map. The map is
      * used to store the configuration properties, any change will also affect
@@ -59,12 +107,38 @@
         return map;
     }
 
+    /**
+     * Returns the flag whether trimming of property values is disabled.
+     *
+     * @return <b>true</b> if trimming of property values is disabled;
+     *         <b>false</b> otherwise
+     * @since 1.7
+     */
+    public boolean isTrimmingDisabled()
+    {
+        return trimmingDisabled;
+    }
+
+    /**
+     * Sets a flag whether trimming of property values is disabled. This flag is
+     * only evaluated if list splitting is enabled. Refer to the header comment
+     * for more information about list splitting and trimming.
+     *
+     * @param trimmingDisabled a flag whether trimming of property values should
+     *        be disabled
+     * @since 1.7
+     */
+    public void setTrimmingDisabled(boolean trimmingDisabled)
+    {
+        this.trimmingDisabled = trimmingDisabled;
+    }
+
     public Object getProperty(String key)
     {
         Object value = map.get(key);
         if ((value instanceof String) && (!isDelimiterParsingDisabled()))
         {
-            List list = PropertyConverter.split((String) value, getListDelimiter());
+            List list = PropertyConverter.split((String) value, getListDelimiter(), !isTrimmingDisabled());
             return list.size() > 1 ? list : list.get(0);
         }
         else

Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMapConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMapConfiguration.java?rev=763367&r1=763366&r2=763367&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMapConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMapConfiguration.java Wed Apr  8 19:56:10 2009
@@ -18,6 +18,7 @@
 package org.apache.commons.configuration;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.configuration.event.ConfigurationEvent;
@@ -31,10 +32,19 @@
  */
 public class TestMapConfiguration extends TestAbstractConfiguration
 {
+    /** Constant for a test key.*/
+    private static final String KEY = "key1";
+
+    /** Constant for a test property value with whitespace.*/
+    private static final String SPACE_VALUE = "   Value with whitespace  ";
+
+    /** The trimmed test value.*/
+    private static final String TRIM_VALUE = SPACE_VALUE.trim();
+
     protected AbstractConfiguration getConfiguration()
     {
         Map map = new HashMap();
-        map.put("key1", "value1");
+        map.put(KEY, "value1");
         map.put("key2", "value2");
         map.put("list", "value1, value2");
         map.put("listesc", "value1\\,value2");
@@ -86,4 +96,50 @@
         assertEquals("Map not decoupled (2)", "value1", config
                 .getString("key1"));
     }
+
+    /**
+     * Tests adding another value to an existing property.
+     */
+    public void testAddProperty()
+    {
+        MapConfiguration config = (MapConfiguration) getConfiguration();
+        config.addProperty(KEY, TRIM_VALUE);
+        config.addProperty(KEY, "anotherValue");
+        List values = config.getList(KEY);
+        assertEquals("Wrong number of values", 3, values.size());
+    }
+
+    /**
+     * Tests querying a property when trimming is active.
+     */
+    public void testGetPropertyTrim()
+    {
+        MapConfiguration config = (MapConfiguration) getConfiguration();
+        config.getMap().put(KEY, SPACE_VALUE);
+        assertEquals("Wrong trimmed value", TRIM_VALUE, config.getProperty(KEY));
+    }
+
+    /**
+     * Tests querying a property when trimming is disabled.
+     */
+    public void testGetPropertyTrimDisabled()
+    {
+        MapConfiguration config = (MapConfiguration) getConfiguration();
+        config.getMap().put(KEY, SPACE_VALUE);
+        config.setTrimmingDisabled(true);
+        assertEquals("Wrong trimmed value", SPACE_VALUE, config.getProperty(KEY));
+    }
+
+    /**
+     * Tests querying a property when trimming is enabled, but list splitting is
+     * disabled. In this case no trimming is performed (trimming only works if
+     * list splitting is enabled).
+     */
+    public void testGetPropertyTrimNoSplit()
+    {
+        MapConfiguration config = (MapConfiguration) getConfiguration();
+        config.getMap().put(KEY, SPACE_VALUE);
+        config.setDelimiterParsingDisabled(true);
+        assertEquals("Wrong trimmed value", SPACE_VALUE, config.getProperty(KEY));
+    }
 }

Modified: commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/xdocs/changes.xml?rev=763367&r1=763366&r2=763367&view=diff
==============================================================================
--- commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ commons/proper/configuration/trunk/xdocs/changes.xml Wed Apr  8 19:56:10 2009
@@ -23,6 +23,10 @@
 
   <body>
     <release version="1.7" date="in SVN" description="">
+      <action dev="oheger" type="add" issue="CONFIGURATION-374">
+        MapConfiguration now provides a way of controlling the trimming
+        behavior.
+      </action>
       <action dev="rgoers" type="add" issue="CONFIGURATION-378">
         Added MergeCombiner to allow elements in two configurations to be merged when the
         element and attributes in the first file match those in the second file.