Author: onealj
Date: Tue Nov  7 00:29:09 2017
New Revision: 1814448

URL: http://svn.apache.org/viewvc?rev=1814448&view=rev
Log:
bug 61730: add iterator interface to CellRangeAddressBase for iterating over 
CellAddresses

Modified:
    poi/trunk/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
    poi/trunk/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java

Modified: poi/trunk/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java?rev=1814448&r1=1814447&r2=1814448&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java Tue Nov 
 7 00:29:09 2017
@@ -17,7 +17,12 @@
 
 package org.apache.poi.ss.util;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 import org.apache.poi.ss.SpreadsheetVersion;
@@ -29,7 +34,7 @@ import org.apache.poi.ss.usermodel.Cell;
  *
  * Common superclass of 8-bit and 16-bit versions
  */
-public abstract class CellRangeAddressBase {
+public abstract class CellRangeAddressBase implements Iterable<CellAddress> {
 
     /**
      * Indicates a cell or range is in the given relative position in a range.
@@ -160,6 +165,20 @@ public abstract class CellRangeAddressBa
            return isInRange(ref.getRow(), ref.getCol());
        }
        
+    /**
+     * Determines if the given {@link CellAddress} lies within the bounds 
+     * of this range.  
+     * <p>NOTE: It is up to the caller to ensure the reference is 
+     * for the correct sheet, since this instance doesn't have a sheet 
reference.
+     *
+     * @param ref the CellAddress to check
+     * @return True if the reference lies within the bounds, false otherwise.
+     * @see #intersects(CellRangeAddressBase) for checking if two ranges 
overlap
+     */
+    public boolean isInRange(CellAddress ref) {
+        return isInRange(ref.getRow(), ref.getColumn());
+    }
+       
        /**
         * Determines if the given {@link Cell} lies within the bounds 
         * of this range.  
@@ -263,11 +282,83 @@ public abstract class CellRangeAddressBa
        public int getNumberOfCells() {
                return (_lastRow - _firstRow + 1) * (_lastCol - _firstCol + 1);
        }
+       
+       public List<CellAddress> getCellAddresses(boolean rowMajorOrder) {
+               List<CellAddress> addresses = new ArrayList<>();
+               if (rowMajorOrder) {
+                       for (int r = _firstRow; r <= _lastRow; r++) {
+                               for (int c = _firstCol; c <= _lastCol; c++) {
+                                       addresses.add(new CellAddress(r, c));
+                               }
+                       }
+               }
+               else {
+                       for (int c = _firstCol; c <= _lastCol; c++) {
+                               for (int r = _firstRow; r <= _lastRow; r++) {
+                                       addresses.add(new CellAddress(r, c));
+                               }
+                       }
+               }
+               return Collections.unmodifiableList(addresses);
+       }
+       
+       @Override
+       public Iterator<CellAddress> iterator() {
+               return new RowMajorCellAddressIterator(this);
+       }
+       
+       /**
+        *  Iterates over the cell addresses in a cell range in row major order
+        *  
+        *  The iterator is unaffected by changes to the CellRangeAddressBase 
instance
+        *  after the iterator is created.
+        */
+       private static class RowMajorCellAddressIterator implements 
Iterator<CellAddress> {
+               private final int firstRow, firstCol, lastRow, lastCol;
+               private int r, c;
+               
+               public RowMajorCellAddressIterator(CellRangeAddressBase ref) {
+                       r = firstRow = ref.getFirstRow();
+                       c = firstCol = ref.getFirstColumn();
+                       lastRow = ref.getLastRow();
+                       lastCol = ref.getLastColumn();
+                       
+                       // whole row and whole column ranges currently not 
supported
+                       if (firstRow < 0) throw new 
IllegalStateException("First row cannot be negative.");
+                       if (firstCol < 0) throw new 
IllegalStateException("First column cannot be negative.");
+                       
+                       // avoid infinite iteration
+                       if (firstRow > lastRow) throw new 
IllegalStateException("First row cannot be greater than last row.");
+                       if (firstCol > lastCol) throw new 
IllegalStateException("First column cannot be greater than last column.");
+               }
+               
+               @Override
+               public boolean hasNext() {
+                       return r <= lastRow && c <= lastCol;
+               }
+               
+               @Override
+               public CellAddress next() {
+                       if (hasNext()) {
+                               final CellAddress addr = new CellAddress(r, c);
+                               // row major order
+                               if (c < lastCol) {
+                                       c++;
+                               }
+                               else { //c >= lastCol, end of row reached
+                                       c = firstCol; //CR
+                                       r++;              //LF
+                               }
+                               return addr;
+                       }
+                       throw new NoSuchElementException();
+               }
+       }
 
        @Override
-    public final String toString() {
-               CellReference crA = new CellReference(_firstRow, _firstCol);
-               CellReference crB = new CellReference(_lastRow, _lastCol);
+       public final String toString() {
+               CellAddress crA = new CellAddress(_firstRow, _firstCol);
+               CellAddress crB = new CellAddress(_lastRow, _lastCol);
                return getClass().getName() + " [" + crA.formatAsString() + ":" 
+ crB.formatAsString() +"]";
        }
        

Modified: 
poi/trunk/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java?rev=1814448&r1=1814447&r2=1814448&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java 
(original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java 
Tue Nov  7 00:29:09 2017
@@ -20,15 +20,17 @@ package org.apache.poi.ss.util;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 import org.apache.poi.hssf.record.TestcaseRecordInputStream;
 import org.apache.poi.util.LittleEndianOutputStream;
-
 import org.junit.Test;
 
 public final class TestCellRangeAddress {
@@ -263,6 +265,39 @@ public final class TestCellRangeAddress
         assertFalse(region.containsColumn(6));
     }
     
+    @Test
+    public void iterator() {
+        final CellRangeAddress A1_B2 = new CellRangeAddress(0, 1, 0, 1);
+        
+        // the cell address iterator iterates in row major order
+        final Iterator<CellAddress> iter = A1_B2.iterator();
+        assertEquals("A1", new CellAddress(0, 0), iter.next());
+        assertEquals("B1", new CellAddress(0, 1), iter.next());
+        assertEquals("A2", new CellAddress(1, 0), iter.next());
+        assertEquals("B2", new CellAddress(1, 1), iter.next());
+        assertFalse(iter.hasNext());
+        try {
+            iter.next();
+            fail("Expected NoSuchElementException");
+        } catch (final NoSuchElementException e) {
+            //expected
+        }
+        try {
+            iter.remove();
+            fail("Expected UnsupportedOperationException");
+        } catch (final UnsupportedOperationException e) {
+            //expected
+        }
+        
+        // for each interface
+        int count = 0;
+        for (final CellAddress addr : A1_B2) {
+            assertNotNull(addr);
+            count++;
+        }
+        assertEquals(4, count);
+    }
+    
     private static void assertIntersects(CellRangeAddress regionA, 
CellRangeAddress regionB) {
         if (!(regionA.intersects(regionB) && regionB.intersects(regionA))) {
             final String A = regionA.formatAsString();



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to