View Javadoc
1   package org.djutils.exceptions;
2   
3   import java.lang.reflect.Constructor;
4   import java.util.ArrayList;
5   import java.util.Arrays;
6   import java.util.IllegalFormatException;
7   import java.util.List;
8   
9   import org.djutils.reflection.ClassUtil;
10  
11  /**
12   * The Throw class has a number of static methods that make it easy to throw an exception under conditions for any Exception
13   * class, including the standard Java exceptions and exceptions from libraries that are used in the project. Instead of:
14   * 
15   * <pre>
16   * if (car == null)
17   * {
18   *     throw new NullPointerException(&quot;Car may not be null.&quot;);
19   * }
20   * if (Double.isNaN(car.getPosition()))
21   * {
22   *     throw new IllegalArgumentException(&quot;Position of car &quot; + car + &quot; is NaN.&quot;);
23   * }
24   * </pre>
25   * 
26   * we can write:
27   * 
28   * <pre>
29   * Throw.whenNull(car, &quot;Car may not be null.&quot;);
30   * Throw.when(Double.isNaN(car.getPosition()), IllegalArgumentException.class, &quot;Position of car %s is NaN.&quot;, car);
31   * </pre>
32   * 
33   * The exception message can be formatted with additional arguments, such that the overhead of building the exception message
34   * only occurs if the exception condition is met. All methods have a version where the first parameter is returned. Thereby, the
35   * Throw can be used as part of a <b>super</b>(...) call in a constructor.
36   * <p>
37   * Copyright (c) 2016-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
38   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
39   * distributed under a three-clause BSD-style license, which can be found at
40   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
41   * </p>
42   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
43   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
44   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
45   */
46  @SuppressWarnings("checkstyle:linelength")
47  public final class Throw
48  {
49      /** private constructor for utility class. */
50      private Throw()
51      {
52          // utility class
53      }
54  
55      /**
56       * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. Use as
57       * follows: <br>
58       * 
59       * <pre>
60       * Throw.when(Double.isNan(object.getValue()), IllegalArgumentException.class, &quot;Value may not be NaN.&quot;);
61       * </pre>
62       * 
63       * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
64       * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
65       * @param message String; the message to use in the exception
66       * @throws T the throwable to throw on true condition
67       * @param <T> the Throwable type
68       */
69      public static <T extends Throwable> void when(final boolean condition, final Class<T> throwableClass, final String message)
70              throws T
71      {
72          if (condition)
73          {
74              throwMessage(throwableClass, message, null);
75          }
76      }
77  
78      /**
79       * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. Use as
80       * follows: <br>
81       * 
82       * <pre>
83       * Throw.when(Double.isNan(object.getValue()), IllegalArgumentException.class, &quot;Value may not be NaN for object %s.&quot;, object);
84       * </pre>
85       * 
86       * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
87       * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
88       * @param message String; the message to use in the exception, with formatting identifiers
89       * @param arg Object; value to use for the formatting identifiers
90       * @throws T the throwable to throw on true condition
91       * @param <T> the Throwable type
92       */
93      public static <T extends Throwable> void when(final boolean condition, final Class<T> throwableClass, final String message,
94              final Object arg) throws T
95      {
96          if (condition)
97          {
98              List<Object> argList = new ArrayList<>();
99              argList.add(arg);
100             throwMessage(throwableClass, message, argList);
101         }
102     }
103 
104     /**
105      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. Use as
106      * follows: <br>
107      * 
108      * <pre>
109      * Throw.when(Double.isNan(object.getValue()), IllegalArgumentException.class,
110      *         &quot;Value may not be NaN for object %s with name %s.&quot;, object, name);
111      * </pre>
112      * 
113      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
114      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
115      * @param message String; the message to use in the exception, with formatting identifiers
116      * @param arg1 Object; 1st value to use for the formatting identifiers
117      * @param arg2 Object; 2nd value to use for the formatting identifiers
118      * @throws T the throwable to throw on true condition
119      * @param <T> the Throwable type
120      */
121     public static <T extends Throwable> void when(final boolean condition, final Class<T> throwableClass, final String message,
122             final Object arg1, final Object arg2) throws T
123     {
124         if (condition)
125         {
126             List<Object> argList = new ArrayList<>();
127             argList.add(arg1);
128             argList.add(arg2);
129             throwMessage(throwableClass, message, argList);
130         }
131     }
132 
133     /**
134      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. Use as
135      * follows: <br>
136      * 
137      * <pre>
138      * Throw.when(Double.isNan(object.getValue()), IllegalArgumentException.class,
139      *         &quot;Value may not be NaN for object %s with name %s and id %s.&quot;, object, name, id);
140      * </pre>
141      * 
142      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
143      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
144      * @param message String; the message to use in the exception, with formatting identifiers
145      * @param arg1 Object; 1st value to use for the formatting identifiers
146      * @param arg2 Object; 2nd value to use for the formatting identifiers
147      * @param arg3 Object; 3rd value to use for the formatting identifiers
148      * @throws T the throwable to throw on true condition
149      * @param <T> the Throwable type
150      */
151     public static <T extends Throwable> void when(final boolean condition, final Class<T> throwableClass, final String message,
152             final Object arg1, final Object arg2, final Object arg3) throws T
153     {
154         if (condition)
155         {
156             List<Object> argList = new ArrayList<>();
157             argList.add(arg1);
158             argList.add(arg2);
159             argList.add(arg3);
160             throwMessage(throwableClass, message, argList);
161         }
162     }
163 
164     /**
165      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. Use as
166      * follows: <br>
167      * 
168      * <pre>
169      * Throw.when(Double.isNan(object.getValue()), IllegalArgumentException.class,
170      *         &quot;Value may not be NaN for object %s with name %s, id %s and parent %s.&quot;, object, name, id, parent);
171      * </pre>
172      * 
173      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
174      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
175      * @param message String; the message to use in the exception, with formatting identifiers
176      * @param arg1 Object; 1st value to use for the formatting identifiers
177      * @param arg2 Object; 2nd value to use for the formatting identifiers
178      * @param arg3 Object; 3rd value to use for the formatting identifiers
179      * @param args Object...; potential 4th and further values to use for the formatting identifiers
180      * @throws T the throwable to throw on true condition
181      * @param <T> the Throwable type
182      */
183     public static <T extends Throwable> void when(final boolean condition, final Class<T> throwableClass, final String message,
184             final Object arg1, final Object arg2, final Object arg3, final Object... args) throws T
185     {
186         if (condition)
187         {
188             List<Object> argList = new ArrayList<>();
189             argList.add(arg1);
190             argList.add(arg2);
191             argList.add(arg3);
192             argList.addAll(Arrays.asList(args));
193             throwMessage(throwableClass, message, argList);
194         }
195     }
196 
197     /**
198      * Private method to handle the throwing an Exception, Throwable or Error.
199      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
200      * @param message String; the message to use in the exception, with potential formatting identifiers
201      * @param argList List&lt;Object&gt;; List with potential values to use for the formatting identifiers, or null when there
202      *            are no formatting identifiers
203      * @throws T the throwable to throw
204      * @param <T> the Throwable type
205      */
206     private static <T extends Throwable> void throwMessage(final Class<T> throwableClass, final String message,
207             final List<Object> argList) throws T
208     {
209         // create a clear message
210         List<StackTraceElement> steList = new ArrayList<>(Arrays.asList(new Throwable().getStackTrace()));
211         steList.remove(0); // remove the throwMessage(...) call
212         steList.remove(0); // remove the when(...) call
213         StackTraceElement[] ste = steList.toArray(new StackTraceElement[steList.size()]);
214         String where = ste[0].getClassName() + "." + ste[0].getMethodName() + " (" + ste[0].getLineNumber() + "): ";
215         String formattedMessage;
216         if (argList == null)
217         {
218             formattedMessage = message;
219         }
220         else
221         {
222             try
223             {
224                 formattedMessage = where + String.format(message, argList.toArray());
225             }
226             catch (IllegalFormatException exception)
227             {
228                 formattedMessage = where + message + " [FormatException; args=" + argList + "]";
229             }
230         }
231 
232         // throw all other exceptions through reflection
233         T exception;
234         try
235         {
236             Constructor<T> constructor = ClassUtil.resolveConstructor(throwableClass, new Class<?>[] {String.class});
237             exception = constructor.newInstance(formattedMessage);
238             exception.setStackTrace(ste);
239         }
240         catch (Throwable t)
241         {
242             RuntimeException rte = new RuntimeException(t.getMessage(), new Exception(formattedMessage));
243             rte.setStackTrace(ste);
244             throw rte;
245         }
246         throw exception;
247     }
248 
249     /**
250      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. This
251      * version of the method returns its first parameter, so it can be used inside a constructor. Use e.g., as follows:
252      * 
253      * <pre>
254      * super(Throw.when(object, Double.isNaN(object.getValue()), IllegalArgumentException.class, "Value may not be NaN."));
255      * </pre>
256      * 
257      * @param object O; the object to return by this static method
258      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
259      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
260      * @param message String; the message to use in the exception
261      * @throws T the throwable to throw on true condition
262      * @param <T> the Throwable type
263      * @param <O> the Object type to return
264      * @return the object that was passed as the first parameter
265      */
266     public static <T extends Throwable, O extends Object> O when(final O object, final boolean condition,
267             final Class<T> throwableClass, final String message) throws T
268     {
269         if (condition)
270         {
271             throwMessage(throwableClass, message, null);
272         }
273         return object;
274     }
275 
276     /**
277      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. This
278      * version of the method returns its first parameter, so it can be used inside a constructor. Use e.g., as follows:
279      * 
280      * <pre>
281      * super(Throw.when(object, Double.isNan(object.getValue()), IllegalArgumentException.class,
282      *         &quot;Value may not be NaN for object %s.&quot;, object));
283      * </pre>
284      * 
285      * @param object O; the object to return by this static method
286      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
287      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
288      * @param message String; the message to use in the exception, with formatting identifiers
289      * @param arg Object; value to use for the formatting identifiers
290      * @throws T the throwable to throw on true condition
291      * @param <T> the Throwable type
292      * @param <O> the Object type to return
293      * @return the object that was passed as the first parameter
294      */
295     public static <T extends Throwable, O extends Object> O when(final O object, final boolean condition,
296             final Class<T> throwableClass, final String message, final Object arg) throws T
297     {
298         if (condition)
299         {
300             List<Object> argList = new ArrayList<>();
301             argList.add(arg);
302             throwMessage(throwableClass, message, argList);
303         }
304         return object;
305     }
306 
307     /**
308      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. This
309      * version of the method returns its first parameter, so it can be used inside a constructor. Use e.g., as follows:
310      * 
311      * <pre>
312      * super(Throw.when(object, Double.isNan(object.getValue()), IllegalArgumentException.class,
313      *         &quot;Value may not be NaN for object %s with name %s.&quot;, object, name));
314      * </pre>
315      * 
316      * @param object O; the object to return by this static method
317      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
318      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
319      * @param message String; the message to use in the exception, with formatting identifiers
320      * @param arg1 Object; 1st value to use for the formatting identifiers
321      * @param arg2 Object; 2nd value to use for the formatting identifiers
322      * @throws T the throwable to throw on true condition
323      * @param <T> the Throwable type
324      * @param <O> the Object type to return
325      * @return the object that was passed as the first parameter
326      */
327     public static <T extends Throwable, O extends Object> O when(final O object, final boolean condition,
328             final Class<T> throwableClass, final String message, final Object arg1, final Object arg2) throws T
329     {
330         if (condition)
331         {
332             List<Object> argList = new ArrayList<>();
333             argList.add(arg1);
334             argList.add(arg2);
335             throwMessage(throwableClass, message, argList);
336         }
337         return object;
338     }
339 
340     /**
341      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. This
342      * version of the method returns its first parameter, so it can be used inside a constructor. Use e.g., as follows:
343      * 
344      * <pre>
345      * super(Throw.when(object, Double.isNan(object.getValue()), IllegalArgumentException.class,
346      *         &quot;Value may not be NaN for object %s with name %s and id %s.&quot;, object, name, id));
347      * </pre>
348      * 
349      * @param object O; the object to return by this static method
350      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
351      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
352      * @param message String; the message to use in the exception, with formatting identifiers
353      * @param arg1 Object; 1st value to use for the formatting identifiers
354      * @param arg2 Object; 2nd value to use for the formatting identifiers
355      * @param arg3 Object; 3rd value to use for the formatting identifiers
356      * @throws T the throwable to throw on true condition
357      * @param <T> the Throwable type
358      * @param <O> the Object type to return
359      * @return the object that was passed as the first parameter
360      */
361     public static <T extends Throwable, O extends Object> O when(final O object, final boolean condition,
362             final Class<T> throwableClass, final String message, final Object arg1, final Object arg2, final Object arg3)
363             throws T
364     {
365         if (condition)
366         {
367             List<Object> argList = new ArrayList<>();
368             argList.add(arg1);
369             argList.add(arg2);
370             argList.add(arg3);
371             throwMessage(throwableClass, message, argList);
372         }
373         return object;
374     }
375 
376     /**
377      * Throw a Throwable (such as an Exception or Error) if a condition is met, e.g. for pre- and postcondition checking. This
378      * version of the method returns its first parameter, so it can be used inside a constructor. Use e.g., as follows:
379      * 
380      * <pre>
381      * super(Throw.when(object, Double.isNan(object.getValue()), IllegalArgumentException.class,
382      *         &quot;Value may not be NaN for object %s with name %s, id %s and parent %s.&quot;, object, name, id, parent));
383      * </pre>
384      * 
385      * @param object O; the object to return by this static method
386      * @param condition boolean; the condition to check; an exception will be thrown if this is <b>true</b>
387      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
388      * @param message String; the message to use in the exception, with formatting identifiers
389      * @param arg1 Object; 1st value to use for the formatting identifiers
390      * @param arg2 Object; 2nd value to use for the formatting identifiers
391      * @param arg3 Object; 3rd value to use for the formatting identifiers
392      * @param args Object...; potential 4th and further values to use for the formatting identifiers
393      * @throws T the throwable to throw on true condition
394      * @param <T> the Throwable type
395      * @param <O> the Object type to return
396      * @return the object that was passed as the first parameter
397      */
398     @SuppressWarnings("checkstyle:parameternumber")
399     public static <T extends Throwable, O extends Object> O when(final O object, final boolean condition,
400             final Class<T> throwableClass, final String message, final Object arg1, final Object arg2, final Object arg3,
401             final Object... args) throws T
402     {
403         if (condition)
404         {
405             List<Object> argList = new ArrayList<>();
406             argList.add(arg1);
407             argList.add(arg2);
408             argList.add(arg3);
409             argList.addAll(Arrays.asList(args));
410             throwMessage(throwableClass, message, argList);
411         }
412         return object;
413     }
414 
415     /**
416      * Throw a NullPointerException if object is null, e.g. for pre- and postcondition checking. Use as follows: <br>
417      * 
418      * <pre>
419      * Throw.whenNull(value, &quot;value may not be null.&quot;);
420      * </pre>
421      *
422      * A shortened version where the text " may not be null" is automatically appended after the variable name is just listing
423      * the variable name without any spaces:
424      * 
425      * <pre>
426      * Throw.whenNull(value, &quot;value&quot;);
427      * </pre>
428      * 
429      * @param object object to check; an exception will be thrown if the object is <b>null</b>
430      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
431      *            null"
432      * @param <O> the Object type to return
433      * @return the object that was passed as the first parameter
434      * @throws NullPointerException if object is null
435      */
436     public static <O extends Object> O whenNull(final O object, final String message) throws NullPointerException
437     {
438         if (object == null)
439         {
440             if (message.matches("\\S+")) // \S+ is any non-whitespace character
441             {
442                 throwMessage(NullPointerException.class, message + " may not be null", null);
443             }
444             else
445             {
446                 throwMessage(NullPointerException.class, message, null);
447             }
448         }
449         return object;
450     }
451 
452     /**
453      * Throw a NullPointerException if object is null, e.g. for pre- and postcondition checking. Use as follows: <br>
454      * 
455      * <pre>
456      * Throw.whenNull(object.getValue(), &quot;Value may not be null for object %s.&quot;, object);
457      * </pre>
458      * 
459      * @param object object to check; an exception will be thrown if this is <b>null</b>
460      * @param message String; the message to use in the exception, with formatting identifiers
461      * @param arg Object; value to use for the formatting identifiers
462      * @param <O> the Object type to return
463      * @return the object that was passed as the first parameter
464      * @throws NullPointerException if object is null
465      */
466     public static <O extends Object> O whenNull(final O object, final String message, final Object arg)
467             throws NullPointerException
468     {
469         if (object == null)
470         {
471             List<Object> argList = new ArrayList<>();
472             argList.add(arg);
473             throwMessage(NullPointerException.class, message, argList);
474         }
475         return object;
476     }
477 
478     /**
479      * Throw a NullPointerException if object is null, e.g. for pre- and postcondition checking. Use as follows: <br>
480      * 
481      * <pre>
482      * Throw.whenNull(object.getValue(), &quot;Value may not be null for object %s with name %s.&quot;, object, name);
483      * </pre>
484      * 
485      * @param object object to check; an exception will be thrown if this is <b>null</b>
486      * @param message String; the message to use in the exception, with formatting identifiers
487      * @param arg1 Object; 1st value to use for the formatting identifiers
488      * @param arg2 Object; 2nd value to use for the formatting identifiers
489      * @param <O> the Object type to return
490      * @return the object that was passed as the first parameter
491      * @throws NullPointerException if object is null
492      */
493     public static <O extends Object> O whenNull(final O object, final String message, final Object arg1, final Object arg2)
494             throws NullPointerException
495     {
496         if (object == null)
497         {
498             List<Object> argList = new ArrayList<>();
499             argList.add(arg1);
500             argList.add(arg2);
501             throwMessage(NullPointerException.class, message, argList);
502         }
503         return object;
504     }
505 
506     /**
507      * Throw a NullPointerException if object is null, e.g. for pre- and postcondition checking. Use as follows: <br>
508      * 
509      * <pre>
510      * Throw.whenNull(object.getValue(), &quot;Value may not be null for object %s with name %s and id %s.&quot;, object, name, id);
511      * </pre>
512      * 
513      * @param object object to check; an exception will be thrown if this is <b>null</b>
514      * @param message String; the message to use in the exception, with formatting identifiers
515      * @param arg1 Object; 1st value to use for the formatting identifiers
516      * @param arg2 Object; 2nd value to use for the formatting identifiers
517      * @param arg3 Object; 3rd value to use for the formatting identifiers
518      * @param <O> the Object type to return
519      * @return the object that was passed as the first parameter
520      * @throws NullPointerException if object is null
521      */
522     public static <O extends Object> O whenNull(final O object, final String message, final Object arg1, final Object arg2,
523             final Object arg3) throws NullPointerException
524     {
525         if (object == null)
526         {
527             List<Object> argList = new ArrayList<>();
528             argList.add(arg1);
529             argList.add(arg2);
530             argList.add(arg3);
531             throwMessage(NullPointerException.class, message, argList);
532         }
533         return object;
534     }
535 
536     /**
537      * Throw a NullPointerException if object is null, e.g. for pre- and postcondition checking. Use as follows: <br>
538      * 
539      * <pre>
540      * Throw.whenNull(object.getValue(), &quot;Value may not be null for object %s with name %s, id %s and parent %s.&quot;, object, name, id,
541      *         parent);
542      * </pre>
543      * 
544      * @param object object to check; an exception will be thrown if this is <b>null</b>
545      * @param message String; the message to use in the exception, with formatting identifiers
546      * @param arg1 Object; 1st value to use for the formatting identifiers
547      * @param arg2 Object; 2nd value to use for the formatting identifiers
548      * @param arg3 Object; 3rd value to use for the formatting identifiers
549      * @param args Object...; potential 4th and further values to use for the formatting identifiers
550      * @param <O> the Object type to return
551      * @return the object that was passed as the first parameter
552      * @throws NullPointerException if object is null
553      */
554     public static <O extends Object> O whenNull(final O object, final String message, final Object arg1, final Object arg2,
555             final Object arg3, final Object... args) throws NullPointerException
556     {
557         if (object == null)
558         {
559             List<Object> argList = new ArrayList<>();
560             argList.add(arg1);
561             argList.add(arg2);
562             argList.add(arg3);
563             argList.addAll(Arrays.asList(args));
564             throwMessage(NullPointerException.class, message, argList);
565         }
566         return object;
567     }
568 
569     /**
570      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
571      * 
572      * <pre>
573      * Throw.whenNaN(value, &quot;value may not be NaN.&quot;);
574      * </pre>
575      *
576      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
577      * the variable name without any spaces:
578      * 
579      * <pre>
580      * Throw.whenNaN(value, &quot;value&quot;);
581      * </pre>
582      * 
583      * @param value double; value to check; an exception will be thrown if the object is <b>NaN</b>
584      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
585      *            NaN"
586      * @return double; the value that was passed as the first parameter
587      * @throws ArithmeticException if value is NaN
588      */
589     public static double whenNaN(final double value, final String message) throws ArithmeticException
590     {
591         if (Double.isNaN(value))
592         {
593             if (message.matches("\\S+")) // \S+ is any non-whitespace character
594             {
595                 throwMessage(ArithmeticException.class, message + " may not be NaN", null);
596             }
597             else
598             {
599                 throwMessage(ArithmeticException.class, message, null);
600             }
601         }
602         return value;
603     }
604 
605     /**
606      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
607      * 
608      * <pre>
609      * Throw.whenNaN(value, &quot;value may not be NaN.&quot;);
610      * </pre>
611      *
612      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
613      * the variable name without any spaces:
614      * 
615      * <pre>
616      * Throw.whenNaN(value, &quot;value&quot;);
617      * </pre>
618      * 
619      * @param value float; value to check; an exception will be thrown if the object is <b>NaN</b>
620      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
621      *            NaN"
622      * @return float; the value that was passed as the first parameter
623      * @throws ArithmeticException if value is NaN
624      */
625     public static float whenNaN(final float value, final String message) throws ArithmeticException
626     {
627         if (Float.isNaN(value))
628         {
629             if (message.matches("\\S+")) // \S+ is any non-whitespace character
630             {
631                 throwMessage(ArithmeticException.class, message + " may not be NaN", null);
632             }
633             else
634             {
635                 throwMessage(ArithmeticException.class, message, null);
636             }
637         }
638         return value;
639     }
640 
641     /**
642      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
643      * 
644      * <pre>
645      * Throw.whenNaN(value, &quot;value may not be NaN.&quot;);
646      * </pre>
647      *
648      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
649      * the variable name without any spaces:
650      * 
651      * <pre>
652      * Throw.whenNaN(value, &quot;value&quot;);
653      * </pre>
654      * 
655      * @param value Double; value to check; an exception will be thrown if the object is <b>NaN</b>
656      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
657      *            NaN"
658      * @return Double; the value that was passed as the first parameter
659      * @throws ArithmeticException if value is NaN
660      */
661     public static Double whenNaN(final Double value, final String message) throws ArithmeticException
662     {
663         if (value != null && Double.isNaN(value))
664         {
665             if (message.matches("\\S+")) // \S+ is any non-whitespace character
666             {
667                 throwMessage(ArithmeticException.class, message + " may not be NaN", null);
668             }
669             else
670             {
671                 throwMessage(ArithmeticException.class, message, null);
672             }
673         }
674         return value;
675     }
676 
677     /**
678      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
679      * 
680      * <pre>
681      * Throw.whenNaN(value, &quot;Value may not be NaN for object %s with name %s, id %s.&quot;, object, name, id);
682      * </pre>
683      * 
684      * @param value Double; the value to check; an exception will be thrown if this is <b>NaN</b>
685      * @param message String; the message to use in the exception, with formatting identifiers
686      * @param arg1 Object; 1st value to use for the formatting identifiers
687      * @param args Object...; potential 2nd and further values to use for the formatting identifiers
688      * @return Double; the value that was passed as the first parameter
689      * @throws ArithmeticException if value is NaN
690      */
691     public static Double whenNaN(final Double value, final String message, final Object arg1, final Object... args)
692             throws ArithmeticException
693     {
694         if (value != null && Double.isNaN(value))
695         {
696             List<Object> argList = new ArrayList<>();
697             argList.add(arg1);
698             argList.addAll(Arrays.asList(args));
699             throwMessage(ArithmeticException.class, message, argList);
700         }
701         return value;
702     }
703 
704     /**
705      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
706      * 
707      * <pre>
708      * Throw.whenNaN(value, &quot;value may not be NaN.&quot;);
709      * </pre>
710      *
711      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
712      * the variable name without any spaces:
713      * 
714      * <pre>
715      * Throw.whenNaN(value, &quot;value&quot;);
716      * </pre>
717      * 
718      * @param value Float; value to check; an exception will be thrown if the object is <b>NaN</b>
719      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
720      *            NaN"
721      * @return Float; the value that was passed as the first parameter
722      * @throws ArithmeticException if value is NaN
723      */
724     public static Float whenNaN(final Float value, final String message) throws ArithmeticException
725     {
726         if (value != null && Float.isNaN(value))
727         {
728             if (message.matches("\\S+")) // \S+ is any non-whitespace character
729             {
730                 throwMessage(ArithmeticException.class, message + " may not be NaN", null);
731             }
732             else
733             {
734                 throwMessage(ArithmeticException.class, message, null);
735             }
736         }
737         return value;
738     }
739 
740     /**
741      * Throw an ArithmeticException if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
742      * 
743      * <pre>
744      * Throw.whenNaN(value, &quot;Value may not be NaN for object %s with name %s, id %s.&quot;, object, name, id);
745      * </pre>
746      * 
747      * @param value Float; the value to check; an exception will be thrown if this is <b>NaN</b>
748      * @param message String; the message to use in the exception, with formatting identifiers
749      * @param arg1 Object; 1st value to use for the formatting identifiers
750      * @param args Object...; potential 2nd and further values to use for the formatting identifiers
751      * @return Float; the value that was passed as the first parameter
752      * @throws ArithmeticException if value is NaN
753      */
754     public static Float whenNaN(final Float value, final String message, final Object arg1, final Object... args)
755             throws ArithmeticException
756     {
757         if (value != null && Float.isNaN(value))
758         {
759             List<Object> argList = new ArrayList<>();
760             argList.add(arg1);
761             argList.addAll(Arrays.asList(args));
762             throwMessage(ArithmeticException.class, message, argList);
763         }
764         return value;
765     }
766 
767     /**
768      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
769      * 
770      * <pre>
771      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value may not be NaN.&quot;);
772      * </pre>
773      *
774      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
775      * the variable name without any spaces:
776      * 
777      * <pre>
778      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value&quot;);
779      * </pre>
780      * 
781      * @param value double; value to check; an exception will be thrown if the object is <b>NaN</b>
782      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
783      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
784      *            NaN"
785      * @param <T> the Throwable class
786      * @return double; the value that was passed as the first parameter
787      * @throws T if value is NaN
788      */
789     public static <T extends Throwable> double whenNaN(final double value, final Class<T> throwableClass, final String message)
790             throws T
791     {
792         if (Double.isNaN(value))
793         {
794             if (message.matches("\\S+")) // \S+ is any non-whitespace character
795             {
796                 throwMessage(throwableClass, message + " may not be NaN", null);
797             }
798             else
799             {
800                 throwMessage(throwableClass, message, null);
801             }
802         }
803         return value;
804     }
805 
806     /**
807      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
808      * 
809      * <pre>
810      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value may not be NaN.&quot;);
811      * </pre>
812      *
813      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
814      * the variable name without any spaces:
815      * 
816      * <pre>
817      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value&quot;);
818      * </pre>
819      * 
820      * @param value float; value to check; an exception will be thrown if the object is <b>NaN</b>
821      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
822      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
823      *            NaN"
824      * @param <T> the Throwable class
825      * @return float; the value that was passed as the first parameter
826      * @throws T if value is NaN
827      */
828     public static <T extends Throwable> float whenNaN(final float value, final Class<T> throwableClass, final String message)
829             throws T
830     {
831         if (Float.isNaN(value))
832         {
833             if (message.matches("\\S+")) // \S+ is any non-whitespace character
834             {
835                 throwMessage(throwableClass, message + " may not be NaN", null);
836             }
837             else
838             {
839                 throwMessage(throwableClass, message, null);
840             }
841         }
842         return value;
843     }
844 
845     /**
846      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
847      * 
848      * <pre>
849      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value may not be NaN.&quot;);
850      * </pre>
851      *
852      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
853      * the variable name without any spaces:
854      * 
855      * <pre>
856      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value&quot;);
857      * </pre>
858      * 
859      * @param value Double; value to check; an exception will be thrown if the object is <b>NaN</b>
860      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
861      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
862      *            NaN"
863      * @param <T> the Throwable class
864      * @return Double; the value that was passed as the first parameter
865      * @throws T if value is NaN
866      */
867     public static <T extends Throwable> Double whenNaN(final Double value, final Class<T> throwableClass, final String message)
868             throws T
869     {
870         if (value != null && Double.isNaN(value))
871         {
872             if (message.matches("\\S+")) // \S+ is any non-whitespace character
873             {
874                 throwMessage(throwableClass, message + " may not be NaN", null);
875             }
876             else
877             {
878                 throwMessage(throwableClass, message, null);
879             }
880         }
881         return value;
882     }
883 
884     /**
885      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
886      * 
887      * <pre>
888      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;Value may not be NaN for object %s with name %s, 
889      *          id %s.&quot;, object, name, id);
890      * </pre>
891      * 
892      * @param value Double; the value to check; an exception will be thrown if this is <b>NaN</b>
893      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
894      * @param message String; the message to use in the exception, with formatting identifiers
895      * @param arg1 Object; 1st value to use for the formatting identifiers
896      * @param args Object...; potential 2nd and further values to use for the formatting identifiers
897      * @param <T> the Throwable class
898      * @return Double; the value that was passed as the first parameter
899      * @throws T if value is NaN
900      */
901     public static <T extends Throwable> Double whenNaN(final Double value, final Class<T> throwableClass, final String message,
902             final Object arg1, final Object... args) throws T
903     {
904         if (value != null && Double.isNaN(value))
905         {
906             List<Object> argList = new ArrayList<>();
907             argList.add(arg1);
908             argList.addAll(Arrays.asList(args));
909             throwMessage(throwableClass, message, argList);
910         }
911         return value;
912     }
913 
914     /**
915      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
916      * 
917      * <pre>
918      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value may not be NaN.&quot;);
919      * </pre>
920      *
921      * A shortened version where the text " may not be NaN" is automatically appended after the variable name is just listing
922      * the variable name without any spaces:
923      * 
924      * <pre>
925      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;value&quot;);
926      * </pre>
927      * 
928      * @param value Float; value to check; an exception will be thrown if the object is <b>NaN</b>
929      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
930      * @param message String; the message to use in the exception, or the variable name that will be appended with " may not be
931      *            NaN"
932      * @param <T> the Throwable class
933      * @return Float; the value that was passed as the first parameter
934      * @throws T if value is NaN
935      */
936     public static <T extends Throwable> Float whenNaN(final Float value, final Class<T> throwableClass, final String message)
937             throws T
938     {
939         if (value != null && Float.isNaN(value))
940         {
941             if (message.matches("\\S+")) // \S+ is any non-whitespace character
942             {
943                 throwMessage(throwableClass, message + " may not be NaN", null);
944             }
945             else
946             {
947                 throwMessage(throwableClass, message, null);
948             }
949         }
950         return value;
951     }
952 
953     /**
954      * Throw a specified exception if value is NaN, e.g. for pre- and postcondition checking. Use as follows: <br>
955      * 
956      * <pre>
957      * Throw.whenNaN(value, IllegalArgumentException.class, &quot;Value may not be NaN for object %s with name %s, 
958      *          id %s.&quot;, object, name, id);
959      * </pre>
960      * 
961      * @param value Float; the value to check; an exception will be thrown if this is <b>NaN</b>
962      * @param throwableClass Class&lt;T&gt;; the Throwable type to throw
963      * @param message String; the message to use in the exception, with formatting identifiers
964      * @param arg1 Object; 1st value to use for the formatting identifiers
965      * @param args Object...; potential 2nd and further values to use for the formatting identifiers
966      * @param <T> the Throwable class
967      * @return Float; the value that was passed as the first parameter
968      * @throws T if value is NaN
969      */
970     public static <T extends Throwable> Float whenNaN(final Float value, final Class<T> throwableClass, final String message,
971             final Object arg1, final Object... args) throws T
972     {
973         if (value != null && Float.isNaN(value))
974         {
975             List<Object> argList = new ArrayList<>();
976             argList.add(arg1);
977             argList.addAll(Arrays.asList(args));
978             throwMessage(throwableClass, message, argList);
979         }
980         return value;
981     }
982 
983     /**
984      * Throw an unchecked exception for a method with a fixed signature (e.g., extending a method from a library that cannot be
985      * changed), without having to declare the exception, which can be impossible when extending a method. The typical use is:
986      * 
987      * <pre>
988      *   &#64;Override
989      *   public void someMethod() {  
990      *     try {
991      *       // some code that throws e.g., an IOException
992      *     } catch IOException e {
993      *       Throw.throwUnchecked(e);
994      *     }  
995      *   }
996      * </pre>
997      * 
998      * From: <a href="http://blog.ragozin.info/2011/10/java-how-to-throw-undeclared-checked.html" target="_blank">
999      * http://blog.ragozin.info/2011/10/java-how-to-throw-undeclared-checked.html</a> as mentioned in <a href=
1000      * "https://stackoverflow.com/questions/11942946/how-to-throw-an-exception-when-your-method-signature-doesnt-allow-to-throw-exce"
1001      * target="_blank">
1002      * https://stackoverflow.com/questions/11942946/how-to-throw-an-exception-when-your-method-signature-doesnt-allow-to-throw-exce</a>.
1003      * @param e Throwavble; the exception of Throwable to throw in an unchecked manner
1004      */
1005     public static void throwUnchecked(final Throwable e)
1006     {
1007         Throw.<RuntimeException>throwAny(e);
1008     }
1009 
1010     /**
1011      * @param <E> The exception class
1012      * @param e Throwable; The throwable
1013      * @throws E The exception to throw
1014      */
1015     @SuppressWarnings("unchecked")
1016     private static <E extends Throwable> void throwAny(final Throwable e) throws E
1017     {
1018         throw (E) e;
1019     }
1020 }