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 */
017package org.apache.commons.chain.web;
018
019import java.util.Objects;
020
021/**
022 * Represents a function that accepts one argument and produces a result.
023 * With this functional interface it is possible that an exception is thrown.
024 *
025 * <p>This is a <a href="package-summary.html">functional interface</a>
026 * whose functional method is {@link #apply(Object)}.
027 *
028 * @param <T> the type of the input to the function
029 * @param <R> the type of the result of the function
030 * @param <E> the type of the exception to the operation
031 *
032 * @since Chain 1.8
033 */
034@FunctionalInterface
035public interface CheckedFunction<T, R, E extends Throwable> {
036
037    /**
038     * Applies this function to the given argument.
039     *
040     * @param t the function argument
041     *
042     * @return the function result
043     *
044     * @throws E the possible exception
045     */
046    R apply(T t) throws E;
047
048    /**
049     * Returns a composed {@code CheckedFunction} that first applies
050     * the {@code before} function to its input, and then applies this
051     * function to the result. If evaluation of either function throws an
052     * exception, it is relayed to the caller of the composed function.
053     *
054     * @param <V> the type of input to the {@code before} function, and to the
055     *           composed function
056     * @param before the function to apply before this function is applied
057     *
058     * @return a composed function that first applies the {@code before}
059     * function and then applies this function
060     *
061     * @throws NullPointerException if before is null
062     * @throws E the possible exception
063     *
064     * @see #andThen(Function)
065     */
066    default <V> CheckedFunction<V, R, E> compose(CheckedFunction<? super V, ? extends T, E> before) throws E {
067        Objects.requireNonNull(before);
068        return (V v) -> apply(before.apply(v));
069    }
070
071    /**
072     * Returns a composed {@code CheckedFunction} that first applies
073     * this function to its input, and then applies the {@code after}
074     * function to the result. If evaluation of either function throws
075     * an exception, it is relayed to the caller of the composed function.
076     *
077     * @param <V> the type of output of the {@code after} function, and of the
078     *           composed function
079     * @param after the function to apply after this function is applied
080     *
081     * @return a composed function that first applies this function and then
082     * applies the {@code after} function
083     *
084     * @throws NullPointerException if after is null
085     * @throws E the possible exception
086     *
087     * @see #compose(Function)
088     */
089    default <V> CheckedFunction<T, V, E> andThen(CheckedFunction<? super R, ? extends V, E> after) throws E {
090        Objects.requireNonNull(after);
091        return (T t) -> after.apply(apply(t));
092    }
093
094    /**
095     * Returns a function that always returns its input argument.
096     *
097     * @param <T> the type of the input and output objects to the function
098     * @param <E> the type of the exception of the input and output objects
099     *            to the function
100     *
101     * @return a function that always returns its input argument
102     *
103     * @throws E the possible exception
104     */
105    static <T, E extends Throwable> CheckedFunction<T, T, E> identity() throws E {
106        return t -> t;
107    }
108}