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; 020 021import static org.apiguardian.api.API.Status.STABLE; 022 023import java.util.function.BiConsumer; 024import java.util.function.BiFunction; 025import java.util.function.BinaryOperator; 026import java.util.function.Consumer; 027import java.util.function.Function; 028import java.util.function.Predicate; 029import java.util.function.Supplier; 030 031import org.apiguardian.api.API; 032import org.tquadrat.foundation.annotation.ClassVersion; 033import org.tquadrat.foundation.annotation.UtilityClass; 034import org.tquadrat.foundation.exception.LambdaContainerException; 035import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError; 036import org.tquadrat.foundation.function.tce.TCEBiConsumer; 037import org.tquadrat.foundation.function.tce.TCEBiFunction; 038import org.tquadrat.foundation.function.tce.TCEBinaryOperator; 039import org.tquadrat.foundation.function.tce.TCEConsumer; 040import org.tquadrat.foundation.function.tce.TCEFunction; 041import org.tquadrat.foundation.function.tce.TCEPredicate; 042import org.tquadrat.foundation.function.tce.TCESupplier; 043import org.tquadrat.foundation.function.tce.TCETriConsumer; 044import org.tquadrat.foundation.function.tce.TCETriFunction; 045 046/** 047 * <p>{@summary Some helper methods for the use with lambdas and functional 048 * interfaces.}</p> 049 * 050 * <h2>TCE Wrapper</h2> 051 * <p>The methods of the 052 * {@linkplain java.lang.FunctionalInterface functional interfaces} 053 * in the package 054 * {@link java.util.function} 055 * do not declare any checked exceptions - for good reasons, of course. But 056 * sometimes, it would be nice to have that capability.</p> 057 * <p>Using the wrapper methods in this class, you can achieve that like 058 * this:</p> 059 * <div class="source-container"><pre>… 060 * import static org.tquadrat.foundation.function.Functions.*; 061 * … 062 * 063 * … 064 * Appendable appendable = … 065 * Consumer appender = wrapConsumer( s -> appendable.append( s ) ); 066 * … 067 * 068 * … 069 * try 070 * { 071 * appender.accept( "…" ); 072 * } 073 * catch( LambdaContainerException e ) 074 * { 075 * throw (IOException) e.getCause(); 076 * } 077 * …</pre></div> 078 * <p>A 079 * {@link RuntimeException} 080 * that might be thrown by a wrapped function will not be packaged into a 081 * {@link LambdaContainerException}.</p> 082 * <p>"<i>TCE</i>" stands for "<b>T</b>hrows <b>C</b>hecked 083 * <b>E</b>xception".</p> 084 * 085 * @author Thomas Thrien - thomas.thrien@tquadrat.org 086 * @version $Id: Functions.java 1295 2026-10-18 12:34:27Z tquadrat $ 087 * @since 0.0.5 088 * 089 * @UMLGraph.link 090 */ 091@UtilityClass 092@ClassVersion( sourceVersion = "$Id: Functions.java 1295 2026-10-18 12:34:27Z tquadrat $" ) 093public final class Functions 094{ 095 /*--------------*\ 096 ====** Constructors **===================================================== 097 \*--------------*/ 098 /** 099 * <p>{@summary {@noInstance}}</p> 100 */ 101 private Functions() { throw new PrivateConstructorForStaticClassCalledError( Functions.class ); } 102 103 /*---------*\ 104 ====** Methods **========================================================== 105 \*---------*/ 106 /** 107 * <p>{@summary Wraps an instance of 108 * {@link TCEBiConsumer} 109 * to an instance of 110 * {@link BiConsumer} 111 * that throws an instance of 112 * {@link LambdaContainerException} 113 * with the causing exception, in case the wrapped instance emitted a 114 * {@linkplain Exception checked exception}.}</p> 115 * 116 * @param <T1> The type of the first argument taken by the consumer. 117 * @param <T2> The type of the second argument taken by the consumer. 118 * @param consumer The consumer to wrap. 119 * @return The wrapped consumer. 120 */ 121 @API( status = STABLE, since = "0.0.5" ) 122 public static final <T1,T2> BiConsumer<T1,T2> wrapBiConsumer( final TCEBiConsumer<? super T1, ? super T2> consumer ) 123 { 124 final BiConsumer<T1,T2> retValue = ( arg1, arg2) -> 125 { 126 try 127 { 128 consumer.accept( arg1, arg2 ); 129 } 130 catch( final RuntimeException e ) { throw e; } 131 catch( final Exception e ) 132 { 133 throw new LambdaContainerException( e ); 134 } 135 }; 136 137 //---* Done *---------------------------------------------------------- 138 return retValue; 139 } // wrapBiConsumer() 140 141 /** 142 * <p>{@summary Wraps an instance of 143 * {@link TCEBiFunction} 144 * to an instance of 145 * {@link BiFunction} 146 * that throws an instance of 147 * {@link LambdaContainerException} 148 * with the causing exception, in case the wrapped instance emitted a 149 * {@linkplain Exception checked exception}.}</p> 150 * 151 * @param <T1> The type of the first argument to the function. 152 * @param <T2> The type of the second argument to the function. 153 * @param <R> The type of the result of the function. 154 * @param function The function to wrap. 155 * @return The wrapped function. 156 */ 157 @API( status = STABLE, since = "0.0.5" ) 158 public static final <T1,T2,R> BiFunction<T1,T2,R> wrapBiFunction( final TCEBiFunction<? super T1, ? super T2, ? extends R> function ) 159 { 160 final BiFunction<T1,T2,R> retValue = (arg1,arg2) -> 161 { 162 try 163 { 164 return function.apply( arg1, arg2 ); 165 } 166 catch( final RuntimeException e ) { throw e; } 167 catch( final Exception e ) 168 { 169 throw new LambdaContainerException( e ); 170 } 171 }; 172 173 //---* Done *---------------------------------------------------------- 174 return retValue; 175 } // wrapBiFunction() 176 177 /** 178 * <p>{@summary Wraps an instance of 179 * {@link TCEBinaryOperator} 180 * to an instance of 181 * {@link BinaryOperator} 182 * that throws an instance of 183 * {@link LambdaContainerException} 184 * with the causing exception, in case the wrapped instance emitted a 185 * {@linkplain Exception checked exception}.}</p> 186 * 187 * @param <T> The type of the operands and result of the operator. 188 * @param function The function to wrap. 189 * @return The wrapped function. 190 */ 191 @API( status = STABLE, since = "0.0.5" ) 192 public static final <T> BinaryOperator<T> wrapBinaryOperator( final TCEBinaryOperator<T> function ) 193 { 194 final BinaryOperator<T> retValue = (arg1,arg2) -> 195 { 196 try 197 { 198 return function.apply( arg1, arg2 ); 199 } 200 catch( final RuntimeException e ) { throw e; } 201 catch( final Exception e ) 202 { 203 throw new LambdaContainerException( e ); 204 } 205 }; 206 207 //---* Done *---------------------------------------------------------- 208 return retValue; 209 } // wrapBinaryOperator() 210 211 /** 212 * <p>{@summary Wraps an instance of 213 * {@link TCEConsumer} 214 * to an instance of 215 * {@link Consumer} 216 * that throws an instance of 217 * {@link LambdaContainerException} 218 * with the causing exception, in case the wrapped instance emitted a 219 * {@linkplain Exception checked exception}.}</p> 220 * 221 * @param <T> The type of arguments taken by the consumer. 222 * @param consumer The consumer to wrap. 223 * @return The wrapped consumer. 224 */ 225 @API( status = STABLE, since = "0.0.5" ) 226 public static final <T> Consumer<T> wrapConsumer( final TCEConsumer<? super T> consumer ) 227 { 228 final Consumer<T> retValue = arg -> 229 { 230 try 231 { 232 consumer.accept( arg ); 233 } 234 catch( final RuntimeException e ) { throw e; } 235 catch( final Exception e ) 236 { 237 throw new LambdaContainerException( e ); 238 } 239 }; 240 241 //---* Done *---------------------------------------------------------- 242 return retValue; 243 } // wrapConsumer() 244 245 /** 246 * <p>{@summary Wraps an instance of 247 * {@link TCEFunction} 248 * to an instance of 249 * {@link Function} 250 * that throws an instance of 251 * {@link LambdaContainerException} 252 * with the causing exception, in case the wrapped instance emitted a 253 * {@linkplain Exception checked exception}.}</p> 254 * 255 * @param <T> The type of the input to the function. 256 * @param <R> The type of the result of the function. 257 * @param function The function to wrap. 258 * @return The wrapped function. 259 */ 260 @API( status = STABLE, since = "0.0.5" ) 261 public static final <T,R> Function<T,R> wrapFunction( final TCEFunction<? super T, ? extends R> function ) 262 { 263 final Function<T,R> retValue = arg -> 264 { 265 try 266 { 267 return function.apply( arg ); 268 } 269 catch( final RuntimeException e ) { throw e; } 270 catch( final Exception e ) 271 { 272 throw new LambdaContainerException( e ); 273 } 274 }; 275 276 //---* Done *---------------------------------------------------------- 277 return retValue; 278 } // wrapFunction() 279 280 /** 281 * <p>{@summary Wraps an instance of 282 * {@link TCEPredicate} 283 * to an instance of 284 * {@link Predicate} 285 * that throws an instance of 286 * {@link LambdaContainerException} 287 * with the causing exception, in case the wrapped instance emitted a 288 * {@linkplain Exception checked exception}.}</p> 289 * 290 * @param <T> The type of the input to the predicate. 291 * @param predicate The predicate to wrap. 292 * @return The wrapped predicate. 293 */ 294 @API( status = STABLE, since = "0.0.5" ) 295 public static final <T> Predicate<T> wrapPredicate( final TCEPredicate<? super T> predicate ) 296 { 297 final Predicate<T> retValue = arg -> 298 { 299 try 300 { 301 return predicate.test( arg ); 302 } 303 catch( final RuntimeException e ) { throw e; } 304 catch( final Exception e ) 305 { 306 throw new LambdaContainerException( e ); 307 } 308 }; 309 310 //---* Done *---------------------------------------------------------- 311 return retValue; 312 } // wrapPredicate() 313 314 /** 315 * <p>{@summary Wraps an instance of 316 * {@link TCESupplier} 317 * to an instance of 318 * {@link Supplier} 319 * that throws an instance of 320 * {@link LambdaContainerException} 321 * with the causing exception, in case the wrapped instance emitted a 322 * {@linkplain Exception checked exception}.}</p> 323 * 324 * @param <T> The type of results supplied by the supplier. 325 * @param supplier The supplier to wrap. 326 * @return The wrapped supplier. 327 */ 328 @API( status = STABLE, since = "0.0.5" ) 329 public static final <T> Supplier<T> wrapSupplier( final TCESupplier<? extends T> supplier ) 330 { 331 final Supplier<T> retValue = () -> 332 { 333 try 334 { 335 return supplier.get(); 336 } 337 catch( final RuntimeException e ) { throw e; } 338 catch( final Exception e ) 339 { 340 throw new LambdaContainerException( e ); 341 } 342 }; 343 344 //---* Done *---------------------------------------------------------- 345 return retValue; 346 } // wrapSupplier() 347 348 /** 349 * <p>{@summary Wraps an instance of 350 * {@link TCETriConsumer} 351 * to an instance of 352 * {@link TriConsumer} 353 * that throws an instance of 354 * {@link LambdaContainerException} 355 * with the causing exception, in case the wrapped instance emitted a 356 * {@linkplain Exception checked exception}.}</p> 357 * 358 * @param <T1> The type of the first argument taken by the consumer. 359 * @param <T2> The type of the second argument taken by the consumer. 360 * @param <T3> The type of the third argument taken by the consumer. 361 * @param consumer The consumer to wrap. 362 * @return The wrapped consumer. 363 */ 364 @API( status = STABLE, since = "0.0.5" ) 365 public static final <T1,T2,T3> TriConsumer<T1,T2,T3> wrapTriConsumer( final TCETriConsumer<? super T1, ? super T2, ? super T3> consumer ) 366 { 367 final TriConsumer<T1,T2,T3> retValue = (arg1, arg2, arg3) -> 368 { 369 try 370 { 371 consumer.accept( arg1, arg2, arg3 ); 372 } 373 catch( final RuntimeException e ) { throw e; } 374 catch( final Exception e ) 375 { 376 throw new LambdaContainerException( e ); 377 } 378 }; 379 380 //---* Done *---------------------------------------------------------- 381 return retValue; 382 } // wrapTriConsumer() 383 384 /** 385 * <p>{@summary Wraps an instance of 386 * {@link TCETriFunction} 387 * to an instance of 388 * {@link TriFunction} 389 * that throws an instance of 390 * {@link LambdaContainerException} 391 * with the causing exception, in case the wrapped instance emitted a 392 * {@linkplain Exception checked exception}.}</p> 393 * 394 * @param <T1> The type of the first argument taken by the function. 395 * @param <T2> The type of the second argument taken by the function. 396 * @param <T3> The type of the third argument taken by the function. 397 * @param <R> The type of the result of the function. 398 * @param function The function to wrap. 399 * @return The wrapped function. 400 */ 401 @API( status = STABLE, since = "0.0.5" ) 402 public static final <T1,T2,T3,R> TriFunction<T1,T2,T3,R> wrapTriFunction( final TCETriFunction<? super T1, ? super T2, ? super T3, ? extends R> function ) 403 { 404 final TriFunction<T1,T2,T3,R> retValue = (arg1, arg2, arg3) -> 405 { 406 try 407 { 408 return function.apply( arg1, arg2, arg3 ); 409 } 410 catch( final RuntimeException e ) { throw e; } 411 catch( final Exception e ) 412 { 413 throw new LambdaContainerException( e ); 414 } 415 }; 416 417 //---* Done *---------------------------------------------------------- 418 return retValue; 419 } // wrapTriFunction() 420} 421// class Functions 422 423/* 424 * End of File 425 */