Author: bayard
Date: Wed Feb  3 07:31:10 2010
New Revision: 905919

URL: http://svn.apache.org/viewvc?rev=905919&view=rev
Log:
Adding Vincent Ricard's patch to CharRange.java providing an iterator that lets 
you walk the chars in the range. LANG-454

Modified:
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/CharRange.java
    
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/CharRangeTest.java

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/CharRange.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/CharRange.java?rev=905919&r1=905918&r2=905919&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/CharRange.java 
(original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/CharRange.java 
Wed Feb  3 07:31:10 2010
@@ -17,6 +17,8 @@
 package org.apache.commons.lang3;
 
 import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 /**
  * <p>A contiguous range of characters, optionally negated.</p>
@@ -241,5 +243,96 @@
         }
         return iToString;
     }
-    
+
+    // Expansions
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Returns an iterator which can be used to walk through the characters 
described by this range.</p>
+     *
+     * @return an iterator to the chars represented by this range
+     */
+    public Iterator iterator() {
+        return new CharacterIterator(this);
+    }
+
+    static class CharacterIterator implements Iterator {
+        /** The currect character */
+        private char current;
+
+        private CharRange range;
+        private boolean hasNext;
+
+        public CharacterIterator(CharRange r) {
+            range = r;
+            hasNext = true;
+
+            if (range.negated) {
+                if (range.start == 0) {
+                    if (range.end == Character.MAX_VALUE) {
+                        // This range is an empty set
+                        hasNext = false;
+                    } else {
+                        current = (char) (range.end + 1);
+                    }
+                } else {
+                    current = 0;
+                }
+            } else {
+                current = range.start;
+            }
+        }
+
+        private void prepareNext() {
+            if (range.negated) {
+                if (current == Character.MAX_VALUE) {
+                    hasNext = false;
+                } else if (current + 1 == range.start) {
+                    if (range.end == Character.MAX_VALUE) {
+                        hasNext = false;
+                    } else {
+                        current = (char) (range.end + 1);
+                    }
+                } else {
+                    current = (char) (current + 1);
+                }
+            } else if (current < range.end) {
+                current = (char) (current + 1);
+            } else {
+                hasNext = false;
+            }
+        }
+
+        /**
+         * Has the iterator not reached the end character yet?
+         *
+         * @return <code>true</code> if the iterator has yet to reach the 
character date
+         */
+        public boolean hasNext() {
+            return hasNext;
+        }
+
+        /**
+         * Return the next character in the iteration
+         *
+         * @return <code>Character</code> for the next character
+         */
+        public Object next() {
+            if (hasNext == false) {
+                throw new NoSuchElementException();
+            }
+            char cur = current;
+            prepareNext();
+            return Character.valueOf(cur);
+        }
+
+        /**
+         * Always throws UnsupportedOperationException.
+         *
+         * @throws UnsupportedOperationException
+         * @see java.util.Iterator#remove()
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }

Modified: 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/CharRangeTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/CharRangeTest.java?rev=905919&r1=905918&r2=905919&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/CharRangeTest.java
 (original)
+++ 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/CharRangeTest.java
 Wed Feb  3 07:31:10 2010
@@ -19,6 +19,8 @@
 package org.apache.commons.lang3;
 
 import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 import junit.framework.TestCase;
 
@@ -301,7 +303,73 @@
             assertEquals("The Range must not be null", e.getMessage());
         }
     }
-    
+
+    public void testIterator() {
+        CharRange a = CharRange.is('a');
+        CharRange ad = CharRange.isIn('a', 'd');
+        CharRange nota = CharRange.isNot('a');
+        CharRange emptySet = CharRange.isNotIn((char) 0, Character.MAX_VALUE);
+        CharRange notFirst = CharRange.isNotIn((char) 1, Character.MAX_VALUE);
+        CharRange notLast = CharRange.isNotIn((char) 0, (char) 
(Character.MAX_VALUE - 1));
+
+        Iterator aIt = a.iterator();
+        assertNotNull(aIt);
+        assertTrue(aIt.hasNext());
+        assertEquals(Character.valueOf('a'), aIt.next());
+        assertFalse(aIt.hasNext());
+
+        Iterator adIt = ad.iterator();
+        assertNotNull(adIt);
+        assertTrue(adIt.hasNext());
+        assertEquals(Character.valueOf('a'), adIt.next());
+        assertEquals(Character.valueOf('b'), adIt.next());
+        assertEquals(Character.valueOf('c'), adIt.next());
+        assertEquals(Character.valueOf('d'), adIt.next());
+        assertFalse(adIt.hasNext());
+
+        Iterator notaIt = nota.iterator();
+        assertNotNull(notaIt);
+        assertTrue(notaIt.hasNext());
+        while (notaIt.hasNext()) {
+            Character c = (Character) notaIt.next();
+            assertFalse('a' == c.charValue());
+        }
+
+        Iterator emptySetIt = emptySet.iterator();
+        assertNotNull(emptySetIt);
+        assertFalse(emptySetIt.hasNext());
+        try {
+            emptySetIt.next();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            assertTrue(true);
+        }
+
+        Iterator notFirstIt = notFirst.iterator();
+        assertNotNull(notFirstIt);
+        assertTrue(notFirstIt.hasNext());
+        assertEquals(Character.valueOf((char) 0), notFirstIt.next());
+        assertFalse(notFirstIt.hasNext());
+        try {
+               notFirstIt.next();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            assertTrue(true);
+        }
+
+        Iterator notLastIt = notLast.iterator();
+        assertNotNull(notLastIt);
+        assertTrue(notLastIt.hasNext());
+        assertEquals(Character.valueOf(Character.MAX_VALUE), notLastIt.next());
+        assertFalse(notLastIt.hasNext());
+        try {
+               notLastIt.next();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            assertTrue(true);
+        }
+    }
+
     //-----------------------------------------------------------------------  
  
     public void testSerialization() {
         CharRange range = CharRange.is('a');


Reply via email to