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.util.Objects;
022import java.util.function.Consumer;
023import java.util.function.Function;
024import java.util.function.Supplier;
025
026/**
027 * Like {@link Function} but throws {@link IOException}.
028 *
029 * @param <T> the type of the input to the operations.
030 * @param <R> the return type of the operations.
031 * @since 2.7
032 */
033@FunctionalInterface
034public interface IOFunction<T, R> {
035
036    /**
037     * Applies this function to the given argument.
038     *
039     * @param t the function argument
040     * @return the function result
041     *
042     * @throws IOException if the function throws an IOException
043     */
044    R apply(final T t) throws IOException;
045
046    /**
047     * Returns a composed {@link IOFunction} that first applies the {@code before}
048     * function to its input, and then applies this function to the result.
049     * If evaluation of either function throws an exception, it is relayed to
050     * the caller of the composed function.
051     *
052     * @param <V> the type of input to the {@code before} function, and to the
053     *           composed function
054     * @param before the function to apply before this function is applied
055     * @return a composed function that first applies the {@code before}
056     * function and then applies this function
057     * @throws NullPointerException if before is null
058     *
059     * @see #andThen(IOFunction)
060     */
061    default <V> IOFunction<V, R> compose(final IOFunction<? super V, ? extends T> before) {
062        Objects.requireNonNull(before);
063        return (V v) -> apply(before.apply(v));
064    }
065
066    /**
067     * Returns a composed {@link IOFunction} that first applies the {@code before}
068     * function to its input, and then applies this function to the result.
069     * If evaluation of either function throws an exception, it is relayed to
070     * the caller of the composed function.
071     *
072     * @param <V> the type of input to the {@code before} function, and to the
073     *           composed function
074     * @param before the function to apply before this function is applied
075     * @return a composed function that first applies the {@code before}
076     * function and then applies this function
077     * @throws NullPointerException if before is null
078     *
079     * @see #andThen(IOFunction)
080     */
081    default <V> IOFunction<V, R> compose(final Function<? super V, ? extends T> before) {
082        Objects.requireNonNull(before);
083        return (V v) -> apply(before.apply(v));
084    }
085
086    /**
087     * Returns a composed {@link IOFunction} that first applies the {@code before}
088     * function to its input, and then applies this function to the result.
089     * If evaluation of either function throws an exception, it is relayed to
090     * the caller of the composed function.
091     *
092     * @param before the supplier which feeds the application of this function
093     * @return a composed function that first applies the {@code before}
094     * function and then applies this function
095     * @throws NullPointerException if before is null
096     *
097     * @see #andThen(IOFunction)
098     */
099    default IOSupplier<R> compose(final IOSupplier<? extends T> before) {
100        Objects.requireNonNull(before);
101        return () -> apply(before.get());
102    }
103
104    /**
105     * Returns a composed {@link IOFunction} that first applies the {@code before}
106     * function to its input, and then applies this function to the result.
107     * If evaluation of either function throws an exception, it is relayed to
108     * the caller of the composed function.
109     *
110     * @param before the supplier which feeds the application of this function
111     * @return a composed function that first applies the {@code before}
112     * function and then applies this function
113     * @throws NullPointerException if before is null
114     *
115     * @see #andThen(IOFunction)
116     */
117    default IOSupplier<R> compose(final Supplier<? extends T> before) {
118        Objects.requireNonNull(before);
119        return () -> apply(before.get());
120    }
121
122    /**
123     * Returns a composed {@link IOFunction} that first applies this function to
124     * its input, and then applies the {@code after} function to the result.
125     * If evaluation of either function throws an exception, it is relayed to
126     * the caller of the composed function.
127     *
128     * @param <V> the type of output of the {@code after} function, and of the
129     *           composed function
130     * @param after the function to apply after this function is applied
131     * @return a composed function that first applies this function and then
132     * applies the {@code after} function
133     * @throws NullPointerException if after is null
134     *
135     * @see #compose(IOFunction)
136     */
137    default <V> IOFunction<T, V> andThen(IOFunction<? super R, ? extends V> after) {
138        Objects.requireNonNull(after);
139        return (T t) -> after.apply(apply(t));
140    }
141
142    /**
143     * Returns a composed {@link IOFunction} that first applies this function to
144     * its input, and then applies the {@code after} function to the result.
145     * If evaluation of either function throws an exception, it is relayed to
146     * the caller of the composed function.
147     *
148     * @param <V> the type of output of the {@code after} function, and of the
149     *           composed function
150     * @param after the function to apply after this function is applied
151     * @return a composed function that first applies this function and then
152     * applies the {@code after} function
153     * @throws NullPointerException if after is null
154     *
155     * @see #compose(IOFunction)
156     */
157    default <V> IOFunction<T, V> andThen(Function<? super R, ? extends V> after) {
158        Objects.requireNonNull(after);
159        return (T t) -> after.apply(apply(t));
160    }
161
162    /**
163     * Returns a composed {@link IOFunction} that first applies this function to
164     * its input, and then applies the {@code after} consumer to the result.
165     * If evaluation of either function throws an exception, it is relayed to
166     * the caller of the composed function.
167     *
168     * @param after the consumer to apply after this function is applied
169     * @return a composed function that first applies this function and then
170     * applies the {@code after} consumer
171     * @throws NullPointerException if after is null
172     *
173     * @see #compose(IOFunction)
174     */
175    default IOConsumer<T> andThen(IOConsumer<? super R> after) {
176        Objects.requireNonNull(after);
177        return (T t) -> after.accept(apply(t));
178    }
179
180    /**
181     * Returns a composed {@link IOFunction} that first applies this function to
182     * its input, and then applies the {@code after} consumer to the result.
183     * If evaluation of either function throws an exception, it is relayed to
184     * the caller of the composed function.
185     *
186     * @param after the consumer to apply after this function is applied
187     * @return a composed function that first applies this function and then
188     * applies the {@code after} consumer
189     * @throws NullPointerException if after is null
190     *
191     * @see #compose(IOFunction)
192     */
193    default IOConsumer<T> andThen(Consumer<? super R> after) {
194        Objects.requireNonNull(after);
195        return (T t) -> after.accept(apply(t));
196    }
197
198    /**
199     * Returns a {@link IOFunction} that always returns its input argument.
200     *
201     * @param <T> the type of the input and output objects to the function
202     * @return a function that always returns its input argument
203     */
204    static <T> IOFunction<T, T> identity() {
205        return t -> t;
206    }
207}