001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.io.function;
019
020import java.io.IOException;
021import java.io.UncheckedIOException;
022import java.util.Objects;
023import java.util.function.Consumer;
024import java.util.stream.Stream;
025
026import org.apache.commons.io.IOExceptionList;
027import org.apache.commons.io.IOIndexedException;
028
029/**
030 * Like {@link Consumer} but throws {@link IOException}.
031 *
032 * @param <T> the type of the input to the operations.
033 * @since 2.7
034 */
035@FunctionalInterface
036public interface IOConsumer<T> {
037
038    /**
039     * Consider private.
040     */
041    IOConsumer<?> NOOP_IO_CONSUMER = t -> {
042        // noop
043    };
044
045    /**
046     * Performs an action for each element of the collection gathering any exceptions.
047     *
048     * @param action The action to apply to each input element.
049     * @param iterable The input to stream.
050     * @param <T> The element type.
051     * @throws IOExceptionList if any I/O errors occur.
052     * @since 2.12.0
053     */
054    static <T> void forAll(final IOConsumer<T> action, final Iterable<T> iterable) throws IOExceptionList {
055        IOStreams.forAll(IOStreams.of(iterable), action);
056    }
057
058    /**
059     * Performs an action for each element of the collection gathering any exceptions.
060     *
061     * @param action The action to apply to each input element.
062     * @param stream The input to stream.
063     * @param <T> The element type.
064     * @throws IOExceptionList if any I/O errors occur.
065     * @since 2.12.0
066     */
067    static <T> void forAll(final IOConsumer<T> action, final Stream<T> stream) throws IOExceptionList {
068        IOStreams.forAll(stream, action, IOIndexedException::new);
069    }
070
071    /**
072     * Performs an action for each element of the array, gathering any exceptions.
073     *
074     * @param action The action to apply to each input element.
075     * @param array The input to stream.
076     * @param <T> The element type.
077     * @throws IOExceptionList if any I/O errors occur.
078     * @since 2.12.0
079     */
080    @SafeVarargs
081    static <T> void forAll(final IOConsumer<T> action, final T... array) throws IOExceptionList {
082        IOStreams.forAll(IOStreams.of(array), action);
083    }
084
085    /**
086     * Performs an action for each element of the collection, stopping at the first exception.
087     *
088     * @param <T> The element type.
089     * @param iterable The input to stream.
090     * @param action The action to apply to each input element.
091     * @throws IOException if an I/O error occurs.
092     * @since 2.12.0
093     */
094    static <T> void forEach(final Iterable<T> iterable, final IOConsumer<T> action) throws IOException {
095        IOStreams.forEach(IOStreams.of(iterable), action);
096    }
097
098    /**
099     * Performs an action for each element of the stream, stopping at the first exception.
100     *
101     * @param <T> The element type.
102     * @param stream The input to stream.
103     * @param action The action to apply to each input element.
104     * @throws IOException if an I/O error occurs.
105     * @since 2.12.0
106     */
107    static <T> void forEach(final Stream<T> stream, final IOConsumer<T> action) throws IOException {
108        IOStreams.forEach(stream, action);
109    }
110
111    /**
112     * Performs an action for each element of this array, stopping at the first exception.
113     *
114     * @param <T> The element type.
115     * @param array The input to stream.
116     * @param action The action to apply to each input element.
117     * @throws IOException if an I/O error occurs.
118     * @since 2.12.0
119     */
120    static <T> void forEach(final T[] array, final IOConsumer<T> action) throws IOException {
121        IOStreams.forEach(IOStreams.of(array), action);
122    }
123
124    /**
125     * Returns the constant no-op consumer.
126     *
127     * @param <T> Type consumer type.
128     * @return a constant no-op consumer.
129     * @since 2.9.0
130     */
131    @SuppressWarnings("unchecked")
132    static <T> IOConsumer<T> noop() {
133        return (IOConsumer<T>) NOOP_IO_CONSUMER;
134    }
135
136    /**
137     * Performs this operation on the given argument.
138     *
139     * @param t the input argument
140     * @throws IOException if an I/O error occurs.
141     */
142    void accept(T t) throws IOException;
143
144    /**
145     * Returns a composed {@link IOConsumer} that performs, in sequence, this operation followed by the {@code after}
146     * operation. If performing either operation throws an exception, it is relayed to the caller of the composed operation.
147     * If performing this operation throws an exception, the {@code after} operation will not be performed.
148     *
149     * @param after the operation to perform after this operation
150     * @return a composed {@link Consumer} that performs in sequence this operation followed by the {@code after} operation
151     * @throws NullPointerException if {@code after} is null
152     */
153    default IOConsumer<T> andThen(final IOConsumer<? super T> after) {
154        Objects.requireNonNull(after, "after");
155        return (final T t) -> {
156            accept(t);
157            after.accept(t);
158        };
159    }
160
161    /**
162     * Creates a {@link Consumer} for this instance that throws {@link UncheckedIOException} instead of {@link IOException}.
163     *
164     * @return an UncheckedIOException Consumer.
165     * @since 2.12.0
166     */
167    default Consumer<T> asConsumer() {
168        return t -> Uncheck.accept(this, t);
169    }
170
171}