Add and reuse IOConsumer forAll(*), forEach(*)
MODIFY
src/changes/changes.xml
src/changes/changes.xml
@@ -357,7 +357,7 @@ The <action> type attribute can be add,update,fix,remove.
Add IOBiConsumer.
</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">
- Add and reuse IOConsumer.forEach(*) and forEachIndexed(*).
+ Add and reuse IOConsumer forAll(*), forEach(*), and forEachIndexed(*).
</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">
Add CharsetEncoders.

MODIFY
src/main/java/org/apache/commons/io/FileUtils.java
src/main/java/org/apache/commons/io/FileUtils.java
@@ -344,7 +344,7 @@ public static long checksumCRC32(final File file) throws IOException {
* @see #forceDelete(File)
*/
public static void cleanDirectory(final File directory) throws IOException {
- IOConsumer.forEach(listFiles(directory, null), FileUtils::forceDelete);
+ IOConsumer.forAll(listFiles(directory, null), FileUtils::forceDelete);
}
/**
@@ -357,7 +357,7 @@ public static void cleanDirectory(final File directory) throws IOException {
* @see #forceDeleteOnExit(File)
*/
private static void cleanDirectoryOnExit(final File directory) throws IOException {
- IOConsumer.forEach(listFiles(directory, null), FileUtils::forceDeleteOnExit);
+ IOConsumer.forAll(listFiles(directory, null), FileUtils::forceDeleteOnExit);
}
/**

MODIFY
src/main/java/org/apache/commons/io/IOUtils.java
src/main/java/org/apache/commons/io/IOUtils.java
@@ -395,7 +395,7 @@ public static void close(final Closeable closeable) throws IOException {
* @since 2.8.0
*/
public static void close(final Closeable... closeables) throws IOException {
- IOConsumer.forEach(closeables, IOUtils::close);
+ IOConsumer.forAll(closeables, IOUtils::close);
}
/**

MODIFY
src/main/java/org/apache/commons/io/function/IOConsumer.java
src/main/java/org/apache/commons/io/function/IOConsumer.java
package org.apache.commons.io.function;
import java.io.IOException;
-import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Stream;
IOConsumer<?> NOOP_IO_CONSUMER = t -> {/* noop */};
/**
- * Performs an action for each element of the collection.
+ * Performs an action for each element of the collection gathering any exceptions.
*
* @param <T> The element type.
* @param collection The input to stream.
* @param action The action to apply to each input element.
- * @throws IOException if an I/O error occurs.
+ * @throws IOExceptionList if any I/O errors occur.
* @since 2.12.0
*/
- static <T> void forEach(final Collection<T> collection, final IOConsumer<T> action) throws IOException {
- IOStreams.forEach(IOStreams.of(collection), action);
+ static <T> void forAll(final Iterable<T> collection, final IOConsumer<T> action) throws IOExceptionList {
+ IOStreams.forAll(IOStreams.of(collection), action);
}
/**
- * Performs an action for each element of the stream.
+ * Performs an action for each element of the collection gathering any exceptions.
*
* @param <T> The element type.
* @param stream The input to stream.
* @param action The action to apply to each input element.
- * @throws IOException if an I/O error occurs.
+ * @throws IOExceptionList if any I/O errors occur.
* @since 2.12.0
*/
- static <T> void forEach(final Stream<T> stream, final IOConsumer<T> action) throws IOException {
- IOStreams.forEach(stream, action);
+ static <T> void forAll(final Stream<T> stream, final IOConsumer<T> action) throws IOExceptionList {
+ IOStreams.forAll(stream, action, IOIndexedException::new);
}
/**
- * Performs an action for each element of this array.
+ * Performs an action for each element of the array gathering any exceptions.
*
* @param <T> The element type.
* @param array The input to stream.
* @param action The action to apply to each input element.
+ * @throws IOExceptionList if any I/O errors occur.
+ * @since 2.12.0
+ */
+ static <T> void forAll(final T[] array, final IOConsumer<T> action) throws IOExceptionList {
+ IOStreams.forAll(IOStreams.of(array), action);
+ }
+
+ /**
+ * Performs an action for each element of the collection, stopping at the first exception.
+ *
+ * @param <T> The element type.
+ * @param collection The input to stream.
+ * @param action The action to apply to each input element.
* @throws IOException if an I/O error occurs.
* @since 2.12.0
*/
- static <T> void forEach(final T[] array, final IOConsumer<T> action) throws IOException {
- IOStreams.forEach(IOStreams.of(array), action);
+ static <T> void forEach(final Iterable<T> collection, final IOConsumer<T> action) throws IOException {
+ IOStreams.forEach(IOStreams.of(collection), action);
}
/**
- * Performs an action for each element of the stream.
+ * Performs an action for each element of the stream, stopping at the first exception.
*
* @param <T> The element type.
* @param stream The input to stream.
* @param action The action to apply to each input element.
- * @throws IOExceptionList if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
+ * @since 2.12.0
+ */
+ static <T> void forEach(final Stream<T> stream, final IOConsumer<T> action) throws IOException {
+ IOStreams.forEach(stream, action);
+ }
+
+ /**
+ * Performs an action for each element of this array, stopping at the first exception.
+ *
+ * @param <T> The element type.
+ * @param array The input to stream.
+ * @param action The action to apply to each input element.
+ * @throws IOException if an I/O error occurs.
* @since 2.12.0
*/
- static <T> void forEachIndexed(final Stream<T> stream, final IOConsumer<T> action) throws IOExceptionList {
- IOStreams.forEachIndexed(stream, action, IOIndexedException::new);
+ static <T> void forEach(final T[] array, final IOConsumer<T> action) throws IOException {
+ IOStreams.forEach(IOStreams.of(array), action);
}
/**

MODIFY
src/main/java/org/apache/commons/io/function/IOStreams.java
src/main/java/org/apache/commons/io/function/IOStreams.java
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import org.apache.commons.io.IOExceptionList;
*/
class IOStreams {
- static <T> void forEach(final Stream<T> stream, final IOConsumer<T> action) throws IOException {
- forEachIndexed(stream, action, (i, e) -> e);
+ /**
+ * Accepts and throws an IOException.
+ *
+ * @param <T> The consumer type.
+ * @param consumer The consumer to accept.
+ * @param t the input argument.
+ * @throws IOException if an I/O error occurs; erased for the compiler.
+ */
+ static <T> void accept(final IOConsumer<T> consumer, T t) {
+ try {
+ consumer.accept(t);
+ } catch (IOException ex) {
+ rethrow(ex);
+ }
+ }
+
+ static <T> void forAll(final Stream<T> stream, final IOConsumer<T> action) throws IOExceptionList {
+ forAll(stream, action, (i, e) -> e);
}
- static <T> void forEachIndexed(final Stream<T> stream, final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier)
+ static <T> void forAll(final Stream<T> stream, final IOConsumer<T> action, final BiFunction<Integer, IOException, IOException> exSupplier)
throws IOExceptionList {
final AtomicReference<List<IOException>> causeList = new AtomicReference<>();
final AtomicInteger index = new AtomicInteger();
- final IOConsumer<T> actualAction = action != null ? action : IOConsumer.noop();
- if (stream != null) {
- stream.forEach(e -> {
+ final IOConsumer<T> actualAction = toIOConsumer(action);
+ of(stream).forEach(e -> {
try {
actualAction.accept(e);
- } catch (final IOException ioex) {
+ } catch (IOException ex) {
if (causeList.get() == null) {
+ // Only allocate if required
causeList.set(new ArrayList<>());
}
if (exSupplier != null) {
- causeList.get().add(exSupplier.apply(index.get(), ioex));
+ causeList.get().add(exSupplier.apply(index.get(), ex));
}
}
index.incrementAndGet();
});
IOExceptionList.checkEmpty(causeList.get(), null);
- }}
+ }
+
+ @SuppressWarnings("unused") // IOStreams.rethrow() throws
+ static <T> void forEach(final Stream<T> stream, final IOConsumer<T> action) throws IOException {
+ final IOConsumer<T> actualAction = toIOConsumer(action);
+ of(stream).forEach(e -> accept(actualAction, e));
+ }
/**
- * Null-safe version of {@link Collection#stream()}.
+ * Null-safe version of {@link StreamSupport#stream(java.util.Spliterator, boolean)}.
*
* Copied from Apache Commons Lang.
*
* @param values the elements of the new stream, may be {@code null}.
* @return the new stream on {@code values} or {@link Stream#empty()}.
*/
- static <T> Stream<T> of(final Collection<T> values) {
- return values == null ? Stream.empty() : values.stream();
+ static <T> Stream<T> of(final Iterable<T> values) {
+ return values == null ? Stream.empty() : StreamSupport.stream(values.spliterator(), false);
+ }
+
+ static <T> Stream<T> of(final Stream<T> stream) {
+ return stream == null ? Stream.empty() : stream;
}
/**
return values == null ? Stream.empty() : Stream.of(values);
}
+ /**
+ * Throws the given throwable.
+ *
+ * @param <T> The throwable cast type.
+ * @param throwable The throwable to rethrow.
+ * @return nothing because we throw.
+ * @throws T Always thrown.
+ */
+ @SuppressWarnings("unchecked")
+ static <T extends Throwable> RuntimeException rethrow(final Throwable throwable) throws T {
+ throw (T) throwable; // hack
+ }
+
+ static <T> IOConsumer<T> toIOConsumer(final IOConsumer<T> action) {
+ return action != null ? action : IOConsumer.noop();
+ }
}

MODIFY
src/main/java/org/apache/commons/io/input/ObservableInputStream.java
src/main/java/org/apache/commons/io/input/ObservableInputStream.java
@@ -175,7 +175,7 @@ public void consume() throws IOException {
}
private void forEachObserver(final IOConsumer<Observer> action) throws IOException {
- IOConsumer.forEach(observers, Objects.requireNonNull(action));
+ IOConsumer.forAll(observers, Objects.requireNonNull(action));
}
/**

MODIFY
src/main/java/org/apache/commons/io/output/FilterCollectionWriter.java
src/main/java/org/apache/commons/io/output/FilterCollectionWriter.java
@@ -85,25 +85,25 @@ protected FilterCollectionWriter(final Writer... writers) {
@Override
public Writer append(final char c) throws IOException {
- forEachWriter(w -> w.append(c));
+ forAllWriters(w -> w.append(c));
return this;
}
@Override
public Writer append(final CharSequence csq) throws IOException {
- forEachWriter(w -> w.append(csq));
+ forAllWriters(w -> w.append(csq));
return this;
}
@Override
public Writer append(final CharSequence csq, final int start, final int end) throws IOException {
- forEachWriter(w -> w.append(csq, start, end));
+ forAllWriters(w -> w.append(csq, start, end));
return this;
}
@Override
public void close() throws IOException {
- forEachWriter(Writer::close);
+ forAllWriters(Writer::close);
}
/**
@@ -113,16 +113,16 @@ public void close() throws IOException {
*/
@Override
public void flush() throws IOException {
- forEachWriter(Writer::flush);
+ forAllWriters(Writer::flush);
}
- private void forEachWriter(final IOConsumer<Writer> action) throws IOExceptionList {
- IOConsumer.forEachIndexed(writers(), action);
+ private void forAllWriters(final IOConsumer<Writer> action) throws IOExceptionList {
+ IOConsumer.forAll(writers(), action);
}
@Override
public void write(final char[] cbuf) throws IOException {
- forEachWriter(w -> w.write(cbuf));
+ forAllWriters(w -> w.write(cbuf));
}
/**
@@ -136,7 +136,7 @@ public void write(final char[] cbuf) throws IOException {
*/
@Override
public void write(final char[] cbuf, final int off, final int len) throws IOException {
- forEachWriter(w -> w.write(cbuf, off, len));
+ forAllWriters(w -> w.write(cbuf, off, len));
}
/**
@@ -146,12 +146,12 @@ public void write(final char[] cbuf, final int off, final int len) throws IOExce
*/
@Override
public void write(final int c) throws IOException {
- forEachWriter(w -> w.write(c));
+ forAllWriters(w -> w.write(c));
}
@Override
public void write(final String str) throws IOException {
- forEachWriter(w -> w.write(str));
+ forAllWriters(w -> w.write(str));
}
/**
@@ -165,7 +165,7 @@ public void write(final String str) throws IOException {
*/
@Override
public void write(final String str, final int off, final int len) throws IOException {
- forEachWriter(w -> w.write(str, off, len));
+ forAllWriters(w -> w.write(str, off, len));
}
private Stream<Writer> writers() {

Add and reuse IOConsumer forAll(*), forEach(*)