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 2013/08/10 18:51:12 UTC

svn commit: r1512798 - in /commons/proper/configuration/trunk/src: main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java

Author: oheger
Date: Sat Aug 10 16:51:12 2013
New Revision: 1512798

URL: http://svn.apache.org/r1512798
Log:
Added a flatten() method which allows limiting the number of results.

This method is needed for the conversion of collections or arrays to single
values. Here only the first element needs to be extracted. It is more
efficient to abort the extraction process early instead of producing the full
result collection.

Modified:
    commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java
    commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java

Modified: commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java?rev=1512798&r1=1512797&r2=1512798&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java (original)
+++ commons/proper/configuration/trunk/src/main/java/org/apache/commons/configuration/convert/AbstractListDelimiterHandler.java Sat Aug 10 16:51:12 2013
@@ -119,16 +119,21 @@ public abstract class AbstractListDelimi
     protected abstract String escapeString(String s);
 
     /**
-     * Performs the actual work as advertised by the {@code parse()} method. The
-     * passed in object is evaluated (if necessary, in a recursive way), and all
-     * simple value objects it contains are extracted. They are returned as a
-     * collection.
+     * Extracts all values contained in the specified object up to the given
+     * limit. The passed in object is evaluated (if necessary in a recursive
+     * way). If it is a complex object (e.g. a collection or an array), all its
+     * elements are processed recursively and added to a target collection. The
+     * process stops if the limit is reached, but depending on the input object,
+     * it might be exceeded. (The limit is just an indicator to stop the process
+     * to avoid unnecessary work if the caller is only interested in a few
+     * values.)
      *
      * @param value the value to be processed
+     * @param limit the limit for aborting the processing
      * @return a "flat" collection containing all primitive values of
      *         the passed in object
      */
-    private Collection<?> flatten(Object value)
+    Collection<?> flatten(Object value, int limit)
     {
         if (value instanceof String)
         {
@@ -138,19 +143,20 @@ public abstract class AbstractListDelimi
         Collection<Object> result = new LinkedList<Object>();
         if (value instanceof Iterable)
         {
-            flattenIterator(result, ((Iterable<?>) value).iterator());
+            flattenIterator(result, ((Iterable<?>) value).iterator(), limit);
         }
         else if (value instanceof Iterator)
         {
-            flattenIterator(result, (Iterator<?>) value);
+            flattenIterator(result, (Iterator<?>) value, limit);
         }
         else if (value != null)
         {
             if (value.getClass().isArray())
             {
-                for (int len = Array.getLength(value), idx = 0; idx < len; idx++)
+                for (int len = Array.getLength(value), idx = 0, size = 0; idx < len
+                        && size < limit; idx++, size = result.size())
                 {
-                    result.addAll(flatten(Array.get(value, idx)));
+                    result.addAll(flatten(Array.get(value, idx), limit - size));
                 }
             }
             else
@@ -163,17 +169,34 @@ public abstract class AbstractListDelimi
     }
 
     /**
+     * Performs the actual work as advertised by the {@code parse()} method.
+     * This method delegates to {@link #flatten(Object, int)} without specifying
+     * a limit.
+     *
+     * @param value the value to be processed
+     * @return a &quot;flat&quot; collection containing all primitive values of
+     *         the passed in object
+     */
+    private Collection<?> flatten(Object value)
+    {
+        return flatten(value, Integer.MAX_VALUE);
+    }
+
+    /**
      * Flattens the given iterator. For each element in the iteration
      * {@code flatten()} is called recursively.
      *
      * @param target the target collection
      * @param it the iterator to process
+     * @param limit a limit for the number of elements to extract
      */
-    private void flattenIterator(Collection<Object> target, Iterator<?> it)
+    private void flattenIterator(Collection<Object> target, Iterator<?> it, int limit)
     {
-        while (it.hasNext())
+        int size = target.size();
+        while (size < limit && it.hasNext())
         {
-            target.addAll(flatten(it.next()));
+            target.addAll(flatten(it.next(), limit - size));
+            size = target.size();
         }
     }
 }

Modified: commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java?rev=1512798&r1=1512797&r2=1512798&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java (original)
+++ commons/proper/configuration/trunk/src/test/java/org/apache/commons/configuration/convert/TestDisabledListDelimiterHandler.java Sat Aug 10 16:51:12 2013
@@ -19,12 +19,13 @@ package org.apache.commons.configuration
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Iterator;
 
 import org.apache.commons.configuration.ListDelimiterHandler;
 import org.apache.commons.configuration.ValueTransformer;
-import org.apache.commons.configuration.convert.DisabledListDelimiterHandler;
 import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
@@ -179,4 +180,45 @@ public class TestDisabledListDelimiterHa
         handler.escapeList(Arrays.asList(VALUES),
                 ListDelimiterHandler.NOOP_TRANSFORMER);
     }
+
+    /**
+     * Tests whether a limit is applied when extracting values from an array.
+     */
+    @Test
+    public void testFlattenArrayWithLimit()
+    {
+        Collection<?> res = handler.flatten(VALUES, 1);
+        assertEquals("Wrong collection size", 1, res.size());
+        assertEquals("Wrong element", VALUES[0], res.iterator().next());
+    }
+
+    /**
+     * Tests whether a limit is applied when extracting elements from a
+     * collection.
+     */
+    @Test
+    public void testFlattenCollectionWithLimit()
+    {
+        Collection<Object> src = Arrays.asList(VALUES);
+        Collection<?> res = handler.flatten(src, 1);
+        assertEquals("Wrong collection size", 1, res.size());
+        assertEquals("Wrong element", VALUES[0], res.iterator().next());
+    }
+
+    /**
+     * Tests whether elements can be extracted from a collection that contains
+     * an array if a limit is specified.
+     */
+    @Test
+    public void testFlattenCollectionWithArrayWithLimit()
+    {
+        Collection<Object> src = new ArrayList<Object>(2);
+        src.add(STR_VALUE);
+        src.add(VALUES);
+        Collection<?> res = handler.flatten(src, 2);
+        assertEquals("Wrong collection size", 2, res.size());
+        Iterator<?> it = res.iterator();
+        assertEquals("Wrong element (1)", STR_VALUE, it.next());
+        assertEquals("Wrong element (2)", VALUES[0], it.next());
+    }
 }