    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, "before");
    063        return (final 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, "before");
    083        return (final 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, "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, "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(final IOFunction<? super R, ? extends V> after) {
    138        Objects.requireNonNull(after, "after");
    139        return (final 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(final Function<? super R, ? extends V> after) {
    158        Objects.requireNonNull(after, "after");
    159        return (final 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(final IOConsumer<? super R> after) {
    176        Objects.requireNonNull(after, "after");
    177        return (final 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(final Consumer<? super R> after) {
    194        Objects.requireNonNull(after, "after");
    195        return (final 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}