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("Car may not be null."); 19 * } 20 * if (Double.isNaN(car.getPosition())) 21 * { 22 * throw new IllegalArgumentException("Position of car " + car + " is NaN."); 23 * } 24 * </pre> 25 * 26 * we can write: 27 * 28 * <pre> 29 * Throw.whenNull(car, "Car may not be null."); 30 * Throw.when(Double.isNaN(car.getPosition()), IllegalArgumentException.class, "Position of car %s is NaN.", 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, "Value may not be NaN."); 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<T>; 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, "Value may not be NaN for object %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s and id %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s, id %s and parent %s.", 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<T>; 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<T>; the Throwable type to throw 200 * @param message String; the message to use in the exception, with potential formatting identifiers 201 * @param argList List<Object>; 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<T>; 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 * "Value may not be NaN for object %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s and id %s.", 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<T>; 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 * "Value may not be NaN for object %s with name %s, id %s and parent %s.", 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<T>; 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, "value may not be null."); 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, "value"); 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(), "Value may not be null for object %s.", 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(), "Value may not be null for object %s with name %s.", 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(), "Value may not be null for object %s with name %s and id %s.", 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(), "Value may not be null for object %s with name %s, id %s and parent %s.", 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, "value may not be NaN."); 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, "value"); 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, "value may not be NaN."); 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, "value"); 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, "value may not be NaN."); 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, "value"); 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, "Value may not be NaN for object %s with name %s, id %s.", 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, "value may not be NaN."); 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, "value"); 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, "Value may not be NaN for object %s with name %s, id %s.", 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, "value may not be NaN."); 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, "value"); 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<T>; 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, "value may not be NaN."); 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, "value"); 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<T>; 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, "value may not be NaN."); 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, "value"); 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<T>; 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, "Value may not be NaN for object %s with name %s, 889 * id %s.", 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<T>; 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, "value may not be NaN."); 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, "value"); 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<T>; 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, "Value may not be NaN for object %s with name %s, 958 * id %s.", 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<T>; 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 * @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 }