]> source.dussan.org Git - poi.git/commitdiff
[github-290] Customize Spliterator implementations for better parallelism. Thanks...
authorPJ Fanning <fanningpj@apache.org>
Thu, 23 Dec 2021 10:33:59 +0000 (10:33 +0000)
committerPJ Fanning <fanningpj@apache.org>
Thu, 23 Dec 2021 10:33:59 +0000 (10:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1896305 13f79535-47bb-0310-9956-ffa450edef68

54 files changed:
poi-ooxml-lite-agent/src/main/java9/module-info.class
poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java
poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java
poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java
poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java
poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFRow.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java
poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java
poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFSheet.java
poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFGroupShape.java
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSheet.java
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java
poi/src/main/java/org/apache/poi/ddf/EscherArrayProperty.java
poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java
poi/src/main/java/org/apache/poi/hssf/record/PageBreakRecord.java
poi/src/main/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
poi/src/main/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
poi/src/main/java/org/apache/poi/hssf/record/common/UnicodeString.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java
poi/src/main/java/org/apache/poi/poifs/property/DirectoryProperty.java
poi/src/main/java/org/apache/poi/sl/draw/geom/CustomGeometry.java
poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java
poi/src/main/java/org/apache/poi/ss/usermodel/Row.java
poi/src/main/java/org/apache/poi/ss/usermodel/Sheet.java
poi/src/main/java/org/apache/poi/ss/usermodel/Workbook.java
poi/src/main/java/org/apache/poi/ss/util/CellRangeAddressBase.java
poi/src/main/java/org/apache/poi/ss/util/SSCellRange.java
poi/src/main/java/org/apache/poi/util/IntMapper.java
poi/src/main/java9/module-info.class
poi/src/test/java/org/apache/poi/hssf/model/TestDrawingShapes.java
poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java
poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java
poi/src/test/java/org/apache/poi/poifs/property/TestDirectoryProperty.java
poi/src/test/java/org/apache/poi/sl/draw/geom/TestPresetGeometries.java
poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestRow.java
poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java
poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestWorkbook.java
poi/src/test/java/org/apache/poi/ss/util/TestCellRangeAddress.java

index 13840f12cc8467dbad0db594399d16e847054b98..e5bdb0c1d947f6940b00d3df09d1f58237b5e260 100644 (file)
Binary files a/poi-ooxml-lite-agent/src/main/java9/module-info.class and b/poi-ooxml-lite-agent/src/main/java9/module-info.class differ
index ba507c617f34c9a99b635eb769424098f7f885f1..4ac65c7eaafe18eed0d7a60d4d782752e5dc6df0 100644 (file)
@@ -373,6 +373,16 @@ public final class PackageRelationshipCollection implements Iterable<PackageRela
         return relationshipsByID.values().iterator();
     }
 
+    /**
+     * Get this collection's spliterator.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<PackageRelationship> spliterator() {
+        return relationshipsByID.values().spliterator();
+    }
+
     /**
      * Get an iterator of a collection with all relationship with the specified
      * type.
index 7fa888b05fdf4aad0ec7c71a6845b3a5c19c5092..4f52d26a7a00001d87f06211acd1f8542eaaa8f4 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
+import java.util.Spliterator;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -48,7 +49,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
  * is the highest level text separation mechanism.
  */
 @Beta
-public class XDDFTextParagraph {
+public class XDDFTextParagraph implements Iterable<XDDFTextRun> {
     private XDDFTextBody _parent;
     private XDDFParagraphProperties _properties;
     private final CTTextParagraph _p;
@@ -115,10 +116,19 @@ public class XDDFTextParagraph {
         return _runs;
     }
 
+    @Override
     public Iterator<XDDFTextRun> iterator() {
         return _runs.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XDDFTextRun> spliterator() {
+        return _runs.spliterator();
+    }
+
     /**
      * Append a line break.
      *
index a147758403e24b3790bfbd5e0f857d34a0aa16ee..2a0e6aded7a7b71f3891ec681de1870d0d77cd29 100644 (file)
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
+import java.util.Spliterator;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -87,6 +88,14 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
         return getTextParagraphs().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XSLFTextParagraph> spliterator() {
+        return getTextParagraphs().spliterator();
+    }
+
     @Override
     public String getText() {
         StringBuilder out = new StringBuilder();
index dbaf370e3066207fb4ce5012e683f53ef6bf60e2..c75265a4dbfc2f5fffeee7fa3a614c79b748793c 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.xssf.streaming;
 
 import java.util.Iterator;
+import java.util.Spliterator;
 
 import org.apache.poi.ss.usermodel.ClientAnchor;
 import org.apache.poi.ss.usermodel.Comment;
@@ -66,6 +67,14 @@ public class SXSSFDrawing implements Drawing<XSSFShape> {
     public Iterator<XSSFShape> iterator() {
         return _drawing.getShapes().iterator();
     }
-    
+
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XSSFShape> spliterator() {
+        return _drawing.getShapes().spliterator();
+    }
+
 }
 
index 531261e056fe1ff1c2bdf8c40bde7ae86d860d22..ff86b1ef30a6082378c95280934ac9165ff04c02 100644 (file)
@@ -21,6 +21,8 @@ import java.util.Iterator;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.SortedMap;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.TreeMap;
 
 import org.apache.poi.ss.SpreadsheetVersion;
@@ -61,6 +63,11 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
         return new CellIterator();
     }
 
+    public Spliterator<Cell> allCellsSpliterator()
+    {
+        return Spliterators.spliterator(allCellsIterator(), getLastCellNum(), 0);
+    }
+
     public boolean hasCustomHeight()
     {
         return _height!=-1;
@@ -100,15 +107,6 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
         this._collapsed = collapsed;
     }
 //begin of interface implementation
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Iterator<Cell> iterator()
-    {
-        return new FilledCellIterator();
-    }
-
     /**
      * Use this to create new cells within the row and return it.
      * <p>
@@ -427,7 +425,23 @@ public class SXSSFRow implements Row, Comparable<SXSSFRow>
     @Override
     public Iterator<Cell> cellIterator()
     {
-        return iterator();
+        return new FilledCellIterator();
+    }
+
+    /**
+     * Create a spliterator over the cells from [0, getLastCellNum()).
+     * Includes blank cells, excludes empty cells
+     *
+     * Returns a spliterator over all filled cells (created via Row.createCell())
+     * Throws ConcurrentModificationException if cells are added, moved, or
+     * removed after the spliterator is created.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public Spliterator<Cell> spliterator() {
+        return (Spliterator<Cell>)(Spliterator<? extends Cell>) _cells.values().spliterator();
     }
 
     /**
index a29ce6049978973f474f2c7a0bd26596d9ec8ed6..d4e22810b21560d70a0a716fd0550d472f9052e5 100644 (file)
@@ -24,6 +24,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Spliterator;
 import java.util.TreeMap;
 
 import org.apache.poi.ss.SpreadsheetVersion;
@@ -100,11 +101,6 @@ public class SXSSFSheet implements Sheet, OoxmlSheetExtensions {
     }
 
     //start of interface implementation
-    @Override
-    public Iterator<Row> iterator() {
-        return rowIterator();
-    }
-
     /**
      * Create a new row within the sheet and return the high level representation
      *
@@ -508,6 +504,20 @@ public class SXSSFSheet implements Sheet, OoxmlSheetExtensions {
         return result;
     }
 
+    /**
+     *  Returns a spliterator of the physical rows
+     *
+     * @return a spliterator of the PHYSICAL rows.  Meaning the 3rd element may not
+     * be the third row if say for instance the second row is undefined.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public Spliterator<Row> spliterator() {
+        return (Spliterator<Row>)(Spliterator<? extends Row>) _rows.values().spliterator();
+    }
+
     /**
      * Flag indicating whether the sheet displays Automatic Page Breaks.
      *
index fc499ad70e1ab0055833d1186f04a4c38198ed3b..189787f96b716bfd0dc63921fa53c4ee59dc9e1e 100644 (file)
@@ -31,6 +31,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
 
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
 import org.apache.commons.compress.archivers.zip.Zip64Mode;
@@ -758,6 +759,19 @@ public class SXSSFWorkbook implements Workbook {
         return new SheetIterator<>();
     }
 
+    /**
+     *  Returns a spliterator of the sheets in the workbook
+     *  in sheet order. Includes hidden and very hidden sheets.
+     *
+     * @return a spliterator of the sheets.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<Sheet> spliterator() {
+        return _wb.spliterator();
+    }
+
     protected final class SheetIterator<T extends Sheet> implements Iterator<T> {
         final private Iterator<XSSFSheet> it;
         @SuppressWarnings("unchecked")
@@ -786,15 +800,6 @@ public class SXSSFWorkbook implements Workbook {
         }
     }
 
-    /**
-     * Alias for {@link #sheetIterator()} to allow
-     * foreach loops
-     */
-    @Override
-    public Iterator<Sheet> iterator() {
-        return sheetIterator();
-    }
-
     /**
      * Get the Sheet object at the given index.
      *
index 46fef0784b0a1c2573e52f49761fe318df2c2e36..6bf672db6de42f40b8a7f36ebc26cce9c0f991ec 100644 (file)
@@ -25,6 +25,7 @@ import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import javax.xml.namespace.QName;
 
@@ -724,6 +725,14 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
         return getShapes().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XSSFShape> spliterator() {
+        return getShapes().spliterator();
+    }
+
     /**
      * @return the sheet associated with the drawing
      */
index b35c71e8584f0956905be13b7fd9f15deea6fe48..85543d5ff029c74ed8a5d4be87d0612e8ad93baf 100644 (file)
@@ -22,6 +22,7 @@ import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Objects;
 import java.util.Set;
+import java.util.Spliterator;
 import java.util.TreeMap;
 
 import org.apache.poi.ss.SpreadsheetVersion;
@@ -120,18 +121,16 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
     }
 
     /**
-     * Alias for {@link #cellIterator()} to allow  foreach loops:
-     * <blockquote><pre>
-     * for(Cell cell : row){
-     *     ...
-     * }
-     * </pre></blockquote>
+     * Cell spliterator over the physically defined cells
      *
-     * @return an iterator over cells in this row.
+     * @return a spliterator over cells in this row.
+     *
+     * @since POI 5.2.0
      */
     @Override
-    public Iterator<Cell> iterator() {
-        return cellIterator();
+    @SuppressWarnings("unchecked")
+    public Spliterator<Cell> spliterator() {
+        return (Spliterator<Cell>)(Spliterator<? extends Cell>)_cells.values().spliterator();
     }
 
     /**
index 96c7c9bcd3670cddab73fcf7a6b4f5b56bf655e7..b9c92ddd7af12b8843cb24cde5c77804b1e6638c 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.xssf.usermodel;
 
 import java.util.Iterator;
+import java.util.Spliterator;
 
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.ss.usermodel.ShapeContainer;
@@ -230,6 +231,14 @@ public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XS
         return getDrawing().getShapes(this).iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XSSFShape> spliterator() {
+        return getDrawing().getShapes(this).spliterator();
+    }
+
     @Override
     public String getShapeName() {
         return ctGroup.getNvGrpSpPr().getCNvPr().getName();
index 886d25b563d0b9a454a00c473931e62870fc694c..e90c7a5c97fe6d9058a4b9f324f4a5a436a569a0 100644 (file)
@@ -2058,12 +2058,16 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
     }
 
     /**
-     * Alias for {@link #rowIterator()} to
-     *  allow foreach loops
+     * @return a spliterator of the PHYSICAL rows.  Meaning the 3rd element may not
+     * be the third row if say for instance the second row is undefined.
+     * Call getRowNum() on each row if you care which one it is.
+     *
+     * @since POI 5.2.0
      */
     @Override
-    public Iterator<Row> iterator() {
-        return rowIterator();
+    @SuppressWarnings("unchecked")
+    public Spliterator<Row> spliterator() {
+        return (Spliterator<Row>)(Spliterator<? extends Row>) _rows.values().spliterator();
     }
 
     /**
index dfc7a694668f15126512d8259a226de56025d206..9cab106a1407c089b8db26725697baf5912ab51f 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
+import java.util.Spliterator;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -167,6 +168,14 @@ public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParag
         return _paragraphs.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XSSFTextParagraph> spliterator() {
+        return _paragraphs.spliterator();
+    }
+
     /**
      * Returns the text from all paragraphs in the shape. Paragraphs are
      * separated by new lines.
index 39cf9c708052e96ae3b07c3281d441f8dab0b42b..efe4893c5a1983c90f7768c7a5c4a688efade7c9 100644 (file)
@@ -35,6 +35,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
 import java.util.regex.Pattern;
 
 import javax.xml.namespace.QName;
@@ -1269,6 +1270,20 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
         return sheetIterator();
     }
 
+    /**
+     * Returns a spliterator of the sheets in the workbook
+     * in sheet order. Includes hidden and very hidden sheets.
+     *
+     * @return a spliterator of the sheets.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    @SuppressWarnings("unchecked")
+    public Spliterator<Sheet> spliterator() {
+        return (Spliterator<Sheet>)(Spliterator<? extends Sheet>) sheets.spliterator();
+    }
+
     private final class SheetIterator<T extends Sheet> implements Iterator<T> {
         final private Iterator<T> it;
         @SuppressWarnings("unchecked")
index d1a86f2945326b132bbcd74d402bbf3aee735aee..8c1cc90784f04d5e9d91271622861c1bc68e0dab 100644 (file)
@@ -20,6 +20,7 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.poi.ooxml.POIXMLDocumentPart;
 import org.apache.poi.util.Internal;
@@ -112,6 +113,17 @@ public abstract class XWPFAbstractFootnoteEndnote  implements Iterable<XWPFParag
         return paragraphs.iterator();
     }
 
+    /**
+     * Get a spliterator over the {@link XWPFParagraph}s in the footnote.
+     * @return Spliterator over the paragraph list.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<XWPFParagraph> spliterator() {
+        return paragraphs.spliterator();
+    }
+
     /**
      * Get the list of {@link XWPFTable}s in the footnote.
      * @return List of tables
index 012a09a3a67c6b07efa1ee1cd4ec1bf69e930b89..3530c7c5fee531af7dd0bb7e82902fed45ca3e0b 100644 (file)
@@ -32,6 +32,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
 
 import javax.xml.namespace.QName;
 
@@ -348,6 +349,15 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
         return bodyElements.iterator();
     }
 
+    /**
+     * returns a Spliterator with paragraphs and tables
+     *
+     * @since POI 5.2.0
+     */
+    public Spliterator<IBodyElement> getBodyElementsSpliterator() {
+        return bodyElements.spliterator();
+    }
+
     @Override
     public List<XWPFParagraph> getParagraphs() {
         return Collections.unmodifiableList(paragraphs);
@@ -1582,10 +1592,24 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
         return tables.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public Spliterator<XWPFTable> getTablesSpliterator() {
+        return tables.spliterator();
+    }
+
     public Iterator<XWPFParagraph> getParagraphsIterator() {
         return paragraphs.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public Spliterator<XWPFParagraph> getParagraphsSpliterator() {
+        return paragraphs.spliterator();
+    }
+
     /**
      * Returns the paragraph that of position pos
      */
index 7d92af51a6973f7d2359fe687c83080f27a34e8f..dac5bbc7469bfe368a8af238c740640cee08ad39 100644 (file)
@@ -179,7 +179,9 @@ public final class TestSXSSFSheet extends BaseTestXSheet {
         assertEquals(2, row0.getRowNum(), "Row 2 knows its row number");
         assertEquals(1, sheet.getRowNum(row1), "Sheet knows Row 1's row number");
         assertEquals(2, sheet.getRowNum(row0), "Sheet knows Row 2's row number");
-        assertEquals(row1, sheet.iterator().next(), "Sheet row iteratation order should be ascending");
+        assertEquals(row1, sheet.iterator().next(), "Sheet row iteration order should be ascending");
+        sheet.spliterator().tryAdvance(row ->
+                assertEquals(row1, row, "Sheet row iteration order should be ascending"));
 
         wb.close();
     }
index 2140678d266c4c2bf4c9e071c1099157cc9db22d..1267da2eebe8fb328201e47b4affd696f3553802 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Spliterator;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
@@ -85,6 +86,14 @@ public final class PPDrawing extends RecordAtom implements Iterable<EscherRecord
         return getEscherRecords().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<EscherRecord> spliterator() {
+        return getEscherRecords().spliterator();
+    }
+
     /**
      * Get access to the atoms inside Textboxes
      */
index cfa09db8a413bde8ba3e1f6321ba3974cfc12615..a82390e97f7e3ac66070f515ab3762befe646826 100644 (file)
@@ -21,6 +21,7 @@ import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -261,6 +262,14 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
         return getShapes().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSLFShape> spliterator() {
+        return getShapes().spliterator();
+    }
+
     @Override
     public boolean removeShape(HSLFShape shape) {
         // TODO: implement!
index 6ceafed5b4e7e22052d65cda62af90cd2b24f540..effe54e372a0f82079aec744f07853e29cc36f8f 100644 (file)
@@ -22,6 +22,7 @@ import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherDgRecord;
@@ -360,6 +361,13 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
         return getShapes().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSLFShape> spliterator() {
+        return getShapes().spliterator();
+    }
 
     /**
      * @return whether shapes on the master sheet should be shown. By default master graphics is turned off.
index 129c61c0f302b017b4241fc3824b370c90b3840d..2612b17692ce698473c768cf5fd87b978ae424c6 100644 (file)
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
@@ -341,6 +342,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
         return _runs.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSLFTextRun> spliterator() {
+        return _runs.spliterator();
+    }
+
     @Override
     public Double getLeftMargin() {
         Integer val = null;
index 8efa7cadb1b1ca347990302e927c9112bbeb6c2c..8d99617e7b0a0e6a6c0c941e8716f4d23dd8c99f 100644 (file)
@@ -28,6 +28,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -704,6 +705,14 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
         return _paragraphs.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSLFTextParagraph> spliterator() {
+        return _paragraphs.spliterator();
+    }
+
     @Override
     public Insets2D getInsets() {
         return new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset());
index 07731c97bb18734724bba6815cf7fd5cfab75186..e135623c4b5fa261edd7384f8bfbb24ee56c536a 100644 (file)
@@ -20,6 +20,8 @@ package org.apache.poi.ddf;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
@@ -263,6 +265,14 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
         };
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<byte[]> spliterator() {
+        return Spliterators.spliterator(iterator(), getNumberOfElementsInArray(), 0);
+    }
+
     @Override
     public Map<String, Supplier<?>> getGenericProperties() {
         return GenericRecordUtil.getGenericProperties(
index e525d503337ad3037a6e9298e0c0a03c5def1f96..74df2761a6ead4976bbd01941d240f1a065a2ed9 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
 import java.util.function.Supplier;
 
 import org.apache.logging.log4j.LogManager;
@@ -170,6 +171,15 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl
         return Collections.unmodifiableList(_childRecords).iterator();
     }
 
+    /**
+     * @return a spliterator over the child records
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<EscherRecord> spliterator() {
+        return _childRecords.spliterator();
+    }
 
     /**
      * replaces the internal child list with the contents of the supplied {@code childRecords}
index eda43c94e2fc9ba4a9c5771332e807780abb515d..1df6e28c8e1e5a4934a9dda2438e9c0dd8a001c0 100644 (file)
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Spliterator;
 import java.util.function.Supplier;
 
 import org.apache.poi.common.usermodel.GenericRecord;
@@ -146,6 +147,13 @@ public abstract class PageBreakRecord extends StandardRecord {
         return _breaks.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public final Spliterator<Break> getBreaksSpliterator() {
+        return _breaks.spliterator();
+    }
+
    /**
     * Adds the page break at the specified parameters
     * @param main Depending on sid, will determine row or column to put page break (zero-based)
index 172ce0e7ea62f75ce7f638bc00e3135d6260a6d7..2a5789c7cb9d54cb0fd3d99932ad2ef06104e68c 100644 (file)
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
 import java.util.TreeMap;
 
 import org.apache.poi.hssf.model.RecordStream;
@@ -307,6 +308,13 @@ public final class RowRecordsAggregate extends RecordAggregate {
         return _rowRecords.values().iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public Spliterator<RowRecord> getSpliterator() {
+        return _rowRecords.values().spliterator();
+    }
+
     public int findStartOfRowOutlineGroup(int row) {
         // Find the start of the group.
         RowRecord rowRecord = this.getRow( row );
@@ -461,6 +469,15 @@ public final class RowRecordsAggregate extends RecordAggregate {
         return _valuesAgg.iterator();
     }
 
+    /**
+     * Returns a spliterator for the cell values
+     *
+     * @since POI 5.2.0
+     */
+    public Spliterator<CellValueRecordInterface> getCellValueSpliterator() {
+        return _valuesAgg.spliterator();
+    }
+
     public IndexRecord createIndexRecord(int indexRecordOffset, int sizeOfInitialSheetRecords) {
         IndexRecord result = new IndexRecord();
         result.setFirstRow(_firstrow);
index 7b53847741760c8b659ce74c885787d97dc977c3..d5a9ba5478746a5658fee7c2e8f3c202058a43ed 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.poi.hssf.record.aggregates;
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
 
 import org.apache.poi.hssf.model.RecordStream;
 import org.apache.poi.hssf.record.BlankRecord;
@@ -354,4 +356,14 @@ public final class ValueRecordsAggregate implements Iterable<CellValueRecordInte
     public Iterator<CellValueRecordInterface> iterator() {
         return new ValueIterator();
     }
+
+    /**
+     * value spliterator
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<CellValueRecordInterface> spliterator() {
+        return Spliterators.spliterator(iterator(), getPhysicalNumberOfCells(), 0);
+    }
 }
index 63c405aeca95fa208b8d8640c0c3028b071239f5..37fd7e0ec5e79dd24f9146bfde523c0741bae662 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Spliterator;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
@@ -324,6 +325,16 @@ public class UnicodeString implements Comparable<UnicodeString>, Duplicatable, G
       return null;
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public Spliterator<FormatRun> formatSpliterator() {
+        if (field_4_format_runs != null) {
+            return field_4_format_runs.spliterator();
+        }
+        return null;
+    }
+
     public void removeFormatRun(FormatRun r) {
       field_4_format_runs.remove(r);
       if (field_4_format_runs.size() == 0) {
index bf68edf82165f00f142cc885e20cd4156cb8fe3f..45ac29a9eb7f0abecdc43c85137e6ffb08be4c60 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Spliterator;
 
 import org.apache.poi.ddf.EscherComplexProperty;
 import org.apache.poi.ddf.EscherContainerRecord;
@@ -554,6 +555,14 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing<HSSFShap
         return _shapes.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSSFShape> spliterator() {
+        return _shapes.spliterator();
+    }
+
     protected HSSFSheet getSheet() {
         return _sheet;
     }
index 4a28ca4668c52ba41d4a0d773edbf0edaf7da714..83d6213b3224b506e502136ea05fc3b606d0e9ee 100644 (file)
@@ -630,14 +630,6 @@ public final class HSSFRow implements Row, Comparable<HSSFRow> {
     {
       return new CellIterator();
     }
-    /**
-     * Alias for {@link #cellIterator} to allow
-     *  foreach loops
-     */
-    @Override
-    public Iterator<Cell> iterator() {
-       return cellIterator();
-    }
 
     /**
      * An iterator over the (physical) cells in the row.
index 623409d684f9b5599f79b9bbd018852d2f35d341..ab7df1d733f5963325ce01860799ce9211c49260 100644 (file)
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.poi.ddf.DefaultEscherRecordFactory;
 import org.apache.poi.ddf.EscherBoolProperty;
@@ -410,4 +411,12 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
     public Iterator<HSSFShape> iterator() {
         return shapes.iterator();
     }
+
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<HSSFShape> spliterator() {
+        return shapes.spliterator();
+    }
 }
index b37f54605a78f4ac53c46d6a3c8983c611364f6e..f77cc162053bcbb208614392b16f6db3316fc442 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
 import java.util.TreeMap;
 import java.util.TreeSet;
 
@@ -963,15 +964,18 @@ public final class HSSFSheet implements Sheet {
     }
 
     /**
-     * Alias for {@link #rowIterator()} to allow
-     * foreach loops
+     * @return a spliterator of the PHYSICAL rows.  Meaning the 3rd element may not
+     *         be the third row if say for instance the second row is undefined.
+     *         Call getRowNum() on each row if you care which one it is.
+     *
+     * @since POI 5.2.0
      */
     @Override
-    public Iterator<Row> iterator() {
-        return rowIterator();
+    @SuppressWarnings("unchecked") // can this clumsy generic syntax be improved?
+    public Spliterator<Row> spliterator() {
+        return (Spliterator<Row>)(Spliterator<? extends Row>) _rows.values().spliterator();
     }
 
-
     /**
      * used internally in the API to get the low level Sheet record represented by this
      * Object.
index e2504d27123519f5b1e9b95ab36c6b29f4f1875c..e369488d107b8151cbf14625a25589033d9ffd75 100644 (file)
@@ -42,6 +42,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.Spliterator;
 import java.util.regex.Pattern;
 
 import org.apache.commons.codec.digest.DigestUtils;
@@ -988,12 +989,17 @@ public final class HSSFWorkbook extends POIDocument implements Workbook {
     }
 
     /**
-     * Alias for {@link #sheetIterator()} to allow
-     * foreach loops
+     * Returns a spliterator of the sheets in the workbook
+     * in sheet order. Includes hidden and very hidden sheets.
+     *
+     * @return a spliterator of the sheets.
+     *
+     * @since POI 5.2.0
      */
     @Override
-    public Iterator<Sheet> iterator() {
-        return sheetIterator();
+    @SuppressWarnings("unchecked")
+    public Spliterator<Sheet> spliterator() {
+        return (Spliterator<Sheet>)(Spliterator<? extends Sheet>) _sheets.spliterator();
     }
 
     private final class SheetIterator<T extends Sheet> implements Iterator<T> {
index 3b233ab81d4f0aad449eccdea0545f1f6e9eb3c7..cd3a1bc134b97462928cb094c40ebd16d5001d1a 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Spliterator;
 
 import org.apache.poi.hpsf.ClassID;
 import org.apache.poi.poifs.dev.POIFSViewable;
@@ -553,6 +554,16 @@ public class DirectoryNode
         return getEntries();
     }
 
+    /**
+     * Returns a Spliterator over all the entries
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<Entry> spliterator() {
+        return _entries.spliterator();
+    }
+
     /* **********  END  begin implementation of POIFSViewable ********** */
 }   // end public class DirectoryNode
 
index 609578aaa9f436c0e6896b6e9dba54ed4572cb99..9b3c0150b072f6d5cafe3bd0589c14d5fbc07c3b 100644 (file)
@@ -31,6 +31,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators;
 
 import org.apache.poi.hpsf.ClassID;
 
@@ -115,6 +117,14 @@ public class FilteringDirectoryNode implements DirectoryEntry
       return getEntries();
    }
 
+   /**
+    * @since POI 5.2.0
+    */
+   @Override
+   public Spliterator<Entry> spliterator() {
+      return Spliterators.spliterator(iterator(), getEntryCount(), 0);
+   }
+
    @Override
    public int getEntryCount() {
       int size = directory.getEntryCount();
index 0e72e089cdfcbfcb12077827d86aeac485af6732..b7e6356b38483f9b111edeebbabd412a226a697d 100644 (file)
@@ -26,6 +26,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.Spliterator;
 
 /**
  * Directory property
@@ -243,6 +244,18 @@ public class DirectoryProperty extends Property implements Parent, Iterable<Prop
     public Iterator<Property> iterator() {
         return getChildren();
     }
+    /**
+     * Get a spliterator over the children of this Parent; all elements
+     * are instances of Property.
+     *
+     * @return Spliterator of children; may refer to an empty collection
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<Property> spliterator() {
+        return _children.spliterator();
+    }
 
     /**
      * Add a new child to the collection of children
index 84ef46357fcc5dfdd7a07a0e246d5a169cb51fa6..a5157c23d9e99b86212774945ab6614015f5dcc3 100644 (file)
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.Spliterator;
 
 /**
  * Definition of a custom geometric shape
@@ -110,6 +111,14 @@ public final class CustomGeometry implements Iterable<PathIf>{
         return paths.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<PathIf> spliterator() {
+        return paths.spliterator();
+    }
+
     public Path getTextBounds(){
         return textBounds;
     }
index 09528ae95ae1fceb5394bbddaeed29c154e568b7..a393e13b6501b254b92d2aa7541eedf026715bfb 100644 (file)
@@ -21,6 +21,8 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -123,6 +125,12 @@ public final class LookupUtils {
                 }
             };
         }
+        /**
+         * @since POI 5.2.0
+         */
+        default Spliterator<Integer> indexSpliterator() {
+            return Spliterators.spliterator(indexIterator(), getSize(), 0);
+        }
         default Iterator<Integer> reverseIndexIterator() {
             return new Iterator<Integer>() {
                 int pos = getSize() - 1;
@@ -138,6 +146,12 @@ public final class LookupUtils {
                 }
             };
         }
+        /**
+         * @since POI 5.2.0
+         */
+        default Spliterator<Integer> reverseIndexSpliterator() {
+            return Spliterators.spliterator(reverseIndexIterator(), getSize(), 0);
+        }
     }
 
     private static final class RowVector implements ValueVector {
index ff27f4e826e02bada8d230d6666de3cce3e80146..2ddb95727471d8e30860d66c68b77facba33bb37 100644 (file)
@@ -18,6 +18,8 @@
 package org.apache.poi.ss.usermodel;
 
 import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
 
 /**
  * High level representation of a row of a spreadsheet.
@@ -211,6 +213,32 @@ public interface Row extends Iterable<Cell> {
      */
     Iterator<Cell> cellIterator();
 
+    /**
+     * Alias for {@link #cellIterator()} to allow  foreach loops:
+     * <blockquote><pre>
+     * for(Cell cell : row){
+     *     ...
+     * }
+     * </pre></blockquote>
+     *
+     * @return an iterator over cells in this row.
+     */
+    @Override
+    default Iterator<Cell> iterator() {
+        return cellIterator();
+    }
+
+    /**
+     * @return Cell spliterator of the physically defined cells.  Note element 4 may
+     * actually be row cell depending on how many are defined!
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    default Spliterator<Cell> spliterator() {
+        return Spliterators.spliterator(cellIterator(), getPhysicalNumberOfCells(), 0);
+    }
+
     /**
      * Returns the Sheet this row belongs to
      *
index fadbb6f48b034872207fe29839f89a1269e4e74f..ee03e35ea76cbb7b1469d757244c01ece91788c1 100644 (file)
@@ -21,6 +21,8 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
+import java.util.Spliterators;
 
 import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
@@ -375,6 +377,27 @@ public interface Sheet extends Iterable<Row> {
      */
     Iterator<Row> rowIterator();
 
+    /**
+     * Alias for {@link #rowIterator()} to allow foreach loops
+     */
+    @Override
+    default Iterator<Row> iterator() {
+        return rowIterator();
+    }
+
+    /**
+     *  Returns a spliterator of the physical rows
+     *
+     * @return a spliterator of the PHYSICAL rows.  Meaning the 3rd element may not
+     * be the third row if say for instance the second row is undefined.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    default Spliterator<Row> spliterator() {
+        return Spliterators.spliterator(rowIterator(), getPhysicalNumberOfRows(), 0);
+    }
+
     /**
      * Control if Excel should be asked to recalculate all formulas on this sheet
      * when the workbook is opened.
index 26a81725c06832757fa1983228734f4d1d949fe8..e76637f5fddf20b3c450267c902c4828a7f61492 100644 (file)
@@ -22,6 +22,8 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
+import java.util.Spliterators;
 
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.formula.EvaluationWorkbook;
@@ -220,6 +222,27 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
      */
     Iterator<Sheet> sheetIterator();
 
+    /**
+     * Alias for {@link #sheetIterator()} to allow foreach loops
+     */
+    @Override
+    default Iterator<Sheet> iterator() {
+        return sheetIterator();
+    }
+
+    /**
+     *  Returns a spliterator of the sheets in the workbook
+     *  in sheet order. Includes hidden and very hidden sheets.
+     *
+     * @return a spliterator of the sheets.
+     *
+     * @since POI 5.2.0
+     */
+    @Override
+    default Spliterator<Sheet> spliterator() {
+        return Spliterators.spliterator(sheetIterator(), getNumberOfSheets(), 0);
+    }
+
     /**
      * Get the number of spreadsheets in the workbook
      *
index 482bc70f0241693b1d7dcf0b6c0e276b1172b6ce..d8852221c475f70d861cbd6b8a068afdaf8a0df1 100644 (file)
@@ -22,6 +22,8 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.function.Supplier;
 
 import org.apache.poi.common.Duplicatable;
@@ -289,6 +291,15 @@ public abstract class CellRangeAddressBase implements Iterable<CellAddress>, Dup
         return new RowMajorCellAddressIterator(this);
     }
 
+    /**
+     * Returns a spliterator over the CellAddresses in this cell range in row-major order.
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<CellAddress> spliterator() {
+        return Spliterators.spliterator(iterator(), getNumberOfCells(), 0);
+    }
+
     /**
      *  Iterates over the cell addresses in a cell range in row major order
      *
index c9cb954bf211a98234b1bcbcf35bf6602a9178f2..20757c092faef6cf11809db5df786810d1b3966b 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.poi.ss.util;
 import java.lang.reflect.Array;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 import java.util.stream.Stream;
 
 import org.apache.poi.ss.usermodel.Cell;
@@ -119,4 +120,12 @@ public final class SSCellRange<K extends Cell> implements CellRange<K> {
     public Iterator<K> iterator() {
         return Stream.of(_flattenedArray).iterator();
     }
+
+    /**
+     * @since POI 5.2.0
+     */
+    @Override
+    public Spliterator<K> spliterator() {
+        return Stream.of(_flattenedArray).spliterator();
+    }
 }
index 86d5b599aeb02f4a359a273c2ee84f12f544f94c..3a2c4f2ecdbabcfa985c0c132f91c0f6c9a505a3 100644 (file)
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Spliterator;
 
 import org.apache.poi.common.Duplicatable;
 
@@ -37,7 +38,7 @@ import org.apache.poi.common.Duplicatable;
  * update
  */
 
-public class IntMapper<T> implements Duplicatable {
+public class IntMapper<T> implements Duplicatable, Iterable<T> {
     private final List<T> elements;
     private final Map<T, Integer> valueKeyMap;
 
@@ -90,6 +91,13 @@ public class IntMapper<T> implements Duplicatable {
         return elements.iterator();
     }
 
+    /**
+     * @since POI 5.2.0
+     */
+    public Spliterator<T> spliterator() {
+        return elements.spliterator();
+    }
+
     @Override
     public IntMapper<T> copy() {
         return new IntMapper<>(this);
index e6ce06b6d335d541870a62736af9984de41b4c4e..6274a9f771b25e7b571224bf11484302c986ee61 100644 (file)
Binary files a/poi/src/main/java9/module-info.class and b/poi/src/main/java9/module-info.class differ
index 81673da773084b520c802ce5fc08daf954b1b6bb..1ca797067ffa7c65d3ee922cd893045d27bdbe8f 100644 (file)
@@ -25,10 +25,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Spliterator;
 
 import org.apache.poi.ddf.EscherBoolProperty;
 import org.apache.poi.ddf.EscherContainerRecord;
@@ -700,6 +702,11 @@ class TestDrawingShapes {
             assertEquals(s1, iter.next());
             assertEquals(s2, iter.next());
             assertFalse(iter.hasNext());
+
+            Spliterator<HSSFShape> spliter = patriarch.spliterator();
+            spliter.tryAdvance(s -> assertEquals(s1, s));
+            spliter.tryAdvance(s -> assertEquals(s2, s));
+            assertFalse(spliter.tryAdvance(s -> fail()));
         }
     }
 
index 9212aa6c8fdebb166bebf859fd126c48041b107c..1a81dc5a5867cbb473156f86fdd4e42fe4e841d4 100644 (file)
@@ -63,6 +63,9 @@ final class TestDirectoryNode {
             }
             assertEquals(0, count);
 
+            // verify that spliterator behaves correctly
+            assertEquals(0, node.spliterator().getExactSizeIfKnown());
+
             // verify behavior of isEmpty
             assertTrue(node.isEmpty());
 
@@ -111,6 +114,9 @@ final class TestDirectoryNode {
             }
             assertEquals(2, count);
 
+            // verify that spliterator behaves correctly
+            assertEquals(2, node.spliterator().getExactSizeIfKnown());
+
             // verify behavior of isEmpty
             assertFalse(node.isEmpty());
 
index aa9c8883af55a2d052bc50d6e6cbbfc21286dbef..ae28e00d36c5fc36c505564c10e52fff364994df 100644 (file)
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.FileNotFoundException;
@@ -30,6 +31,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -77,6 +79,12 @@ final class TestFilteringDirectoryNode {
         assertEquals(dirB, i.next());
         assertEquals(eRoot, i.next());
         assertThrows(NoSuchElementException.class, i::next, "Should throw NoSuchElementException when depleted");
+
+        Spliterator<Entry> s = d.spliterator();
+        s.tryAdvance(entry -> assertEquals(dirA, entry));
+        s.tryAdvance(entry -> assertEquals(dirB, entry));
+        s.tryAdvance(entry -> assertEquals(eRoot, entry));
+        assertFalse(s.tryAdvance(entry -> fail("Should be depleted")), "Should return false when depleted");
     }
 
     @Test
@@ -98,6 +106,11 @@ final class TestFilteringDirectoryNode {
         assertEquals(dirB, i.next());
         assertThrows(NoSuchElementException.class, i::next, "Should throw NoSuchElementException when depleted");
 
+        Spliterator<Entry> s1 = d1.spliterator();
+        s1.tryAdvance(entry -> assertEquals(dirA, entry));
+        s1.tryAdvance(entry -> assertEquals(dirB, entry));
+        assertFalse(s1.tryAdvance(entry -> fail("Should be depleted")), "Should return false when depleted");
+
 
         // Filter more
         excl = Arrays.asList("NotThere", "AlsoNotThere", eRoot.getName(), dirA.getName());
@@ -115,6 +128,10 @@ final class TestFilteringDirectoryNode {
         assertEquals(dirB, i.next());
         assertThrows(NoSuchElementException.class, i::next, "Should throw NoSuchElementException when depleted");
 
+        Spliterator<Entry> s2 = d2.spliterator();
+        s2.tryAdvance(entry -> assertEquals(dirB, entry));
+        assertFalse(s2.tryAdvance(entry -> fail("Should be depleted")), "Should return false when depleted");
+
         // Filter everything
         excl = Arrays.asList("NotThere", eRoot.getName(), dirA.getName(), dirB.getName());
         FilteringDirectoryNode d3 = new FilteringDirectoryNode(fs.getRoot(), excl);
@@ -129,6 +146,9 @@ final class TestFilteringDirectoryNode {
 
         i = d3.getEntries();
         assertThrows(NoSuchElementException.class, i::next, "Should throw NoSuchElementException when depleted");
+
+        Spliterator<Entry> s3 = d3.spliterator();
+        assertFalse(s3.tryAdvance(entry -> fail("Should be depleted")), "Should return false when depleted");
     }
 
     @Test
index f3f855fd8dfa87e41338c7292e665642a70555b2..c200bbdee0bbc82d4d2daca77bad5114914bb86e 100644 (file)
@@ -110,6 +110,7 @@ final class TestDirectoryProperty {
             children.add(iter.next());
         }
         assertEquals(count, children.size());
+        assertEquals(count, _property.spliterator().getExactSizeIfKnown());
         if (count != 0)
         {
             boolean[] found = new boolean[ count ];
index 6cb3360b68ab646dbca2c6b64e73822835cbb7d9..ddf6aaf1d28dcbd71880d9118febb5f918221632 100644 (file)
@@ -24,7 +24,9 @@ import static org.junit.jupiter.api.Assertions.assertSame;
 
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
+import java.util.stream.StreamSupport;
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 class TestPresetGeometries {
@@ -41,6 +43,9 @@ class TestPresetGeometries {
                 Path2D path = p.getPath(ctx);
                 assertNotNull(path);
             }
+            StreamSupport.stream(geom.spliterator(), true)
+                    .map(p -> p.getPath(ctx))
+                    .forEach(Assertions::assertNotNull);
         }
 
         // we get the same instance on further calls
index c2205d240c4a15b872ad21c83f4ea864fd7ac3b4..878b5ab9e4fd062911d2486a72628fb7f4a0418e 100644 (file)
@@ -25,9 +25,11 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.Spliterator;
 
 import org.apache.poi.ss.ITestDataProvider;
 import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
@@ -408,6 +410,54 @@ public abstract class BaseTestRow {
         wb.close();
     }
 
+    /**
+     * Test adding cells to a row in various places and see if we can find them again.
+     */
+    @Test
+    void testSpliterator() throws IOException {
+        Workbook wb = _testDataProvider.createWorkbook();
+        Sheet sheet = wb.createSheet();
+        Row row = sheet.createRow(0);
+
+        // One cell at the beginning
+        Cell cell1 = row.createCell(1);
+        Spliterator<Cell> split = row.spliterator();
+        assertTrue(split.tryAdvance(cell -> assertSame(cell1, cell)));
+        assertFalse(split.tryAdvance(cell -> fail()));
+
+        // Add another cell at the end
+        Cell cell2 = row.createCell(99);
+        split = row.spliterator();
+        assertTrue(split.tryAdvance(cell -> assertSame(cell1, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell2, cell)));
+
+        // Add another cell at the beginning
+        Cell cell3 = row.createCell(0);
+        split = row.spliterator();
+        assertTrue(split.tryAdvance(cell -> assertSame(cell3, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell1, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell2, cell)));
+
+        // Replace cell1
+        Cell cell4 = row.createCell(1);
+        split = row.spliterator();
+        assertTrue(split.tryAdvance(cell -> assertSame(cell3, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell4, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell2, cell)));
+        assertFalse(split.tryAdvance(cell -> fail()));
+
+        // Add another cell, specifying the cellType
+        Cell cell5 = row.createCell(2, CellType.STRING);
+        split = row.spliterator();
+        assertNotNull(cell5);
+        assertTrue(split.tryAdvance(cell -> assertSame(cell3, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell4, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell5, cell)));
+        assertTrue(split.tryAdvance(cell -> assertSame(cell2, cell)));
+        assertEquals(CellType.STRING, cell5.getCellType());
+        wb.close();
+    }
+
     @Test
     void testRowStyle() throws IOException {
        Workbook wb1 = _testDataProvider.createWorkbook();
index 2b4a8697a4ae3633f46c8c3f8647d866c61f82b0..6c069f0539996e9ec9d883628ac53e7313750af3 100644 (file)
@@ -37,6 +37,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.Spliterator;
 
 import org.apache.poi.common.usermodel.HyperlinkType;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@@ -83,6 +84,9 @@ public abstract class BaseTestSheet {
             assertSame(row1, it.next());
             assertTrue(it.hasNext());
             assertSame(row2, it.next());
+            Spliterator<Row> split = sheet.spliterator();
+            assertTrue(split.tryAdvance(row -> assertSame(row1, row)));
+            assertTrue(split.tryAdvance(row -> assertSame(row2, row)));
             assertEquals(1, sheet.getLastRowNum());
 
             // Test row creation with non consecutive index
@@ -102,6 +106,12 @@ public abstract class BaseTestSheet {
             Row row2_ovrewritten_ref = it2.next();
             assertSame(row2_ovrewritten, row2_ovrewritten_ref);
             assertEquals(100.0, row2_ovrewritten_ref.getCell(0).getNumericCellValue(), 0.0);
+            Spliterator<Row> split2 = sheet.spliterator();
+            assertTrue(split2.tryAdvance(row -> assertSame(row1, row)));
+            assertTrue(split2.tryAdvance(row -> {
+                assertSame(row2_ovrewritten, row);
+                assertEquals(100.0, row.getCell(0).getNumericCellValue(), 0.0);
+            }));
         }
     }
 
index d41a9a9aa3abe6d9b320868d1559a0819cf16575..1f600cf0f2da051b866f63157ab9a9cd540a660b 100644 (file)
@@ -31,6 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.io.IOException;
 import java.util.ConcurrentModificationException;
 import java.util.Iterator;
+import java.util.Spliterator;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.ss.ITestDataProvider;
@@ -74,11 +75,15 @@ public abstract class BaseTestWorkbook {
             wb.createSheet("Sheet2");
 
             Iterator<Sheet> it = wb.sheetIterator();
+            Spliterator<Sheet> split = wb.spliterator();
             it.next();
+            split.tryAdvance(sheet -> {});
             wb.setSheetOrder("Sheet2", 1);
 
             // Iterator order should be fixed when iterator is created
             assertThrows(ConcurrentModificationException.class, it::next);
+            // Spliterator order should be fixed when spliterator is created
+            assertThrows(ConcurrentModificationException.class, () -> split.tryAdvance(sheet -> {}));
         }
     }
 
@@ -95,10 +100,15 @@ public abstract class BaseTestWorkbook {
             wb.createSheet("Sheet2");
 
             Iterator<Sheet> it = wb.sheetIterator();
+            Spliterator<Sheet> split = wb.spliterator();
+            it.next();
+            split.tryAdvance(sheet -> {});
             wb.removeSheetAt(1);
 
             // Iterator order should be fixed when iterator is created
             assertThrows(ConcurrentModificationException.class, it::next);
+            // Spliterator order should be fixed when spliterator is created
+            assertThrows(ConcurrentModificationException.class, () -> split.tryAdvance(sheet -> {}));
         }
     }
 
index 033fb5f1790fb32496bdd3c4ee687e7db67e4ba4..4d729d600620674849d6908e8f1371015fc542bf 100644 (file)
@@ -28,10 +28,13 @@ import static org.junit.jupiter.api.Assertions.fail;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.stream.StreamSupport;
 
 import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.poi.hssf.record.TestcaseRecordInputStream;
 import org.apache.poi.util.LittleEndianOutputStream;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 final class TestCellRangeAddress {
@@ -275,6 +278,29 @@ final class TestCellRangeAddress {
         assertEquals(4, count);
     }
 
+    @Test
+    void spliterator() {
+        final CellRangeAddress A1_B2 = new CellRangeAddress(0, 1, 0, 1);
+
+        // the cell address iterator iterates in row major order
+        final Spliterator<CellAddress> spliter = A1_B2.spliterator();
+        spliter.tryAdvance(addr ->
+                assertEquals(new CellAddress(0, 0), addr, "A1"));
+        spliter.tryAdvance(addr ->
+                assertEquals(new CellAddress(0, 1), addr, "B1"));
+        spliter.tryAdvance(addr ->
+                assertEquals(new CellAddress(1, 0), addr, "A2"));
+        spliter.tryAdvance(addr ->
+                assertEquals(new CellAddress(1, 1), addr, "B2"));
+        assertFalse(spliter.tryAdvance(addr -> fail()));
+
+        // stream
+        long count = StreamSupport.stream(A1_B2.spliterator(), false)
+                .peek(Assertions::assertNotNull)
+                .count();
+        assertEquals(4, count);
+    }
+
     private static void assertIntersects(CellRangeAddress regionA, CellRangeAddress regionB) {
         if (!(regionA.intersects(regionB) && regionB.intersects(regionA))) {
             final String A = regionA.formatAsString();