Skip to content

Commit 21939d0

Browse files
committed
Add IOIterable
1 parent c873adc commit 21939d0

4 files changed

Lines changed: 193 additions & 0 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ The <action> type attribute can be add,update,fix,remove.
5050
<!-- FIX -->
5151
<!-- ADD -->
5252
<action dev="ggregory" type="add" issue="IO-860" due-to="Nico Strecker, Gary Gregory">Add ThrottledInputStream.Builder.setMaxBytes(long, ChronoUnit).</action>
53+
<action dev="ggregory" type="add" due-to="Gary Gregory">Add IOIterable.</action>
5354
<!-- UPDATE -->
5455
</release>
5556
<release version="2.18.0" date="2024-11-16" description="Version 2.18.0: Java 8 is required.">
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.io.function;
19+
20+
import java.io.IOException;
21+
import java.util.Objects;
22+
23+
/**
24+
* Like {@link Iterable} but throws {@link IOException}.
25+
*
26+
* @param <T> the type of elements returned by the iterable.
27+
* @since 2.19.0
28+
*/
29+
public interface IOIterable<T> {
30+
31+
/**
32+
* Like {@link Iterable#iterator()}.
33+
*
34+
* @param action The action to be performed for each element.
35+
* @throws NullPointerException if the specified action is null.
36+
* @throws IOException thrown by the given action.
37+
* @see Iterable#iterator()
38+
*/
39+
default void forEach(final IOConsumer<? super T> action) throws IOException {
40+
Objects.requireNonNull(action);
41+
iterator().forEachRemaining(action);
42+
}
43+
44+
/**
45+
* Like {@link Iterable#iterator()}.
46+
*
47+
* @return See {@link Iterable#iterator() delegate}.
48+
* @see Iterable#iterator()
49+
*/
50+
IOIterator<T> iterator();
51+
52+
/**
53+
* Like {@link Iterable#spliterator()}.
54+
*
55+
* @return See {@link Iterable#spliterator() delegate}.
56+
* @see Iterable#spliterator()
57+
*/
58+
default IOSpliterator<T> spliterator() {
59+
return IOSpliteratorAdapter.adapt(new UncheckedIOIterable<>(this).spliterator());
60+
}
61+
62+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.io.function;
19+
20+
import java.io.IOException;
21+
import java.io.UncheckedIOException;
22+
import java.util.Iterator;
23+
import java.util.Objects;
24+
25+
/**
26+
* An {@link Iterable} for an {@link IOIterable} that throws {@link UncheckedIOException} instead of {@link IOException}.
27+
* <p>
28+
* Keep package-private for now.
29+
* </p>
30+
*
31+
* @param <E> the type of elements returned by this iterator.
32+
*/
33+
final class UncheckedIOIterable<E> implements Iterable<E> {
34+
35+
private final IOIterable<E> delegate;
36+
37+
/**
38+
* Constructs a new instance.
39+
*
40+
* @param delegate The delegate
41+
*/
42+
UncheckedIOIterable(final IOIterable<E> delegate) {
43+
this.delegate = Objects.requireNonNull(delegate, "delegate");
44+
}
45+
46+
@Override
47+
public Iterator<E> iterator() {
48+
return new UncheckedIOIterator<>(delegate.iterator());
49+
}
50+
51+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.io.function;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
22+
23+
import java.io.IOException;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
26+
import java.util.Arrays;
27+
import java.util.List;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
30+
import org.junit.jupiter.api.BeforeEach;
31+
import org.junit.jupiter.api.Test;
32+
33+
/**
34+
* Tests {@link IOIterable}.
35+
*/
36+
public class IOIterableTest {
37+
38+
private static class Fixture implements IOIterable<Path> {
39+
40+
List<Path> list = Arrays.asList(Paths.get("a"), Paths.get("b"));
41+
42+
@Override
43+
public IOIterator<Path> iterator() {
44+
return IOIterator.adapt(list);
45+
}
46+
47+
}
48+
49+
private IOIterable<Path> iterable;
50+
private Fixture fixture;
51+
52+
@BeforeEach
53+
public void beforeEach() {
54+
fixture = new Fixture();
55+
iterable = fixture;
56+
}
57+
58+
@Test
59+
public void testForEach() throws IOException {
60+
final AtomicInteger ref = new AtomicInteger();
61+
assertThrows(NullPointerException.class, () -> iterable.forEach(null));
62+
iterable.forEach(e -> ref.incrementAndGet());
63+
assertEquals(2, ref.get());
64+
}
65+
66+
@Test
67+
public void testIterator() throws IOException {
68+
final AtomicInteger ref = new AtomicInteger();
69+
iterable.iterator().forEachRemaining(e -> ref.incrementAndGet());
70+
assertEquals(2, ref.get());
71+
}
72+
73+
@Test
74+
public void testSpliterator() throws IOException {
75+
final AtomicInteger ref = new AtomicInteger();
76+
iterable.spliterator().forEachRemaining(e -> ref.incrementAndGet());
77+
assertEquals(2, ref.get());
78+
}
79+
}

0 commit comments

Comments
 (0)