001/*
002 * ============================================================================
003 * Copyright © 2002-2026 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 *
007 * Licensed to the public under the agreements of the GNU Lesser General Public
008 * License, version 3.0 (the "License"). You may obtain a copy of the License at
009 *
010 *      http://www.gnu.org/licenses/lgpl.html
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015 * License for the specific language governing permissions and limitations
016 * under the License.
017 */
018
019package org.tquadrat.foundation.function.tce;
020
021import static org.apiguardian.api.API.Status.STABLE;
022import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
023
024import org.apiguardian.api.API;
025import org.tquadrat.foundation.annotation.ClassVersion;
026import org.tquadrat.foundation.function.TriFunction;
027
028/**
029 *  <p>{@summary The TCE version of the interface
030 *  {@link TriFunction}
031 *  that represents a function that accepts three arguments and produces a
032 *  result.}</p>
033 *  <p>Different from the method
034 *  {@link TriFunction#apply(Object, Object, Object) Function.apply()}
035 *  the method
036 *  {@link #apply(Object, Object, Object)}
037 *  of this interface declares to throw a
038 *  {@linkplain Exception checked exception}.</p>
039 *  <p>This is a functional interface whose functional method is
040 *  {@link #apply(Object, Object, Object)}.</p>
041 *
042 *  @param  <A> The type of the first argument to the function.
043 *  @param  <B> The type of the second argument to the function.
044 *  @param  <C> The type of the third argument to the function.
045 *  @param  <R> The type of the result of the function.
046 *
047 *  @author Thomas Thrien - thomas.thrien@tquadrat.org
048 *  @version $Id: TCETriFunction.java 1295 2026-10-18 12:34:27Z tquadrat $
049 *  @since 0.0.5
050 *
051 *  @UMLGraph.link
052 */
053@SuppressWarnings( "ProhibitedExceptionDeclared" )
054@FunctionalInterface
055@ClassVersion( sourceVersion = "$Id: TCETriFunction.java 1295 2026-10-18 12:34:27Z tquadrat $" )
056@API( status = STABLE, since = "0.0.5" )
057public interface TCETriFunction<A,B,C,R>
058{
059        /*---------*\
060    ====** Methods **==========================================================
061        \*---------*/
062    /**
063     *  <p>{@summary Applies this function to the given arguments.}</p>
064     *
065     *  @param  firstArgument   The first function argument.
066     *  @param  secondArgument  The second function argument.
067     *  @param  thirdArgument   The third function argument.
068     *  @return The function result.
069     *  @throws Exception   Something went wrong.
070     */
071    @SuppressWarnings( "ProhibitedExceptionDeclared" )
072    public R apply( final A firstArgument, final B secondArgument, final C thirdArgument ) throws Exception;
073
074    /**
075     *  <p>{@summary Returns a composed function that first applies this
076     *  function to its input, and then applies the {@code after} function to
077     *  the result.} If evaluation of either function throws an exception, it
078     *  is relayed to the caller of the composed function.</p>
079     *
080     *  @param  <R1>    The type of the output of the {@code after} function,
081     *      and of the composed function.
082     *  @param  after   The function to apply after this function is applied.
083     *  @return A composed function that first applies this function and then
084     *      applies the {@code after} function.
085     *
086     *  @since 0.1.0
087     */
088    @API( status = STABLE, since = "0.1.0" )
089    public default <R1> TCETriFunction<A,B,C,R1> andThen( final TCEFunction<? super R, ? extends R1> after )
090    {
091        final TCETriFunction<A,B,C,R1> retValue = ( A firstArgument, B secondArgument, C thirdArgument ) -> requireNonNullArgument( after, "after" )
092            .apply( apply( firstArgument, secondArgument, thirdArgument ) );
093
094        //---* Done *----------------------------------------------------------
095        return retValue;
096    }   //  andThen()
097}
098//  interface TCETriFunction
099
100/*
101 *  End of File
102 */