From: PJ Fanning Date: Thu, 23 Dec 2021 10:33:59 +0000 (+0000) Subject: [github-290] Customize Spliterator implementations for better parallelism. Thanks... X-Git-Tag: REL_5_2_0~51 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d6ab8e844442607965eb749d42c67d7c9f0f5495;p=poi.git [github-290] Customize Spliterator implementations for better parallelism. Thanks to Daniel Shuy. This closes #290 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1896305 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/poi-ooxml-lite-agent/src/main/java9/module-info.class b/poi-ooxml-lite-agent/src/main/java9/module-info.class index 13840f12cc..e5bdb0c1d9 100644 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 diff --git a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java index ba507c617f..4ac65c7eaa 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java +++ b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java @@ -373,6 +373,16 @@ public final class PackageRelationshipCollection implements Iterable spliterator() { + return relationshipsByID.values().spliterator(); + } + /** * Get an iterator of a collection with all relationship with the specified * type. diff --git a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java index 7fa888b05f..4f52d26a7a 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java @@ -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 { private XDDFTextBody _parent; private XDDFParagraphProperties _properties; private final CTTextParagraph _p; @@ -115,10 +116,19 @@ public class XDDFTextParagraph { return _runs; } + @Override public Iterator iterator() { return _runs.iterator(); } + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return _runs.spliterator(); + } + /** * Append a line break. * diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index a147758403..2a0e6aded7 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -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 spliterator() { + return getTextParagraphs().spliterator(); + } + @Override public String getText() { StringBuilder out = new StringBuilder(); diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java index dbaf370e30..c75265a4db 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java @@ -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 { public Iterator iterator() { return _drawing.getShapes().iterator(); } - + + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return _drawing.getShapes().spliterator(); + } + } diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java index 531261e056..ff86b1ef30 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFRow.java @@ -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 return new CellIterator(); } + public Spliterator allCellsSpliterator() + { + return Spliterators.spliterator(allCellsIterator(), getLastCellNum(), 0); + } + public boolean hasCustomHeight() { return _height!=-1; @@ -100,15 +107,6 @@ public class SXSSFRow implements Row, Comparable this._collapsed = collapsed; } //begin of interface implementation - /** - * {@inheritDoc} - */ - @Override - public Iterator iterator() - { - return new FilledCellIterator(); - } - /** * Use this to create new cells within the row and return it. *

@@ -427,7 +425,23 @@ public class SXSSFRow implements Row, Comparable @Override public Iterator 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 spliterator() { + return (Spliterator)(Spliterator) _cells.values().spliterator(); } /** diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java index a29ce60499..d4e22810b2 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFSheet.java @@ -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 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 spliterator() { + return (Spliterator)(Spliterator) _rows.values().spliterator(); + } + /** * Flag indicating whether the sheet displays Automatic Page Breaks. * diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java index fc499ad70e..189787f96b 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java @@ -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 spliterator() { + return _wb.spliterator(); + } + protected final class SheetIterator implements Iterator { final private Iterator it; @SuppressWarnings("unchecked") @@ -786,15 +800,6 @@ public class SXSSFWorkbook implements Workbook { } } - /** - * Alias for {@link #sheetIterator()} to allow - * foreach loops - */ - @Override - public Iterator iterator() { - return sheetIterator(); - } - /** * Get the Sheet object at the given index. * diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java index 46fef0784b..6bf672db6d 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java @@ -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 spliterator() { + return getShapes().spliterator(); + } + /** * @return the sheet associated with the drawing */ diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFRow.java index b35c71e858..85543d5ff0 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -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 { } /** - * Alias for {@link #cellIterator()} to allow foreach loops: - *

-     * for(Cell cell : row){
-     *     ...
-     * }
-     * 
+ * 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 iterator() { - return cellIterator(); + @SuppressWarnings("unchecked") + public Spliterator spliterator() { + return (Spliterator)(Spliterator)_cells.values().spliterator(); } /** diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java index 96c7c9bcd3..b9c92ddd7a 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java @@ -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 spliterator() { + return getDrawing().getShapes(this).spliterator(); + } + @Override public String getShapeName() { return ctGroup.getNvGrpSpPr().getCNvPr().getName(); diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 886d25b563..e90c7a5c97 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -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 iterator() { - return rowIterator(); + @SuppressWarnings("unchecked") + public Spliterator spliterator() { + return (Spliterator)(Spliterator) _rows.values().spliterator(); } /** diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java index dfc7a69466..9cab106a14 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java @@ -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 spliterator() { + return _paragraphs.spliterator(); + } + /** * Returns the text from all paragraphs in the shape. Paragraphs are * separated by new lines. diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index 39cf9c7080..efe4893c5a 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -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 spliterator() { + return (Spliterator)(Spliterator) sheets.spliterator(); + } + private final class SheetIterator implements Iterator { final private Iterator it; @SuppressWarnings("unchecked") diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java index d1a86f2945..8c1cc90784 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java @@ -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 spliterator() { + return paragraphs.spliterator(); + } + /** * Get the list of {@link XWPFTable}s in the footnote. * @return List of tables diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index 012a09a3a6..3530c7c5fe 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -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 getBodyElementsSpliterator() { + return bodyElements.spliterator(); + } + @Override public List 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 getTablesSpliterator() { + return tables.spliterator(); + } + public Iterator getParagraphsIterator() { return paragraphs.iterator(); } + /** + * @since POI 5.2.0 + */ + public Spliterator getParagraphsSpliterator() { + return paragraphs.spliterator(); + } + /** * Returns the paragraph that of position pos */ diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFSheet.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFSheet.java index 7d92af51a6..dac5bbc746 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFSheet.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/streaming/TestSXSSFSheet.java @@ -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(); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java index 2140678d26..1267da2eeb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/record/PPDrawing.java @@ -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 spliterator() { + return getEscherRecords().spliterator(); + } + /** * Get access to the atoms inside Textboxes */ diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFGroupShape.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFGroupShape.java index cfa09db8a4..a82390e97f 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFGroupShape.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFGroupShape.java @@ -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 { return getShapes().iterator(); } + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return getShapes().spliterator(); + } + @Override public boolean removeShape(HSLFShape shape) { // TODO: implement! diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSheet.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSheet.java index 6ceafed5b4..effe54e372 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSheet.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSheet.java @@ -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 spliterator() { + return getShapes().spliterator(); + } /** * @return whether shapes on the master sheet should be shown. By default master graphics is turned off. diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java index 129c61c0f3..2612b17692 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java @@ -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 spliterator() { + return _runs.spliterator(); + } + @Override public Double getLeftMargin() { Integer val = null; diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java index 8efa7cadb1..8d99617e7b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFTextShape.java @@ -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 { return _paragraphs.iterator(); } + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return _paragraphs.spliterator(); + } + @Override public Insets2D getInsets() { return new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset()); diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherArrayProperty.java b/poi/src/main/java/org/apache/poi/ddf/EscherArrayProperty.java index 07731c97bb..e135623c4b 100644 --- a/poi/src/main/java/org/apache/poi/ddf/EscherArrayProperty.java +++ b/poi/src/main/java/org/apache/poi/ddf/EscherArrayProperty.java @@ -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 spliterator() { + return Spliterators.spliterator(iterator(), getNumberOfElementsInArray(), 0); + } + @Override public Map> getGenericProperties() { return GenericRecordUtil.getGenericProperties( diff --git a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java index e525d50333..74df2761a6 100644 --- a/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java +++ b/poi/src/main/java/org/apache/poi/ddf/EscherContainerRecord.java @@ -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 spliterator() { + return _childRecords.spliterator(); + } /** * replaces the internal child list with the contents of the supplied {@code childRecords} diff --git a/poi/src/main/java/org/apache/poi/hssf/record/PageBreakRecord.java b/poi/src/main/java/org/apache/poi/hssf/record/PageBreakRecord.java index eda43c94e2..1df6e28c8e 100644 --- a/poi/src/main/java/org/apache/poi/hssf/record/PageBreakRecord.java +++ b/poi/src/main/java/org/apache/poi/hssf/record/PageBreakRecord.java @@ -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 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) diff --git a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java index 172ce0e7ea..2a5789c7cb 100644 --- a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java +++ b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -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 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 getCellValueSpliterator() { + return _valuesAgg.spliterator(); + } + public IndexRecord createIndexRecord(int indexRecordOffset, int sizeOfInitialSheetRecords) { IndexRecord result = new IndexRecord(); result.setFirstRow(_firstrow); diff --git a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java index 7b53847741..d5a9ba5478 100644 --- a/poi/src/main/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/poi/src/main/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -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 iterator() { return new ValueIterator(); } + + /** + * value spliterator + * + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return Spliterators.spliterator(iterator(), getPhysicalNumberOfCells(), 0); + } } diff --git a/poi/src/main/java/org/apache/poi/hssf/record/common/UnicodeString.java b/poi/src/main/java/org/apache/poi/hssf/record/common/UnicodeString.java index 63c405aeca..37fd7e0ec5 100644 --- a/poi/src/main/java/org/apache/poi/hssf/record/common/UnicodeString.java +++ b/poi/src/main/java/org/apache/poi/hssf/record/common/UnicodeString.java @@ -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, Duplicatable, G return null; } + /** + * @since POI 5.2.0 + */ + public Spliterator 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) { diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index bf68edf821..45ac29a9eb 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -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 spliterator() { + return _shapes.spliterator(); + } + protected HSSFSheet getSheet() { return _sheet; } diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java index 4a28ca4668..83d6213b32 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFRow.java @@ -630,14 +630,6 @@ public final class HSSFRow implements Row, Comparable { { return new CellIterator(); } - /** - * Alias for {@link #cellIterator} to allow - * foreach loops - */ - @Override - public Iterator iterator() { - return cellIterator(); - } /** * An iterator over the (physical) cells in the row. diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java index 623409d684..ab7df1d733 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java @@ -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 iterator() { return shapes.iterator(); } + + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return shapes.spliterator(); + } } diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index b37f54605a..f77cc16205 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -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 iterator() { - return rowIterator(); + @SuppressWarnings("unchecked") // can this clumsy generic syntax be improved? + public Spliterator spliterator() { + return (Spliterator)(Spliterator) _rows.values().spliterator(); } - /** * used internally in the API to get the low level Sheet record represented by this * Object. diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index e2504d2712..e369488d10 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -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 iterator() { - return sheetIterator(); + @SuppressWarnings("unchecked") + public Spliterator spliterator() { + return (Spliterator)(Spliterator) _sheets.spliterator(); } private final class SheetIterator implements Iterator { diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index 3b233ab81d..cd3a1bc134 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -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 spliterator() { + return _entries.spliterator(); + } + /* ********** END begin implementation of POIFSViewable ********** */ } // end public class DirectoryNode diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java index 609578aaa9..9b3c0150b0 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java @@ -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 spliterator() { + return Spliterators.spliterator(iterator(), getEntryCount(), 0); + } + @Override public int getEntryCount() { int size = directory.getEntryCount(); diff --git a/poi/src/main/java/org/apache/poi/poifs/property/DirectoryProperty.java b/poi/src/main/java/org/apache/poi/poifs/property/DirectoryProperty.java index 0e72e089cd..b7e6356b38 100644 --- a/poi/src/main/java/org/apache/poi/poifs/property/DirectoryProperty.java +++ b/poi/src/main/java/org/apache/poi/poifs/property/DirectoryProperty.java @@ -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 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 spliterator() { + return _children.spliterator(); + } /** * Add a new child to the collection of children diff --git a/poi/src/main/java/org/apache/poi/sl/draw/geom/CustomGeometry.java b/poi/src/main/java/org/apache/poi/sl/draw/geom/CustomGeometry.java index 84ef46357f..a5157c23d9 100644 --- a/poi/src/main/java/org/apache/poi/sl/draw/geom/CustomGeometry.java +++ b/poi/src/main/java/org/apache/poi/sl/draw/geom/CustomGeometry.java @@ -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{ return paths.iterator(); } + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return paths.spliterator(); + } + public Path getTextBounds(){ return textBounds; } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java index 09528ae95a..a393e13b65 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/LookupUtils.java @@ -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 indexSpliterator() { + return Spliterators.spliterator(indexIterator(), getSize(), 0); + } default Iterator reverseIndexIterator() { return new Iterator() { int pos = getSize() - 1; @@ -138,6 +146,12 @@ public final class LookupUtils { } }; } + /** + * @since POI 5.2.0 + */ + default Spliterator reverseIndexSpliterator() { + return Spliterators.spliterator(reverseIndexIterator(), getSize(), 0); + } } private static final class RowVector implements ValueVector { diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/Row.java b/poi/src/main/java/org/apache/poi/ss/usermodel/Row.java index ff27f4e826..2ddb957274 100644 --- a/poi/src/main/java/org/apache/poi/ss/usermodel/Row.java +++ b/poi/src/main/java/org/apache/poi/ss/usermodel/Row.java @@ -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 { */ Iterator cellIterator(); + /** + * Alias for {@link #cellIterator()} to allow foreach loops: + *
+     * for(Cell cell : row){
+     *     ...
+     * }
+     * 
+ * + * @return an iterator over cells in this row. + */ + @Override + default Iterator 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 spliterator() { + return Spliterators.spliterator(cellIterator(), getPhysicalNumberOfCells(), 0); + } + /** * Returns the Sheet this row belongs to * diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/Sheet.java b/poi/src/main/java/org/apache/poi/ss/usermodel/Sheet.java index fadbb6f48b..ee03e35ea7 100644 --- a/poi/src/main/java/org/apache/poi/ss/usermodel/Sheet.java +++ b/poi/src/main/java/org/apache/poi/ss/usermodel/Sheet.java @@ -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 { */ Iterator rowIterator(); + /** + * Alias for {@link #rowIterator()} to allow foreach loops + */ + @Override + default Iterator 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 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. diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/Workbook.java b/poi/src/main/java/org/apache/poi/ss/usermodel/Workbook.java index 26a81725c0..e76637f5fd 100644 --- a/poi/src/main/java/org/apache/poi/ss/usermodel/Workbook.java +++ b/poi/src/main/java/org/apache/poi/ss/usermodel/Workbook.java @@ -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 { */ Iterator sheetIterator(); + /** + * Alias for {@link #sheetIterator()} to allow foreach loops + */ + @Override + default Iterator 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 spliterator() { + return Spliterators.spliterator(sheetIterator(), getNumberOfSheets(), 0); + } + /** * Get the number of spreadsheets in the workbook * diff --git a/poi/src/main/java/org/apache/poi/ss/util/CellRangeAddressBase.java b/poi/src/main/java/org/apache/poi/ss/util/CellRangeAddressBase.java index 482bc70f02..d8852221c4 100644 --- a/poi/src/main/java/org/apache/poi/ss/util/CellRangeAddressBase.java +++ b/poi/src/main/java/org/apache/poi/ss/util/CellRangeAddressBase.java @@ -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, 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 spliterator() { + return Spliterators.spliterator(iterator(), getNumberOfCells(), 0); + } + /** * Iterates over the cell addresses in a cell range in row major order * diff --git a/poi/src/main/java/org/apache/poi/ss/util/SSCellRange.java b/poi/src/main/java/org/apache/poi/ss/util/SSCellRange.java index c9cb954bf2..20757c092f 100644 --- a/poi/src/main/java/org/apache/poi/ss/util/SSCellRange.java +++ b/poi/src/main/java/org/apache/poi/ss/util/SSCellRange.java @@ -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 implements CellRange { public Iterator iterator() { return Stream.of(_flattenedArray).iterator(); } + + /** + * @since POI 5.2.0 + */ + @Override + public Spliterator spliterator() { + return Stream.of(_flattenedArray).spliterator(); + } } diff --git a/poi/src/main/java/org/apache/poi/util/IntMapper.java b/poi/src/main/java/org/apache/poi/util/IntMapper.java index 86d5b599ae..3a2c4f2ecd 100644 --- a/poi/src/main/java/org/apache/poi/util/IntMapper.java +++ b/poi/src/main/java/org/apache/poi/util/IntMapper.java @@ -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 implements Duplicatable { +public class IntMapper implements Duplicatable, Iterable { private final List elements; private final Map valueKeyMap; @@ -90,6 +91,13 @@ public class IntMapper implements Duplicatable { return elements.iterator(); } + /** + * @since POI 5.2.0 + */ + public Spliterator spliterator() { + return elements.spliterator(); + } + @Override public IntMapper copy() { return new IntMapper<>(this); diff --git a/poi/src/main/java9/module-info.class b/poi/src/main/java9/module-info.class index e6ce06b6d3..6274a9f771 100644 Binary files a/poi/src/main/java9/module-info.class and b/poi/src/main/java9/module-info.class differ diff --git a/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingShapes.java b/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingShapes.java index 81673da773..1ca797067f 100644 --- a/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingShapes.java +++ b/poi/src/test/java/org/apache/poi/hssf/model/TestDrawingShapes.java @@ -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 spliter = patriarch.spliterator(); + spliter.tryAdvance(s -> assertEquals(s1, s)); + spliter.tryAdvance(s -> assertEquals(s2, s)); + assertFalse(spliter.tryAdvance(s -> fail())); } } diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java index 9212aa6c8f..1a81dc5a58 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java @@ -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()); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java index aa9c8883af..ae28e00d36 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java @@ -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 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 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 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 s3 = d3.spliterator(); + assertFalse(s3.tryAdvance(entry -> fail("Should be depleted")), "Should return false when depleted"); } @Test diff --git a/poi/src/test/java/org/apache/poi/poifs/property/TestDirectoryProperty.java b/poi/src/test/java/org/apache/poi/poifs/property/TestDirectoryProperty.java index f3f855fd8d..c200bbdee0 100644 --- a/poi/src/test/java/org/apache/poi/poifs/property/TestDirectoryProperty.java +++ b/poi/src/test/java/org/apache/poi/poifs/property/TestDirectoryProperty.java @@ -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 ]; diff --git a/poi/src/test/java/org/apache/poi/sl/draw/geom/TestPresetGeometries.java b/poi/src/test/java/org/apache/poi/sl/draw/geom/TestPresetGeometries.java index 6cb3360b68..ddf6aaf1d2 100644 --- a/poi/src/test/java/org/apache/poi/sl/draw/geom/TestPresetGeometries.java +++ b/poi/src/test/java/org/apache/poi/sl/draw/geom/TestPresetGeometries.java @@ -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 diff --git a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestRow.java b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestRow.java index c2205d240c..878b5ab9e4 100644 --- a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestRow.java +++ b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestRow.java @@ -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 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(); diff --git a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java index 2b4a8697a4..6c069f0539 100644 --- a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java +++ b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestSheet.java @@ -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 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 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); + })); } } diff --git a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestWorkbook.java b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestWorkbook.java index d41a9a9aa3..1f600cf0f2 100644 --- a/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestWorkbook.java +++ b/poi/src/test/java/org/apache/poi/ss/usermodel/BaseTestWorkbook.java @@ -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 it = wb.sheetIterator(); + Spliterator 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 it = wb.sheetIterator(); + Spliterator 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 -> {})); } } diff --git a/poi/src/test/java/org/apache/poi/ss/util/TestCellRangeAddress.java b/poi/src/test/java/org/apache/poi/ss/util/TestCellRangeAddress.java index 033fb5f179..4d729d6006 100644 --- a/poi/src/test/java/org/apache/poi/ss/util/TestCellRangeAddress.java +++ b/poi/src/test/java/org/apache/poi/ss/util/TestCellRangeAddress.java @@ -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 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();