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.juneau.commons.function;
018
019import static org.apache.juneau.commons.utils.ThrowableUtils.*;
020
021import java.util.function.*;
022
023/**
024 * A functional interface representing a function that accepts one argument, produces a result, and may throw a checked exception.
025 *
026 * <p>
027 * This interface extends the standard Java {@link Function} to allow the functional method
028 * to throw checked exceptions. The default {@link #apply(Object)} method wraps any checked exceptions in a
029 * {@link RuntimeException}, making it compatible with standard {@link Function} usage while still allowing
030 * the implementation to throw checked exceptions via {@link #applyThrows(Object)}.
031 *
032 * <h5 class='section'>Features:</h5>
033 * <ul class='spaced-list'>
034 *    <li>Functional interface - can be used with lambda expressions and method references
035 *    <li>Exception support - allows checked exceptions to be thrown via {@link #applyThrows(Object)}
036 *    <li>Compatible with Function - implements {@link Function#apply(Object)} by wrapping exceptions
037 *    <li>Dual interface - can be used as both Function and ThrowingFunction
038 * </ul>
039 *
040 * <h5 class='section'>Use Cases:</h5>
041 * <ul class='spaced-list'>
042 *    <li>Transformations that may throw I/O exceptions
043 *    <li>Parsing operations that may throw validation exceptions
044 *    <li>Data conversion that may fail with checked exceptions
045 *    <li>Operations that need to propagate checked exceptions
046 * </ul>
047 *
048 * <h5 class='section'>Usage:</h5>
049 * <p class='bjava'>
050 *    <jc>// Lambda with exception</jc>
051 *    ThrowingFunction&lt;String,File&gt; <jv>fileParser</jv> = (<jv>path</jv>) -&gt; {
052 *       <jk>if</jk> (! Files.exists(Paths.get(<jv>path</jv>))) {
053 *          <jk>throw new</jk> FileNotFoundException(<js>"File not found: "</js> + <jv>path</jv>);
054 *       }
055 *       <jk>return new</jk> File(<jv>path</jv>);
056 *    };
057 *
058 *    <jc>// Using applyThrows to get checked exception</jc>
059 *    <jk>try</jk> {
060 *       File <jv>file</jv> = <jv>fileParser</jv>.applyThrows(<js>"/path/to/file"</js>);
061 *    } <jk>catch</jk> (FileNotFoundException <jv>e</jv>) {
062 *       <jc>// Handle checked exception</jc>
063 *    }
064 *
065 *    <jc>// Using apply wraps exception in RuntimeException</jc>
066 *    File <jv>file</jv> = <jv>fileParser</jv>.apply(<js>"/path/to/file"</js>);  <jc>// May throw RuntimeException</jc>
067 * </p>
068 *
069 * <h5 class='section'>Exception Handling:</h5>
070 * <ul class='spaced-list'>
071 *    <li>{@link #applyThrows(Object)} - Throws checked exceptions directly
072 *    <li>{@link #apply(Object)} - Wraps checked exceptions in {@link RuntimeException}
073 *    <li>Use {@code applyThrows} when you need to handle specific checked exceptions
074 *    <li>Use {@code apply} when you want standard Function behavior
075 * </ul>
076 *
077 * <h5 class='section'>See Also:</h5><ul>
078 *    <li class='jc'>{@link ThrowingSupplier} - Supplier that throws exceptions
079 *    <li class='jc'>{@link ThrowingConsumer} - Consumer that throws exceptions
080 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommons">juneau-commons</a>
081 * </ul>
082 *
083 * @param <T> The type of the input to the function.
084 * @param <R> The type of the result of the function.
085 */
086@FunctionalInterface
087@SuppressWarnings({
088   "java:S112" // throws Exception intentional - function may throw any checked exception
089})
090public interface ThrowingFunction<T,R> extends Function<T,R> {
091
092   /**
093    * Applies this function to the given argument, wrapping any checked exceptions in a {@link RuntimeException}.
094    *
095    * <p>
096    * This is the default implementation that makes this interface compatible with {@link Function}.
097    * It calls {@link #applyThrows(Object)} and wraps any checked exceptions.
098    *
099    * @param t The function argument.
100    * @return The function result.
101    * @throws RuntimeException if {@link #applyThrows(Object)} throws a checked exception.
102    */
103   @Override
104   default R apply(T t) {
105      try {
106         return applyThrows(t);
107      } catch (Exception e) {
108         throw toRex(e);
109      }
110   }
111
112   /**
113    * Applies this function to the given argument, potentially throwing a checked exception.
114    *
115    * <p>
116    * This is the functional method that implementations must provide. It allows checked exceptions
117    * to be thrown directly, unlike the standard {@link Function#apply(Object)} method.
118    *
119    * <h5 class='section'>Example:</h5>
120    * <p class='bjava'>
121    *    ThrowingFunction&lt;String,Integer&gt; <jv>parser</jv> = (<jv>s</jv>) -&gt; {
122    *       <jk>try</jk> {
123    *          <jk>return</jk> Integer.parseInt(<jv>s</jv>);
124    *       } <jk>catch</jk> (NumberFormatException <jv>e</jv>) {
125    *          <jk>throw new</jk> ParseException(<js>"Invalid number: "</js> + <jv>s</jv>, 0);
126    *       }
127    *    };
128    *
129    *    <jk>try</jk> {
130    *       <jk>int</jk> <jv>value</jv> = <jv>parser</jv>.applyThrows(<js>"123"</js>);
131    *    } <jk>catch</jk> (ParseException <jv>e</jv>) {
132    *       <jc>// Handle checked exception</jc>
133    *    }
134    * </p>
135    *
136    * @param t The function argument.
137    * @return The function result.
138    * @throws Exception If an error occurs during function execution.
139    */
140   R applyThrows(T t) throws Exception;
141}