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()); + } +}