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 java.util.function.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/JuneauCommonsBasics">juneau-commons Basics</a>
078 * </ul>
079 *
080 * @param <T> The type of the input to the operation.
081 */
082@FunctionalInterface
083public interface ThrowingConsumer<T> extends Consumer<T> {
084
085   /**
086    * Performs this operation on the given argument, wrapping any checked exceptions in a {@link RuntimeException}.
087    *
088    * <p>
089    * This is the default implementation that makes this interface compatible with {@link Consumer}.
090    * It calls {@link #acceptThrows(Object)} and wraps any checked exceptions.
091    *
092    * @param t The input argument.
093    * @throws RuntimeException if {@link #acceptThrows(Object)} throws a checked exception.
094    */
095   @Override
096   default void accept(T t) {
097      try {
098         acceptThrows(t);
099      } catch (Exception e) {
100         throw toRex(e);
101      }
102   }
103
104   /**
105    * Performs this operation on the given argument, potentially throwing a checked exception.
106    *
107    * <p>
108    * This is the functional method that implementations must provide. It allows checked exceptions
109    * to be thrown directly, unlike the standard {@link Consumer#accept(Object)} method.
110    *
111    * <h5 class='section'>Example:</h5>
112    * <p class='bjava'>
113    *    ThrowingConsumer&lt;String&gt; <jv>validator</jv> = (<jv>value</jv>) -&gt; {
114    *       <jk>if</jk> (<jv>value</jv> == <jk>null</jk> || <jv>value</jv>.isEmpty()) {
115    *          <jk>throw new</jk> ValidationException(<js>"Value cannot be empty"</js>);
116    *       }
117    *    };
118    *
119    *    <jk>try</jk> {
120    *       <jv>validator</jv>.acceptThrows(<js>""</js>);
121    *    } <jk>catch</jk> (ValidationException <jv>e</jv>) {
122    *       <jc>// Handle checked exception</jc>
123    *    }
124    * </p>
125    *
126    * @param t The input argument.
127    * @throws Exception If an error occurs during operation execution.
128    */
129   void acceptThrows(T t) throws Exception;
130}