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 an operation that accepts a single argument, returns no result, and may throw a checked exception.
025 *
026 * <p>
027 * This interface extends the standard Java {@link Consumer} to allow the functional method
028 * to throw checked exceptions. The default {@link #accept(Object)} method wraps any checked exceptions in a
029 * {@link RuntimeException}, making it compatible with standard {@link Consumer} usage while still allowing
030 * the implementation to throw checked exceptions via {@link #acceptThrows(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 #acceptThrows(Object)}
036 *    <li>Compatible with Consumer - implements {@link Consumer#accept(Object)} by wrapping exceptions
037 *    <li>Dual interface - can be used as both Consumer and ThrowingConsumer
038 * </ul>
039 *
040 * <h5 class='section'>Use Cases:</h5>
041 * <ul class='spaced-list'>
042 *    <li>Operations that may throw I/O exceptions (file writing, network operations)
043 *    <li>Validation operations that may throw validation exceptions
044 *    <li>Side-effect operations 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 *    ThrowingConsumer&lt;String&gt; <jv>fileWriter</jv> = (<jv>content</jv>) -&gt; {
052 *       Files.write(Paths.get(<js>"output.txt"</js>), <jv>content</jv>.getBytes());
053 *    };
054 *
055 *    <jc>// Using acceptThrows to get checked exception</jc>
056 *    <jk>try</jk> {
057 *       <jv>fileWriter</jv>.acceptThrows(<js>"Hello World"</js>);
058 *    } <jk>catch</jk> (IOException <jv>e</jv>) {
059 *       <jc>// Handle checked exception</jc>
060 *    }
061 *
062 *    <jc>// Using accept wraps exception in RuntimeException</jc>
063 *    <jv>fileWriter</jv>.accept(<js>"Hello World"</js>);  <jc>// May throw RuntimeException</jc>
064 * </p>
065 *
066 * <h5 class='section'>Exception Handling:</h5>
067 * <ul class='spaced-list'>
068 *    <li>{@link #acceptThrows(Object)} - Throws checked exceptions directly
069 *    <li>{@link #accept(Object)} - Wraps checked exceptions in {@link RuntimeException}
070 *    <li>Use {@code acceptThrows} when you need to handle specific checked exceptions
071 *    <li>Use {@code accept} when you want standard Consumer behavior
072 * </ul>
073 *
074 * <h5 class='section'>See Also:</h5><ul>
075 *    <li class='jc'>{@link ThrowingSupplier} - Supplier that throws exceptions
076 *    <li class='jc'>{@link ThrowingFunction} - Function that throws exceptions
077 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommons">juneau-commons</a>
078 * </ul>
079 *
080 * @param <T> The type of the input to the operation.
081 */
082@FunctionalInterface
083@SuppressWarnings({
084   "java:S112" // throws Exception intentional - consumer may throw any checked exception
085})
086public interface ThrowingConsumer<T> extends Consumer<T> {
087
088   /**
089    * Performs this operation on the given argument, wrapping any checked exceptions in a {@link RuntimeException}.
090    *
091    * <p>
092    * This is the default implementation that makes this interface compatible with {@link Consumer}.
093    * It calls {@link #acceptThrows(Object)} and wraps any checked exceptions.
094    *
095    * @param t The input argument.
096    * @throws RuntimeException if {@link #acceptThrows(Object)} throws a checked exception.
097    */
098   @Override
099   default void accept(T t) {
100      try {
101         acceptThrows(t);
102      } catch (Exception e) {
103         throw toRex(e);
104      }
105   }
106
107   /**
108    * Performs this operation on the given argument, potentially throwing a checked exception.
109    *
110    * <p>
111    * This is the functional method that implementations must provide. It allows checked exceptions
112    * to be thrown directly, unlike the standard {@link Consumer#accept(Object)} method.
113    *
114    * <h5 class='section'>Example:</h5>
115    * <p class='bjava'>
116    *    ThrowingConsumer&lt;String&gt; <jv>validator</jv> = (<jv>value</jv>) -&gt; {
117    *       <jk>if</jk> (<jv>value</jv> == <jk>null</jk> || <jv>value</jv>.isEmpty()) {
118    *          <jk>throw new</jk> ValidationException(<js>"Value cannot be empty"</js>);
119    *       }
120    *    };
121    *
122    *    <jk>try</jk> {
123    *       <jv>validator</jv>.acceptThrows(<js>""</js>);
124    *    } <jk>catch</jk> (ValidationException <jv>e</jv>) {
125    *       <jc>// Handle checked exception</jc>
126    *    }
127    * </p>
128    *
129    * @param t The input argument.
130    * @throws Exception If an error occurs during operation execution.
131    */
132   void acceptThrows(T t) throws Exception;
133}