This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git

commit 21939d0094c76da6796a3a46b64373d20dbaca19
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Tue Dec 10 15:28:38 2024 -0500

    Add IOIterable
---
 src/changes/changes.xml                            |  1 +
 .../org/apache/commons/io/function/IOIterable.java | 62 +++++++++++++++++
 .../commons/io/function/UncheckedIOIterable.java   | 51 ++++++++++++++
 .../apache/commons/io/function/IOIterableTest.java | 79 ++++++++++++++++++++++
 4 files changed, 193 insertions(+)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index fb4e0f4a5..295203491 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -50,6 +50,7 @@ The <action> type attribute can be add,update,fix,remove.
       <!-- FIX -->
       <!-- ADD -->
       <action dev="ggregory" type="add" issue="IO-860" due-to="Nico Strecker, 
Gary Gregory">Add ThrottledInputStream.Builder.setMaxBytes(long, 
ChronoUnit).</action>
+      <action dev="ggregory" type="add"                due-to="Gary 
Gregory">Add IOIterable.</action>
       <!-- UPDATE -->
     </release>
     <release version="2.18.0" date="2024-11-16" description="Version 2.18.0: 
Java 8 is required.">
diff --git a/src/main/java/org/apache/commons/io/function/IOIterable.java 
b/src/main/java/org/apache/commons/io/function/IOIterable.java
new file mode 100644
index 000000000..8a5f1f3c0
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/function/IOIterable.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io.function;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Like {@link Iterable} but throws {@link IOException}.
+ *
+ * @param <T> the type of elements returned by the iterable.
+ * @since 2.19.0
+ */
+public interface IOIterable<T> {
+
+    /**
+     * Like {@link Iterable#iterator()}.
+     *
+     * @param action The action to be performed for each element.
+     * @throws NullPointerException if the specified action is null.
+     * @throws IOException thrown by the given action.
+     * @see Iterable#iterator()
+     */
+    default void forEach(final IOConsumer<? super T> action) throws 
IOException {
+        Objects.requireNonNull(action);
+        iterator().forEachRemaining(action);
+    }
+
+    /**
+     * Like {@link Iterable#iterator()}.
+     *
+     * @return See {@link Iterable#iterator() delegate}.
+     * @see Iterable#iterator()
+     */
+    IOIterator<T> iterator();
+
+    /**
+     * Like {@link Iterable#spliterator()}.
+     *
+     * @return See {@link Iterable#spliterator() delegate}.
+     * @see Iterable#spliterator()
+     */
+    default IOSpliterator<T> spliterator() {
+        return IOSpliteratorAdapter.adapt(new 
UncheckedIOIterable<>(this).spliterator());
+    }
+
+}
diff --git 
a/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java 
b/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java
new file mode 100644
index 000000000..76b733567
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io.function;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Iterator;
+import java.util.Objects;
+
+/**
+ * An {@link Iterable} for an {@link IOIterable} that throws {@link 
UncheckedIOException} instead of {@link IOException}.
+ * <p>
+ * Keep package-private for now.
+ * </p>
+ *
+ * @param <E> the type of elements returned by this iterator.
+ */
+final class UncheckedIOIterable<E> implements Iterable<E> {
+
+    private final IOIterable<E> delegate;
+
+    /**
+     * Constructs a new instance.
+     *
+     * @param delegate The delegate
+     */
+    UncheckedIOIterable(final IOIterable<E> delegate) {
+        this.delegate = Objects.requireNonNull(delegate, "delegate");
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return new UncheckedIOIterator<>(delegate.iterator());
+    }
+
+}
diff --git a/src/test/java/org/apache/commons/io/function/IOIterableTest.java 
b/src/test/java/org/apache/commons/io/function/IOIterableTest.java
new file mode 100644
index 000000000..f8f376170
--- /dev/null
+++ b/src/test/java/org/apache/commons/io/function/IOIterableTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.io.function;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link IOIterable}.
+ */
+public class IOIterableTest {
+
+    private static class Fixture implements IOIterable<Path> {
+
+        List<Path> list = Arrays.asList(Paths.get("a"), Paths.get("b"));
+
+        @Override
+        public IOIterator<Path> iterator() {
+            return IOIterator.adapt(list);
+        }
+
+    }
+
+    private IOIterable<Path> iterable;
+    private Fixture fixture;
+
+    @BeforeEach
+    public void beforeEach() {
+        fixture = new Fixture();
+        iterable = fixture;
+    }
+
+    @Test
+    public void testForEach() throws IOException {
+        final AtomicInteger ref = new AtomicInteger();
+        assertThrows(NullPointerException.class, () -> iterable.forEach(null));
+        iterable.forEach(e -> ref.incrementAndGet());
+        assertEquals(2, ref.get());
+    }
+
+    @Test
+    public void testIterator() throws IOException {
+        final AtomicInteger ref = new AtomicInteger();
+        iterable.iterator().forEachRemaining(e -> ref.incrementAndGet());
+        assertEquals(2, ref.get());
+    }
+
+    @Test
+    public void testSpliterator() throws IOException {
+        final AtomicInteger ref = new AtomicInteger();
+        iterable.spliterator().forEachRemaining(e -> ref.incrementAndGet());
+        assertEquals(2, ref.get());
+    }
+}

Reply via email to