001/*
002 * ============================================================================
003 * Copyright © 2002-2023 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 *  <pre><code>  &hellip;
060 *  import static org.tquadrat.foundation.function.Functions.*;
061 *  &hellip;
062 *
063 *  &hellip;
064 *  Appendable appendable = &hellip;
065 *  Consumer appender = wrapConsumer( s -&gt; appendable.append( s ) );
066 *  &hellip;
067 *
068 *  &hellip;
069 *  try
070 *  {
071 *    appender.accept( "&hellip;" );
072 *  }
073 *  catch( LambdaContainerException e )
074 *  {
075 *    throw (IOException) e.getCause();
076 *  }
077 *  &hellip;</code></pre>
078 *  <p>&quot;<i>TCE</i>&quot; stands for &quot;<b>T</b>hrows <b>C</b>hecked
079 *  <b>E</b>xception&quot;.</p>
080 *
081 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
082 *  @version $Id: Functions.java 1060 2023-09-24 19:21:40Z tquadrat $
083 *  @since 0.0.5
084 *
085 *  @UMLGraph.link
086 */
087@UtilityClass
088@ClassVersion( sourceVersion = "$Id: Functions.java 1060 2023-09-24 19:21:40Z tquadrat $" )
089public final class Functions
090{
091        /*--------------*\
092    ====** Constructors **=====================================================
093        \*--------------*/
094    /**
095     *  No instance allowed for this class.
096     */
097    private Functions() { throw new PrivateConstructorForStaticClassCalledError( Functions.class ); }
098
099        /*---------*\
100    ====** Methods **==========================================================
101        \*---------*/
102    /**
103     *  Wraps an instance of
104     *  {@link TCEBiConsumer}
105     *  to an instance of
106     *  {@link BiConsumer}
107     *  that throws an instance of
108     *  {@link LambdaContainerException}
109     *  with the causing exception, in case the wrapped instance emitted a
110     *  {@linkplain Exception checked exception}.
111     *
112     *  @param  <T1> The type of the first argument taken by the consumer.
113     *  @param  <T2> The type of the second argument taken by the consumer.
114     *  @param  consumer    The consumer to wrap.
115     *  @return The wrapped consumer.
116     */
117    @API( status = STABLE, since = "0.0.5" )
118    public static final <T1,T2> BiConsumer<T1,T2> wrapBiConsumer( final TCEBiConsumer<? super T1, ? super T2> consumer )
119    {
120        final BiConsumer<T1,T2> retValue = ( arg1, arg2) ->
121        {
122            try
123            {
124                consumer.accept( arg1, arg2 );
125            }
126            catch( final Exception e )
127            {
128                throw new LambdaContainerException( e );
129            }
130        };
131
132        //---* Done *----------------------------------------------------------
133        return retValue;
134    }   //  wrapBiConsumer()
135
136    /**
137     *  Wraps an instance of
138     *  {@link TCEBiFunction}
139     *  to an instance of
140     *  {@link BiFunction}
141     *  that throws an instance of
142     *  {@link LambdaContainerException}
143     *  with the causing exception, in case the wrapped instance emitted a
144     *  {@linkplain Exception checked exception}.
145     *
146     *  @param  <T1>    The type of the first argument to the function.
147     *  @param  <T2>    The type of the second argument to the function.
148     *  @param  <R> The type of the result of the function.
149     *  @param  function    The function to wrap.
150     *  @return The wrapped function.
151     */
152    @API( status = STABLE, since = "0.0.5" )
153    public static final <T1,T2,R> BiFunction<T1,T2,R> wrapBiFunction( final TCEBiFunction<? super T1, ? super T2, ? extends R> function )
154    {
155        final BiFunction<T1,T2,R> retValue = (arg1,arg2) ->
156        {
157            try
158            {
159                return function.apply( arg1, arg2 );
160            }
161            catch( final Exception e )
162            {
163                throw new LambdaContainerException( e );
164            }
165        };
166
167        //---* Done *----------------------------------------------------------
168        return retValue;
169    }   //  wrapBiFunction()
170
171    /**
172     *  Wraps an instance of
173     *  {@link TCEBinaryOperator}
174     *  to an instance of
175     *  {@link BinaryOperator}
176     *  that throws an instance of
177     *  {@link LambdaContainerException}
178     *  with the causing exception, in case the wrapped instance emitted a
179     *  {@linkplain Exception checked exception}.
180     *
181     *  @param  <T> The type of the operands and result of the operator.
182     *  @param  function    The function to wrap.
183     *  @return The wrapped function.
184     */
185    @API( status = STABLE, since = "0.0.5" )
186    public static final <T> BinaryOperator<T> wrapBinaryOperator( final TCEBinaryOperator<T> function )
187    {
188        final BinaryOperator<T> retValue = (arg1,arg2) ->
189        {
190            try
191            {
192                return function.apply( arg1, arg2 );
193            }
194            catch( final Exception e )
195            {
196                throw new LambdaContainerException( e );
197            }
198        };
199
200        //---* Done *----------------------------------------------------------
201        return retValue;
202    }   //  wrapBinaryOperator()
203
204    /**
205     *  Wraps an instance of
206     *  {@link TCEConsumer}
207     *  to an instance of
208     *  {@link Consumer}
209     *  that throws an instance of
210     *  {@link LambdaContainerException}
211     *  with the causing exception, in case the wrapped instance emitted a
212     *  {@linkplain Exception checked exception}.
213     *
214     *  @param  <T> The type of arguments taken by the consumer.
215     *  @param  consumer    The consumer to wrap.
216     *  @return The wrapped consumer.
217     */
218    @API( status = STABLE, since = "0.0.5" )
219    public static final <T> Consumer<T> wrapConsumer( final TCEConsumer<? super T> consumer )
220    {
221        final Consumer<T> retValue = arg ->
222        {
223            try
224            {
225                consumer.accept( arg );
226            }
227            catch( final Exception e )
228            {
229                throw new LambdaContainerException( e );
230            }
231        };
232
233        //---* Done *----------------------------------------------------------
234        return retValue;
235    }   //  wrapConsumer()
236
237    /**
238     *  Wraps an instance of
239     *  {@link TCEFunction}
240     *  to an instance of
241     *  {@link Function}
242     *  that throws an instance of
243     *  {@link LambdaContainerException}
244     *  with the causing exception, in case the wrapped instance emitted a
245     *  {@linkplain Exception checked exception}.
246     *
247     *  @param  <T> The type of the input to the function.
248     *  @param  <R> The type of the result of the function.
249     *  @param  function    The function to wrap.
250     *  @return The wrapped function.
251     */
252    @API( status = STABLE, since = "0.0.5" )
253    public static final <T,R> Function<T,R> wrapFunction( final TCEFunction<? super T, ? extends R> function )
254    {
255        final Function<T,R> retValue = arg ->
256        {
257            try
258            {
259                return function.apply( arg );
260            }
261            catch( final Exception e )
262            {
263                throw new LambdaContainerException( e );
264            }
265        };
266
267        //---* Done *----------------------------------------------------------
268        return retValue;
269    }   //  wrapFunction()
270
271    /**
272     *  Wraps an instance of
273     *  {@link TCEPredicate}
274     *  to an instance of
275     *  {@link Predicate}
276     *  that throws an instance of
277     *  {@link LambdaContainerException}
278     *  with the causing exception, in case the wrapped instance emitted a
279     *  {@linkplain Exception checked exception}.
280     *
281     *  @param  <T> The type of the input to the predicate.
282     *  @param  predicate   The predicate to wrap.
283     *  @return The wrapped predicate.
284     */
285    @API( status = STABLE, since = "0.0.5" )
286    public static final <T> Predicate<T> wrapPredicate( final TCEPredicate<? super T> predicate )
287    {
288        final Predicate<T> retValue = arg ->
289        {
290            try
291            {
292                return predicate.test( arg );
293            }
294            catch( final Exception e )
295            {
296                throw new LambdaContainerException( e );
297            }
298        };
299
300        //---* Done *----------------------------------------------------------
301        return retValue;
302    }   //  wrapPredicate()
303
304    /**
305     *  Wraps an instance of
306     *  {@link TCESupplier}
307     *  to an instance of
308     *  {@link Supplier}
309     *  that throws an instance of
310     *  {@link LambdaContainerException}
311     *  with the causing exception, in case the wrapped instance emitted a
312     *  {@linkplain Exception checked exception}.
313     *
314     *  @param  <T> The type of results supplied by the supplier.
315     *  @param  supplier    The supplier to wrap.
316     *  @return The wrapped supplier.
317     */
318    @API( status = STABLE, since = "0.0.5" )
319    public static final <T> Supplier<T> wrapSupplier( final TCESupplier<? extends T> supplier )
320    {
321        final Supplier<T> retValue = () ->
322        {
323            try
324            {
325                return supplier.get();
326            }
327            catch( final Exception e )
328            {
329                throw new LambdaContainerException( e );
330            }
331        };
332
333        //---* Done *----------------------------------------------------------
334        return retValue;
335    }   //  wrapSupplier()
336
337    /**
338     *  Wraps an instance of
339     *  {@link TCETriConsumer}
340     *  to an instance of
341     *  {@link TriConsumer}
342     *  that throws an instance of
343     *  {@link LambdaContainerException}
344     *  with the causing exception, in case the wrapped instance emitted a
345     *  {@linkplain Exception checked exception}.
346     *
347     *  @param  <T1> The type of the first argument taken by the consumer.
348     *  @param  <T2> The type of the second argument taken by the consumer.
349     *  @param  <T3> The type of the third argument taken by the consumer.
350     *  @param  consumer    The consumer to wrap.
351     *  @return The wrapped consumer.
352     */
353    @API( status = STABLE, since = "0.0.5" )
354    public static final <T1,T2,T3> TriConsumer<T1,T2,T3> wrapTriConsumer( final TCETriConsumer<? super T1, ? super T2, ? super T3> consumer )
355    {
356        final TriConsumer<T1,T2,T3> retValue = (arg1, arg2, arg3) ->
357        {
358            try
359            {
360                consumer.accept( arg1, arg2, arg3 );
361            }
362            catch( final Exception e )
363            {
364                throw new LambdaContainerException( e );
365            }
366        };
367
368        //---* Done *----------------------------------------------------------
369        return retValue;
370    }   //  wrapTriConsumer()
371
372    /**
373     *  Wraps an instance of
374     *  {@link TCETriFunction}
375     *  to an instance of
376     *  {@link TriFunction}
377     *  that throws an instance of
378     *  {@link LambdaContainerException}
379     *  with the causing exception, in case the wrapped instance emitted a
380     *  {@linkplain Exception checked exception}.
381     *
382     *  @param  <T1> The type of the first argument taken by the function.
383     *  @param  <T2> The type of the second argument taken by the function.
384     *  @param  <T3> The type of the third argument taken by the function.
385     *  @param  <R> The type of the result of the function.
386     *  @param  function    The function to wrap.
387     *  @return The wrapped function.
388     */
389    @API( status = STABLE, since = "0.0.5" )
390    public static final <T1,T2,T3,R> TriFunction<T1,T2,T3,R> wrapTriFunction( final TCETriFunction<? super T1, ? super T2, ? super T3, ? extends R> function )
391    {
392        final TriFunction<T1,T2,T3,R> retValue = (arg1, arg2, arg3) ->
393        {
394            try
395            {
396                return function.apply( arg1, arg2, arg3 );
397            }
398            catch( final Exception e )
399            {
400                throw new LambdaContainerException( e );
401            }
402        };
403
404        //---* Done *----------------------------------------------------------
405        return retValue;
406    }   //  wrapTriFunction()
407}
408//  class Functions
409
410/*
411 *  End of File
412 */