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