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<String> <jv>fileWriter</jv> = (<jv>content</jv>) -> { 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<String> <jv>validator</jv> = (<jv>value</jv>) -> { 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}