001/* 002 * ============================================================================ 003 * Copyright © 2002-2026 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * 007 * Licensed to the public under the agreements of the GNU Lesser General Public 008 * License, version 3.0 (the "License"). You may obtain a copy of the License at 009 * 010 * http://www.gnu.org/licenses/lgpl.html 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 015 * License for the specific language governing permissions and limitations 016 * under the License. 017 */ 018 019package org.tquadrat.foundation.lang; 020 021import static java.lang.Integer.signum; 022import static java.util.Arrays.deepToString; 023import static org.apiguardian.api.API.Status.DEPRECATED; 024import static org.apiguardian.api.API.Status.STABLE; 025import static org.tquadrat.foundation.lang.CommonConstants.NULL_STRING; 026 027import java.lang.reflect.Array; 028import java.util.Arrays; 029import java.util.Collection; 030import java.util.Collections; 031import java.util.Comparator; 032import java.util.Enumeration; 033import java.util.List; 034import java.util.Map; 035import java.util.Optional; 036import java.util.function.BiFunction; 037import java.util.function.DoublePredicate; 038import java.util.function.Function; 039import java.util.function.IntPredicate; 040import java.util.function.LongPredicate; 041import java.util.function.Predicate; 042import java.util.function.Supplier; 043import java.util.function.UnaryOperator; 044 045import org.apiguardian.api.API; 046import org.tquadrat.foundation.annotation.ClassVersion; 047import org.tquadrat.foundation.annotation.UtilityClass; 048import org.tquadrat.foundation.exception.BlankArgumentException; 049import org.tquadrat.foundation.exception.EmptyArgumentException; 050import org.tquadrat.foundation.exception.NullArgumentException; 051import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError; 052import org.tquadrat.foundation.exception.ValidationException; 053 054/** 055 * <p>{@summary This class consists of several utility methods working on 056 * {@link Object} 057 * instances, similar to those on 058 * {@link Arrays} 059 * or 060 * {@link Collections}.}</p> 061 * <p>The class was originally inspired by the class of the same name that 062 * was finally introduced with the Java 7 release; some of its methods 063 * will delegate to 064 * {@link java.util.Objects java.util.Objects}, 065 * others will extend the functionality of the methods with the same 066 * name from {@code java.util.Objects}.</p> 067 * <p>If a method from {@code java.util.Objects} would throw a 068 * {@link NullPointerException}, 069 * the method with the same name from this class would throw a 070 * {@link ValidationException} 071 * instead.</p> 072 * 073 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 074 * @version $Id: Objects.java 1258 2026-06-04 18:33:06Z tquadrat $ 075 * @since 0.0.1 076 * 077 * @UMLGraph.link 078 */ 079@UtilityClass 080@SuppressWarnings( {"ClassWithTooManyMethods", "UseOfObsoleteDateTimeApi", "OverlyComplexClass"} ) 081@ClassVersion( sourceVersion = "$Id: Objects.java 1258 2026-06-04 18:33:06Z tquadrat $" ) 082@API( status = STABLE, since = "0.0.1" ) 083public final class Objects 084{ 085 /*--------------*\ 086 ====** Constructors **===================================================== 087 \*--------------*/ 088 /** 089 * No instance allowed for this class. 090 */ 091 private Objects() { throw new PrivateConstructorForStaticClassCalledError( Objects.class ); } 092 093 /*---------*\ 094 ====** Methods **========================================================== 095 \*---------*/ 096 /** 097 * <p>{@summary Checks if the sub-range from {@code fromIndex} (inclusive) 098 * to {@code fromIndex + size} (exclusive) is within the bounds of range 099 * from {@code 0} (inclusive) to {@code length} (exclusive).}</p> 100 * <p>The sub-range is defined to be out-of-bounds if any of the following 101 * inequalities is true:</p> 102 * <ul> 103 * <li>{@code fromIndex < 0}</li> 104 * <li>{@code size < 0}</li> 105 * <li>{@code fromIndex + size > length}, taking into account integer 106 * overflow</li> 107 * <li>{@code length < 0}, which is implied from the former 108 * inequalities</li> 109 * </ul> 110 * <p>Calls 111 * {@link java.util.Objects#checkFromIndexSize(int,int,int) java.util.Objects.checkFromIndexSize(int,int,int)} 112 * internally.</p> 113 * 114 * @param fromIndex The lower-bound (inclusive) of the sub-interval. 115 * @param size The size of the sub-range. 116 * @param length The upper-bound (exclusive) of the range. 117 * @return The {@code fromIndex} if the sub-range is within bounds of the 118 * range. 119 * @throws IndexOutOfBoundsException The sub-range is out-of-bounds. 120 * 121 * @since 0.0.5 122 */ 123 @API( status = STABLE, since = "0.0.5" ) 124 public static final int checkFromIndexSize( final int fromIndex, final int size, final int length ) 125 { 126 final var retValue = java.util.Objects.checkFromIndexSize( fromIndex, size, length ); 127 128 //---* Done *---------------------------------------------------------- 129 return retValue; 130 } // checkFromIndexSize() 131 132 /** 133 * <p>{@summary Checks if the sub-range from {@code fromIndex} (inclusive) 134 * to {@code toIndex} (exclusive) is within the bounds of range from 135 * {@code 0} (inclusive) to {@code length} (exclusive).}</p> 136 * <p>The sub-range is defined to be out-of-bounds if any of the following 137 * inequalities is true:</p> 138 * <ul> 139 * <li>{@code fromIndex < 0}</li> 140 * <li>{@code fromIndex > toIndex}</li> 141 * <li>{@code toIndex > length}</li> 142 * <li>{@code length < 0}, which is implied from the former 143 * inequalities</li> 144 * </ul> 145 * <p>Calls 146 * {@link java.util.Objects#checkFromToIndex(int,int,int) java.util.Objects.checkFromToIndex(int,int,int)} 147 * internally.</p> 148 * 149 * @param fromIndex The lower-bound (inclusive) of the sub-range. 150 * @param toIndex The upper-bound (exclusive) of the sub-range. 151 * @param length The upper-bound (exclusive) the range. 152 * @return The {@code fromIndex} if the sub-range is within bounds of the 153 * range. 154 * @throws IndexOutOfBoundsException The sub-range is out-of-bounds. 155 * 156 * @since 0.0.5 157 */ 158 @API( status = STABLE, since = "0.0.5" ) 159 public static final int checkFromToIndex( final int fromIndex, final int toIndex, final int length ) 160 { 161 final var retValue = java.util.Objects.checkFromToIndex( fromIndex, toIndex, length ); 162 163 //---* Done *---------------------------------------------------------- 164 return retValue; 165 } // checkFromToIndex() 166 167 /** 168 * <p>{@summary Checks if the {@code index} is within the bounds of the 169 * range from {@code 0} (inclusive) to {@code length} (exclusive).}</p> 170 * <p>The {@code index} is defined to be out-of-bounds if any of the 171 * following inequalities is true:</p> 172 * <ul> 173 * <li>{@code index < 0}</li> 174 * <li>{@code index >= length}</li> 175 * <li>{@code length < 0}, which is implied from the former 176 * inequalities</li> 177 * </ul> 178 * <p>Calls 179 * {@link java.util.Objects#checkIndex(int,int) java.util.Objects.checkIndex(int,int)} 180 * internally.</p> 181 * 182 * @param index The index. 183 * @param length The upper-bound (exclusive) of the range. 184 * @return The {@code index} if it is within bounds of the range. 185 * @throws IndexOutOfBoundsException The {@code index} is out-of-bounds. 186 * 187 * @since 0.0.5 188 */ 189 @API( status = STABLE, since = "0.0.5" ) 190 public static final int checkIndex( final int index, final int length ) 191 { 192 final var retValue = java.util.Objects.checkIndex( index, length ); 193 194 //---* Done *---------------------------------------------------------- 195 return retValue; 196 } // checkIndex() 197 198 /** 199 * <p>{@summary Throws the exception provided by the given supplier if the 200 * condition resolves to {@false}.}</p> 201 * <p>Basically, this method is a replacement for the code sequence 202 * below:</p> 203 * <div class="source-container"><pre>… 204 * if( !<<i>condition</i>> ) 205 * { 206 * throw new <<i>WhatEver</i>>Exception( <<i>WhatEverMessage</i>> ); 207 * } 208 * …</pre></div> 209 * <p>Code using this method may be easier to read than the {@code if} 210 * statement above:</p> 211 * <div class="source-container"><pre>… 212 * checkState( <<i>condition</i>>, () -> new <<i>WhatEver</i>>Exception( <<i>WhatEverMessage</i>> ) ); 213 * …</pre></div> 214 * 215 * @param <E> The type of the exception that is thrown in case the 216 * condition is not met. 217 * @param condition The condition to check. 218 * @param exception The exception to throw. 219 * @throws E The condition was not met. 220 */ 221 @SuppressWarnings( "CheckedExceptionClass" ) 222 public static final <E extends Exception> void checkState( final boolean condition, final Supplier<E> exception ) throws E 223 { 224 if( !condition ) throw requireNonNullArgument( exception, "exception" ).get(); 225 } // checkState() 226 227 /** 228 * <p>{@summary Returns 0 if the arguments are identical and 229 * {@code comparator.compare(a, b)} otherwise.}</p> 230 * <p>Consequently, if both arguments are {@null}, 0 is returned.</p> 231 * <p>Calls 232 * {@link java.util.Objects#compare(Object,Object,Comparator) java.util.Objects#compare()} 233 * internally, but different from that method, this implementation will 234 * throw a 235 * {@link NullArgumentException} 236 * in case the {@code comparator} is {@null}.</p> 237 * 238 * @param <T> The type of the objects being compared. 239 * @param object An object. 240 * @param other Another object to be compared with the first object. 241 * @param comparator The 242 * {@link Comparator} 243 * to compare the first two arguments. 244 * @return 0 if the arguments are identical and +1, 0, or -1, based on the 245 * return value of {@code c.compare(a, b)} otherwise. 246 * @throws NullArgumentException The {@code comparator} is {@null}. 247 * 248 * @see Comparable 249 * @see Comparator 250 * 251 * @since 0.0.5 252 */ 253 @API( status = STABLE, since = "0.0.5" ) 254 public static final <T> int compare( final T object, final T other, final Comparator<? super T> comparator ) throws NullArgumentException 255 { 256 final var retValue = object == other ? 0 : signum( java.util.Objects.compare( object, other, requireNonNullArgument( comparator, "comparator" ) ) ); 257 258 //---* Done *---------------------------------------------------------- 259 return retValue; 260 } // compare() 261 262 /** 263 * <p>{@summary Returns {@true} if the arguments are deeply equal to 264 * each other and {@false} otherwise.}</p> 265 * <p>Two {@null} values are deeply equal. If both arguments are 266 * arrays, the algorithm in 267 * {@link Arrays#deepEquals(Object[], Object[]) Arrays.deepEquals()} 268 * is used to determine equality. Otherwise, equality is determined by 269 * using the 270 * {@link Object#equals(Object) equals()} 271 * method of the first argument.</p> 272 * <p>Calls 273 * {@link java.util.Objects#deepEquals(Object,Object) java.util.Objects#deepEquals()} 274 * internally.</p> 275 * 276 * @param object An object. 277 * @param other Another object to be compared with the first object for 278 * deep equality. 279 * @return {@true} if the arguments are deeply equal to each other 280 * and {@false} otherwise. 281 * 282 * @see Arrays#deepEquals(Object[],Object[]) 283 * @see Objects#equals(Object,Object) 284 * 285 * @since 0.0.5 286 */ 287 @SuppressWarnings( "BooleanMethodNameMustStartWithQuestion" ) 288 @API( status = STABLE, since = "0.0.5" ) 289 public static final boolean deepEquals( final Object object, final Object other ) { return java.util.Objects.deepEquals( object, other ); } 290 291 /** 292 * <p>{@summary Returns {@true} if the arguments are equal to each 293 * other and {@false} otherwise.}</p> 294 * <p> Consequently, if both arguments are {@null}, {@true} is 295 * returned and if exactly one argument is {@null}, {@false} is 296 * returned. Otherwise, equality is determined by using the 297 * {@link Object#equals(Object) equals()} 298 * method of the first argument.</p> 299 * <p>Calls 300 * {@link java.util.Objects#equals(Object, Object)} 301 * internally.</p> 302 * 303 * @param object An object. 304 * @param other Another object to be compared with the first one for 305 * equality. 306 * @return {@true} if the arguments are equal to each other and 307 * {@false} otherwise. 308 * 309 * @see Object#equals(Object) 310 * 311 * @since 0.0.5 312 */ 313 @API( status = STABLE, since = "0.0.5" ) 314 public static final boolean equals( final Object object, final Object other ) { return java.util.Objects.equals( object, other ); } 315 316 /** 317 * <p>{@summary Generates a hash code for a sequence of input values.} The 318 * hash code is generated as if all the input values were placed into an 319 * array, and that array is hashed by calling 320 * {@link Arrays#hashCode(Object[])}.</p> 321 * <p>Calls 322 * {@link java.util.Arrays#hashCode(Object[]) java.util.Arrays.hashCode()} 323 * internally.</p> 324 * 325 * @param values The values to be hashed. 326 * @return A hash value of the sequence of input values. 327 * 328 * @see List#hashCode 329 * 330 * @since 0.0.5 331 */ 332 @API( status = STABLE, since = "0.0.5" ) 333 public static final int hash( final Object... values ) { return Arrays.hashCode( values ); } 334 335 /** 336 * <p>{@summary Returns the hash code of a non-{@null} argument and 0 337 * for a {@null} argument.}</p> 338 * <p>Calls 339 * {@link java.util.Objects#hashCode(Object) java.util.Objects.hashCode(Object)} 340 * internally.</p> 341 * 342 * @param o An object. 343 * @return The hash code of an argument that is not {@null}, and 0 344 * for a {@null} argument, 345 * 346 * @see Object#hashCode 347 * 348 * @since 0.0.5 349 */ 350 @API( status = STABLE, since = "0.0.5" ) 351 public static final int hashCode( final Object o ) { return java.util.Objects.hashCode( o ); } 352 353 /** 354 * <p>{@summary Returns {@true} if the provided reference is 355 * {@null}, otherwise returns {@false}.}</p> 356 * <p>This method can be used as a 357 * {@link java.util.function.Predicate}, 358 * {@code filter(Objects::isNull)}.</p> 359 * <p>Calls 360 * {@link java.util.Objects#isNull(Object) java.util.Objects.isNull()} 361 * internally.</p> 362 * 363 * @param obj A reference to be checked against {@null}. 364 * @return {@true} if the provided reference is {@null}, 365 * otherwise {@false} 366 * 367 * @see java.util.function.Predicate 368 * @see org.tquadrat.foundation.lang.CommonConstants#IS_NULL 369 * 370 * @since 0.0.5 371 */ 372 @API( status = STABLE, since = "0.0.5" ) 373 public static final boolean isNull( final Object obj ) { return java.util.Objects.isNull( obj ); } 374 375 /** 376 * <p>{@summary Provides a replacement value if the given value is 377 * {@null}.}</p> 378 * <p>This is basically a shortcut to</p> 379 * <div class="source-container"><pre>Optional.ofNullable( value ).orElseGet( supplier );</pre></div> 380 * 381 * @param <T> The type of the object to map. 382 * @param value The object to map; can be {@null} (obviously). 383 * @param supplier The supplier for the replacement function. 384 * @return The provided object if that is not {@null}, or the result 385 * from the supplier method. Keep in mind that this result can be 386 * {@null}! 387 * 388 * @see Optional 389 * @see Optional#orElseGet(Supplier) 390 * 391 * @since 0.2.2 392 */ 393 @API( status = STABLE, since = "0.2.2" ) 394 public static final <T> T mapFromNull( final T value, final Supplier<? extends T> supplier ) 395 { 396 requireNonNullArgument( supplier, "supplier" ); 397 final var retValue = isNull( value ) 398 ? supplier.get() 399 : value; 400 401 //---* Done *---------------------------------------------------------- 402 return retValue; 403 } // mapFromNull() 404 405 /** 406 * <p>{@summary Provides a replacement value if the given value is 407 * {@null}.}</p> 408 * <p>This is basically a shortcut to</p> 409 * <div class="source-container"><pre>Optional.ofNullable( value ).orElse( replacement );</pre></div> 410 * 411 * @param <T> The type of the object to map. 412 * @param value The object to map; can be {@null}. 413 * @param replacement The replacement value; it may not be {@null}. 414 * @return The provided object if that is not {@null}, or the 415 * replacement value. 416 * 417 * @see Optional 418 * @see Optional#orElse(Object) 419 * 420 * @since 0.4.2 421 */ 422 @API( status = STABLE, since = "0.4.2" ) 423 public static final <T> T mapFromNull( final T value, final T replacement ) 424 { 425 requireNonNullArgument( replacement, "replacement" ); 426 final var retValue = isNull( value ) 427 ? replacement 428 : value; 429 430 //---* Done *---------------------------------------------------------- 431 return retValue; 432 } // mapFromNull() 433 434 /** 435 * <p>{@summary Maps (converts) the given object instance by applying the 436 * provided mapper if the instance is not {@null}.}</p> 437 * <p>The mapper function will not be called at all if the given instance 438 * is {@null}.</p> 439 * 440 * @param <T> The type of the object to map. 441 * @param <R> The type of the result. 442 * @param o The object to map; can be {@null}. 443 * @param mapper The mapping function. 444 * @return The result of the mapping, or {@null} if the given object 445 * instance was already {@null}. Keep in mind that the result of 446 * the mapping can be {@null}! 447 */ 448 public static final <T,R> R mapNonNull( final T o, final Function<T,? extends R> mapper ) 449 { 450 @SuppressWarnings( "RedundantExplicitVariableType" ) 451 final R retValue = nonNull( o ) ? requireNonNullArgument( mapper, "mapper" ).apply( o ) : null; 452 453 //---* Done *---------------------------------------------------------- 454 return retValue; 455 } // mapNonNull() 456 457 /** 458 * <p>{@summary Maps (converts) the given object instance by applying the 459 * provided mapper if the instance is not {@null} or returns the 460 * given default value.}</p> 461 * <p>The mapper function will not be called at all if the given instance 462 * is {@null}.</p> 463 * 464 * @param <T> The type of the object to map. 465 * @param <R> The type of the result. 466 * @param o The object to map; can be {@null}. 467 * @param mapper The mapping function. 468 * @param defaultValue The default value; can be {@null}. 469 * @return The result of the mapping, or the default value if the given 470 * object instance is {@null}. Keep in mind that the result of 471 * the mapping can be {@null}! 472 */ 473 public static final <T,R> R mapNonNull( final T o, final Function<T,? extends R> mapper, final R defaultValue ) 474 { 475 @SuppressWarnings( "RedundantExplicitVariableType" ) 476 final R retValue = nonNull( o ) ? requireNonNullArgument( mapper, "mapper" ).apply( o ) : defaultValue; 477 478 //---* Done *---------------------------------------------------------- 479 return retValue; 480 } // mapNonNull() 481 482 /** 483 * <p>{@summary Returns {@true} if the provided reference is not 484 * {@null}, otherwise returns {@false}.}</p> 485 * <p>This method exists to be used as a 486 * {@link java.util.function.Predicate}, 487 * {@code filter(Objects::nonNull)}</p> 488 * <p>Calls 489 * {@link java.util.Objects#nonNull(Object) java.util.Objects.nonNull()} 490 * internally.</p> 491 * 492 * @param obj A reference to be checked against {@null} 493 * @return {@false} if the provided reference is {@null}, 494 * otherwise {@true} 495 * 496 * @see java.util.function.Predicate 497 * @see org.tquadrat.foundation.lang.CommonConstants#NON_NULL 498 * 499 * @since 0.0.5 500 */ 501 @SuppressWarnings( "BooleanMethodNameMustStartWithQuestion" ) 502 @API( status = STABLE, since = "0.0.5" ) 503 public static final boolean nonNull( final Object obj ) { return java.util.Objects.nonNull( obj ); } 504 505 /** 506 * Applies the given validation on the given value, and if that fails, an 507 * {@link ValidationException} 508 * is thrown. 509 * 510 * @param <T> The type of the value to check. 511 * @param obj The value to check; can be {@null}. 512 * @param validation The validation 513 * @return The value if the validation succeeds. 514 * @throws ValidationException {@code obj} failed the validation. 515 * 516 * @since 0.1.0 517 */ 518 @SuppressWarnings( "NewExceptionWithoutArguments" ) 519 @API( status = STABLE, since = "0.1.0" ) 520 public static final <T> T require( final T obj, final Predicate<? super T> validation ) throws ValidationException 521 { 522 if( !requireNonNullArgument( validation, "validation" ).test( obj ) ) 523 { 524 throw new ValidationException(); 525 } 526 527 //---* Done *---------------------------------------------------------- 528 return obj; 529 } // require() 530 531 /** 532 * Applies the given validation on the given value, and if that fails, an 533 * {@link ValidationException} 534 * with the specified message is thrown. 535 * 536 * @param <T> The type of the value to check. 537 * @param obj The value to check; can be {@null}. 538 * @param message The message that is set to the thrown exception. 539 * @param validation The validation 540 * @return The value if the validation succeeds. 541 * @throws ValidationException {@code obj} failed the validation. 542 * @throws NullArgumentException {@code message} is {@null}. 543 * @throws EmptyArgumentException {@code message} is the empty String. 544 * 545 * @since 0.1.0 546 */ 547 @API( status = STABLE, since = "0.1.0" ) 548 public static final <T> T require( final T obj, final String message, final Predicate<? super T> validation ) throws ValidationException, NullArgumentException, EmptyArgumentException 549 { 550 requireNotEmptyArgument( message, "message" ); 551 552 if( !requireNonNullArgument( validation, "validation" ).test( obj ) ) 553 { 554 throw new ValidationException( message ); 555 } 556 557 //---* Done *---------------------------------------------------------- 558 return obj; 559 } // require() 560 561 /** 562 * <p>{@summary Applies the given validation on the given value, and if 563 * that fails, a customized 564 * {@link ValidationException} 565 * is thrown.}</p> 566 * <p>Unlike the method 567 * {@link #require(Object,String,Predicate)}, 568 * this method allows to defer the creation of the message until after the 569 * validation was performed (and failed). While this may confer a 570 * performance advantage in the success case, some care should be taken 571 * that the costs for the creation of the message supplier are less than 572 * the cost of just creating the String message directly.</p> 573 * 574 * @param <T> The type of the value to check. 575 * @param obj The value to check; can be {@null}. 576 * @param messageSupplier The supplier of the detail message to be used 577 * in the event that {@code ValidationException} is thrown. If 578 * {@null} or if it returns {@null}, no detail message is 579 * provided to the exception. 580 * @param validation The validation 581 * @return The value if the validation succeeds. 582 * @throws NullArgumentException The validation is {@null}. 583 * @throws ValidationException {@code obk} failed the validation. 584 * 585 * @since 0.1.0 586 */ 587 @SuppressWarnings( "NewExceptionWithoutArguments" ) 588 @API( status = STABLE, since = "0.1.0" ) 589 public static final <T> T require( final T obj, final Supplier<String> messageSupplier, final Predicate<? super T> validation ) throws ValidationException 590 { 591 if( !requireNonNullArgument( validation, "validation" ).test( obj ) ) 592 { 593 final var exception = nonNull( messageSupplier ) 594 ? new ValidationException( messageSupplier.get() ) 595 : new ValidationException(); 596 throw exception; 597 } 598 599 //---* Done *---------------------------------------------------------- 600 return obj; 601 } // require() 602 603 /** 604 * <p>{@summary Applies the given validation on the given value, and if 605 * that fails, a customized 606 * {@link ValidationException} 607 * is thrown.}</p> 608 * <p>Unlike the method 609 * {@link #require(Object,String,Predicate)}, 610 * this method allows to defer the creation of the message until after the 611 * validation was performed (and failed). While this may confer a 612 * performance advantage in the success case, some care should be taken 613 * that the costs the creation of the message supplier are less than the 614 * cost of just creating the String message directly.</p> 615 * <p>This implementation is different from 616 * {@link #requireNonNull(Object, Supplier)} 617 * as it takes an instance of 618 * {@link Function} 619 * for the {@code messageSupplier}. That function is called with 620 * {@code obj} as the argument; this allows to add the invalid value to 621 * the exception detail message. The provided message supplier function 622 * must accept {@null} as a valid argument.</p> 623 * 624 * @param <T> The type of the value to check. 625 * @param obj The value to check; can be {@null}. 626 * @param messageSupplier The supplier of the detail message to be used 627 * in the event that a {@code ValidationException} is thrown. If 628 * {@null} or if it returns {@null}, no detail message is 629 * provided. 630 * @param validation The validation 631 * @return The value if the validation succeeds. 632 * @throws NullArgumentException The validation is {@null}. 633 * @throws ValidationException {@code obj} failed the validation. 634 * 635 * @since 0.1.0 636 */ 637 @SuppressWarnings( "NewExceptionWithoutArguments" ) 638 @API( status = STABLE, since = "0.1.0" ) 639 public static final <T> T require( final T obj, final Function<? super T,String> messageSupplier, final Predicate<? super T> validation ) throws ValidationException 640 { 641 if( !requireNonNullArgument( validation, "validation" ).test( obj ) ) 642 { 643 final var exception = nonNull( messageSupplier ) 644 ? new ValidationException( messageSupplier.apply( obj ) ) 645 : new NullArgumentException(); 646 throw exception; 647 } 648 649 //---* Done *---------------------------------------------------------- 650 return obj; 651 } // require() 652 653 /** 654 * <p>{@summary Checks if the given value {@code obj} is {@null} and 655 * throws a 656 * {@link NullArgumentException} 657 * if it is {@null}.}</p> 658 * 659 * @param <T> The type of the value to check. 660 * @param obj The value to check. 661 * @return The value if it is not {@null}. 662 * @throws NullArgumentException {@code obj} is {@null}. 663 * 664 * @see java.util.Objects#requireNonNull(Object) 665 * 666 * @since 0.0.5 667 */ 668 @SuppressWarnings( "NewExceptionWithoutArguments" ) 669 @API( status = STABLE, since = "0.0.5" ) 670 public static final <T> T requireNonNull( final T obj ) throws NullArgumentException 671 { 672 if( isNull( obj ) ) throw new NullArgumentException(); 673 674 //---* Done *---------------------------------------------------------- 675 return obj; 676 } // requireNonNull() 677 678 /** 679 * <p>{@summary Checks if the given value {@code obj} is {@null} and 680 * throws a 681 * {@link ValidationException} 682 * with the specified message if it is {@null}.}</p> 683 * 684 * @param <T> The type of the value to check. 685 * @param obj The value to check. 686 * @param message The message that is set to the thrown exception. 687 * @return The value if it is not {@null}. 688 * @throws NullArgumentException {@code message} or {@code obj} is 689 * {@null}. 690 * @throws EmptyArgumentException {@code message} is the empty String. 691 * 692 * @see java.util.Objects#requireNonNull(Object,String) 693 * 694 * @since 0.0.5 695 */ 696 @API( status = STABLE, since = "0.0.5" ) 697 public static final <T> T requireNonNull( final T obj, final String message ) throws ValidationException, NullArgumentException, EmptyArgumentException 698 { 699 requireNotEmptyArgument( message, "message" ); 700 if( isNull( obj ) ) throw new ValidationException( message ); 701 702 //---* Done *---------------------------------------------------------- 703 return obj; 704 } // requireNonNull() 705 706 /** 707 * <p>{@summary Checks that the specified object reference is not 708 * {@null} and throws a customized 709 * {@link ValidationException} 710 * if it is.}</p> 711 * <p>Unlike the method 712 * {@link #requireNonNull(Object,String)}, 713 * this method allows to defer the creation of the message until after the 714 * null check failed. While this may confer a performance advantage in the 715 * non-{@null} case, when deciding to call this method care should be 716 * taken that the costs of creating the message supplier are less than the 717 * cost of just creating the String message directly.</p> 718 * 719 * @param <T> The type of the value to check. 720 * @param obj The value to check. 721 * @param messageSupplier The supplier of the detail message to be used 722 * in the event that a {@code NullArgumentException} is thrown. If 723 * {@null}, no detail message is provided. 724 * @return The value if it is not {@null}. 725 * @throws ValidationException {@code obj} is {@null} 726 * 727 * @since 0.0.5 728 */ 729 @API( status = STABLE, since = "0.0.5" ) 730 public static final <T> T requireNonNull( final T obj, final Supplier<String> messageSupplier) throws ValidationException 731 { 732 if( isNull( obj ) ) 733 { 734 final var message = nonNull( messageSupplier ) ? messageSupplier.get() : null; 735 @SuppressWarnings( "NewExceptionWithoutArguments" ) 736 final var exception = isNull( message ) ? new NullArgumentException() : new ValidationException( message ); 737 throw exception; 738 } 739 740 //---* Done *---------------------------------------------------------- 741 return obj; 742 } // requireNonNull() 743 744 /** 745 * Checks if the given argument {@code a} is {@null} and throws a 746 * {@link NullArgumentException} 747 * if it is {@null}. 748 * 749 * @param <T> The type of the argument to check. 750 * @param arg The argument to check. 751 * @param name The name of the argument; this is used for the error 752 * message. 753 * @return The argument if it is not {@null}. 754 * @throws NullArgumentException {@code arg} is {@null}. 755 * 756 * @since 0.0.5 757 */ 758 @API( status = STABLE, since = "0.0.5" ) 759 public static final <T> T requireNonNullArgument( final T arg, final String name ) 760 { 761 if( isNull( name ) ) throw new NullArgumentException( "name" ); 762 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 763 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 764 if( isNull( arg ) ) throw new NullArgumentException( name ); 765 766 //---* Done *---------------------------------------------------------- 767 return arg; 768 } // requireNonNullArgument() 769 770 /** 771 * <p>{@summary Checks if not both of the given arguments {@code arg} and 772 * {@code otherArg} are {@null} and throws a 773 * {@link NullArgumentException} 774 * if both are {@null}.} Otherwise, it returns {@code arg}.</p> 775 * 776 * @param <T> The type of the first argument to check. 777 * @param arg The first argument to check; it will be returned in case of 778 * success, even if {@null}. 779 * @param otherArg The other argument to check. 780 * @param name The name of the first argument; this is used for the 781 * error message. 782 * @param otherName The name of the other argument; this is used for 783 * the error message. 784 * @return The first argument, even that might be {@null}. 785 * @throws NullArgumentException Both arguments are {@null}. 786 * 787 * @since 0.0.7 788 */ 789 @API( status = STABLE, since = "0.0.7" ) 790 public static final <T> T requireNonNullArgument( final T arg, final Object otherArg, final String name, final String otherName ) 791 { 792 if( isNull( name ) ) throw new NullArgumentException( "name" ); 793 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 794 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 795 if( isNull( otherName ) ) throw new NullArgumentException( "otherName" ); 796 if( otherName.isEmpty() ) throw new EmptyArgumentException( "otherName" ); 797 if( otherName.isBlank() ) throw new BlankArgumentException( "otherName" ); 798 if( isNull( arg ) && isNull( otherArg ) ) 799 { 800 throw new NullArgumentException( name, otherName ); 801 } 802 803 //---* Done *---------------------------------------------------------- 804 return arg; 805 } // requireNonNullArgument() 806 807 /** 808 * <p>{@summary Checks if the given String argument {@code arg} is 809 * {@null}, empty or blank and throws a 810 * {@link NullArgumentException} 811 * if it is {@null}, an 812 * {@link EmptyArgumentException} 813 * if it is empty, or a 814 * {@link BlankArgumentException} 815 * if it is blank.}</p> 816 * 817 * @param <T> The type of the argument to check. 818 * @param arg The argument to check; may be {@null}. 819 * @param name The name of the argument; this is used for the error 820 * message. 821 * @return The argument if it is not {@null}, empty or blank. 822 * @throws NullArgumentException {@code arg} is {@null}. 823 * @throws EmptyArgumentException {@code arg} is empty. 824 * @throws BlankArgumentException {@code arg} is blank. 825 * 826 * @see String#isBlank() 827 * 828 * @since 0.1.0 829 */ 830 @SuppressWarnings( "OverlyComplexMethod" ) 831 @API( status = STABLE, since = "0.1.0" ) 832 public static final <T extends CharSequence> T requireNotBlankArgument( final T arg, final String name ) 833 { 834 if( isNull( name ) ) throw new NullArgumentException( "name" ); 835 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 836 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 837 838 switch( arg ) 839 { 840 case null -> throw new NullArgumentException( name ); 841 case final String string -> 842 { 843 if( string.isEmpty() ) throw new EmptyArgumentException( name ); 844 if( string.isBlank() ) throw new BlankArgumentException( name ); 845 } 846 case final CharSequence charSequence -> 847 { 848 if( charSequence.isEmpty() ) throw new EmptyArgumentException( name ); 849 if( charSequence.toString().isBlank() ) throw new BlankArgumentException( name ); 850 } 851 } 852 853 //---* Done *---------------------------------------------------------- 854 return arg; 855 } // requireNotBlankArgument() 856 857 /** 858 * <p>{@summary Checks if the given argument {@code arg} is {@null} or 859 * empty and throws a 860 * {@link NullArgumentException} 861 * if it is {@null}, or an 862 * {@link EmptyArgumentException} 863 * if it is empty.}</p> 864 * <p>Strings, arrays, instances of 865 * {@link java.util.Collection} and 866 * {@link java.util.Map} 867 * as well as instances of 868 * {@link java.lang.StringBuilder}, 869 * {@link java.lang.StringBuffer}, 870 * and 871 * {@link java.lang.CharSequence} 872 * will be checked on being empty.</p> 873 * <p>For an instance of 874 * {@link java.util.Optional}, 875 * the presence of a value is checked in order to determine whether the 876 * {@link Optional} is empty or not.</p> 877 * <p>Because the interface 878 * {@link java.util.Enumeration} 879 * does not provide an API for the check on emptiness 880 * ({@link java.util.Enumeration#hasMoreElements() hasMoreElements()} 881 * will return {@false} after all elements have been taken from 882 * the {@code Enumeration} instance), the result for arguments of this 883 * type has to be taken with caution.</p> 884 * <p>For instances of 885 * {@link java.util.stream.Stream}, 886 * this method will only check for {@null} (like 887 * {@link #requireNonNullArgument(Object,String)}. 888 * This is because any operation on the stream itself would render it 889 * unusable for later processing.</p> 890 * <p>In case the argument is of type 891 * {@link Optional}, 892 * this method behaves different from 893 * {@link #requireNotEmptyArgument(Optional,String)}; 894 * this one will return the {@code Optional} instance, while the other 895 * method will return the contents of the {@code Optional}.</p> 896 * <p>This method will not work properly for instances of 897 * {@link java.util.StringJoiner}, because its method 898 * {@link java.util.StringJoiner#length() length()} 899 * will not return 0 when a prefix, suffix, or an 900 * "{@linkplain java.util.StringJoiner#setEmptyValue(CharSequence) empty value}" 901 * was provided.</p> 902 * 903 * @param <T> The type of the argument to check. 904 * @param arg The argument to check; may be {@null}. 905 * @param name The name of the argument; this is used for the error 906 * message. 907 * @return The argument if it is not {@null} or empty. 908 * @throws NullArgumentException {@code arg} is {@null}. 909 * @throws EmptyArgumentException {@code arg} is empty. 910 * 911 * @since 0.0.5 912 */ 913 @SuppressWarnings( "OverlyComplexMethod" ) 914 @API( status = STABLE, since = "0.0.5" ) 915 public static final <T> T requireNotEmptyArgument( final T arg, final String name ) 916 { 917 if( isNull( name ) ) throw new NullArgumentException( "name" ); 918 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 919 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 920 921 switch( arg ) 922 { 923 /* 924 * When using guarding expressions, the code would not get better 925 * to read and to understand, as the positive cases will be handled 926 * all by the default case. 927 */ 928 case null -> throw new NullArgumentException( name ); 929 case final CharSequence charSequence -> 930 { 931 if( charSequence.isEmpty() ) throw new EmptyArgumentException( name ); 932 } 933 case final Collection<?> collection -> 934 { 935 if( collection.isEmpty() ) throw new EmptyArgumentException( name ); 936 } 937 case final Map<?,?> map -> 938 { 939 if( map.isEmpty() ) throw new EmptyArgumentException( name ); 940 } 941 case final Enumeration<?> enumeration -> 942 { 943 /* 944 * The funny thing with an Enumeration is that it could have 945 * been not empty in the beginning, but it may be empty 946 * (= having no more elements) now. 947 * The good thing is that Enumeration.hasMoreElements() will 948 * not change the state of the Enumeration - at least it should 949 * not do so. 950 */ 951 if( !enumeration.hasMoreElements() ) throw new EmptyArgumentException( name ); 952 } 953 case final Optional<?> optional -> 954 { 955 /* 956 * This is different from the behaviour of 957 * requireNotEmptyArgument(Optional,String) as the Optional 958 * will be returned here. 959 */ 960 if( optional.isEmpty() ) throw new EmptyArgumentException( name ); 961 } 962 default -> 963 { 964 if( arg.getClass().isArray() ) 965 { 966 if( Array.getLength( arg ) == 0 ) throw new EmptyArgumentException( name ); 967 } 968 else 969 { 970 /* 971 * Other data types are not further processed; in 972 * particular, instances of Stream cannot be checked on 973 * being empty. This is because any operation on the Stream 974 * itself will change its state and may make the Stream 975 * unusable. 976 */ 977 } 978 } 979 } 980 981 //---* Done *---------------------------------------------------------- 982 return arg; 983 } // requireNotEmptyArgument() 984 985 /** 986 * <p>{@summary Checks if the given argument {@code optional} of type 987 * {@link Optional} 988 * is {@null} or 989 * {@linkplain Optional#empty() empty} 990 * and throws a 991 * {@link NullArgumentException} 992 * if it is {@null}, or a 993 * {@link EmptyArgumentException} 994 * if it is empty.}</p> 995 * <p>Otherwise it returns the value of the {@code Optional}.</p> 996 * <p>This is different from the behaviour of 997 * {@link #requireNotEmptyArgument(Object,String)} 998 * with an instance of {@code Optional} as the argument to test.</p> 999 * 1000 * @param <T> The type of the given {@code Optional} to check. 1001 * @param optional The argument to check; can be {@null}. 1002 * @param name The name of the argument; this is used for the error 1003 * message. 1004 * @return The value of the argument if {@code optional} is not 1005 * {@null} 1006 * and not 1007 * {@linkplain Optional#empty() empty}. This could be the empty 1008 * string! 1009 * @throws NullArgumentException {@code optional} is {@null}. 1010 * @throws EmptyArgumentException {@code optional} is empty. 1011 * 1012 * @since 0.0.5 1013 */ 1014 @API( status = STABLE, since = "0.0.5" ) 1015 public static final <T> T requireNotEmptyArgument( @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" ) final Optional<T> optional, final String name ) 1016 { 1017 if( isNull( name ) ) throw new NullArgumentException( "name" ); 1018 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 1019 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 1020 1021 //---* Check for null *------------------------------------------------ 1022 if( isNull( optional ) ) throw new NullArgumentException( name ); 1023 final var retValue = optional.orElseThrow( () -> new EmptyArgumentException( name ) ); 1024 1025 //---* Done *---------------------------------------------------------- 1026 return retValue; 1027 } // requireNotEmptyArgument() 1028 1029 /** 1030 * <p>{@summary Returns the first argument if it is not {@null}, 1031 * otherwise it returns the non-{@null} second argument.}</p> 1032 * <p>This implementation behaves different from that in 1033 * {@link java.util.Objects#requireNonNullElse(Object,Object) java.util.Objects.requireNonNullElse(Object,Object)} 1034 * as it will always check that the default is not {@null}.</p> 1035 * 1036 * @param <T> The type of the references. 1037 * @param obj An object reference. 1038 * @param defaultObj Another object reference to be returned if the 1039 * first argument is {@null}. 1040 * @return The first argument if it is not {@null}, otherwise the 1041 * second argument if it is not {@null}. 1042 * @throws NullArgumentException The {@code defaultObj} is {@null}. 1043 * 1044 * @see java.util.Objects#requireNonNullElse(Object, Object) 1045 * 1046 * @since 0.0.5 1047 */ 1048 @API( status = STABLE, since = "0.0.5" ) 1049 public static final <T> T requireNonNullElse( final T obj, final T defaultObj ) throws NullArgumentException 1050 { 1051 return java.util.Objects.requireNonNullElse( obj, requireNonNullArgument( defaultObj, "defaultObj" ) ); 1052 } // requireNonNullElse() 1053 1054 /** 1055 * <p>{@summary Returns the first argument if it is not {@null}, 1056 * otherwise it returns the non-{@null} value returned by 1057 * {@link Supplier#get() supplier.get()}.}</p> 1058 * <p>This implementation behaves different from that in 1059 * {@link java.util.Objects#requireNonNullElseGet(Object,Supplier) java.util.Objects.requireNonNullElseGet(Object,Supplier)} 1060 * as it will always check that the supplier is not {@null}.</p> 1061 * 1062 * @note Although the provided {@code Supplier} may not be {@null}, 1063 * it may <i>return</i> {@null}. 1064 * 1065 * @param <T> The type of the reference. 1066 * @param obj An object reference. 1067 * @param supplier The supplier of a non-{@null} object of type 1068 * {code T} to return if the first argument is {@null}. 1069 * @return The first argument if it is not {@null}, otherwise the 1070 * value returned by a call to {@code supplier.get()} if it is not 1071 * {@null}. 1072 * @throws NullArgumentException The {@code supplier} is {@null}. 1073 * @throws NullPointerException {@code obj} is {@null} and the 1074 * return value of {@code supplier.get()} value is {@null}, too. 1075 * 1076 * @since 0.0.5 1077 */ 1078 @SuppressWarnings( "ProhibitedExceptionDeclared" ) 1079 @API( status = STABLE, since = "0.0.5" ) 1080 public static final <T> T requireNonNullElseGet( final T obj, final Supplier<? extends T> supplier ) throws NullArgumentException, NullPointerException 1081 { 1082 return java.util.Objects.requireNonNullElseGet( obj, requireNonNullArgument( supplier, "supplier" ) ); 1083 } // requireNonNullElseGet() 1084 1085 /** 1086 * <p>{@summary Applies the given validation on the given value, and if 1087 * that fails, an 1088 * {@link ValidationException} 1089 * with a default message is thrown.} The validation is also responsible 1090 * for the {@null}-check; that means, the method 1091 * {@link Predicate#test(Object) test()} 1092 * of the validation may be called with {@null} as the argument.</p> 1093 * 1094 * @param <T> The type of the value to check. 1095 * @param arg The value to check; can be {@null}. 1096 * @param name The name of the argument; this is used for the error 1097 * message. 1098 * @param validation The validation 1099 * @return The value if the validation succeeds. 1100 * @throws ValidationException {@code arg} failed the validation. 1101 * @throws NullArgumentException {@code name} or {@code validation} is 1102 * {@null}. 1103 * @throws EmptyArgumentException {@code name} is the empty String. 1104 * 1105 * @since 0.1.0 1106 */ 1107 @API( status = STABLE, since = "0.1.0" ) 1108 public static final <T> T requireValidArgument( final T arg, final String name, final Predicate<? super T> validation ) 1109 { 1110 requireNotBlankArgument( name, "name" ); 1111 1112 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1113 { 1114 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1115 } 1116 1117 //---* Done *---------------------------------------------------------- 1118 return arg; 1119 } // requireValidArgument() 1120 1121 /** 1122 * <p>{@summary Applies the given validation on the given value, and if 1123 * that fails, a 1124 * {@link ValidationException} 1125 * is thrown.} The message for the exception will be provided by the given 1126 * message supplier that takes the name of the argument as an 1127 * argument.</p> 1128 * <p>The validation is also responsible for the {@null}-check; that 1129 * means, the method 1130 * {@link Predicate#test(Object) test()} 1131 * of the validation may be called with {@null} as the argument.</p> 1132 * 1133 * @param <T> The type of the value to check. 1134 * @param arg The value to check; can be {@null}. 1135 * @param name The name of the argument; this is used for the error 1136 * message. 1137 * @param validation The validation 1138 * @param messageSupplier The function that generates the message for the 1139 * exception. 1140 * @return The value if the validation succeeds. 1141 * @throws ValidationException {@code arg} failed the validation. 1142 * @throws NullArgumentException {@code name}, {@code validation} or 1143 * {@code messageProvider} is {@null}. 1144 * @throws EmptyArgumentException {@code name} is the empty String. 1145 * 1146 * @since 0.1.0 1147 * @deprecated Consider to migrate to 1148 * {@link #requireValidArgument(Object,String,Predicate,BiFunction)}. 1149 */ 1150 @Deprecated( since = "0.25.11", forRemoval = true ) 1151 @API( status = DEPRECATED, since = "0.1.0" ) 1152 public static final <T> T requireValidArgument( final T arg, final String name, final Predicate<? super T> validation, final UnaryOperator<String> messageSupplier ) 1153 { 1154 requireNotBlankArgument( name, "name" ); 1155 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1156 1157 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1158 { 1159 throw new ValidationException( messageSupplier.apply( name ) ); 1160 } 1161 1162 //---* Done *---------------------------------------------------------- 1163 return arg; 1164 } // requireValidArgument() 1165 1166 /** 1167 * <p>{@summary Applies the given validation on the given value, and if 1168 * that fails, a 1169 * {@link ValidationException} 1170 * is thrown.} The message for the exception will be provided by the given 1171 * {@code messageSupplier} that takes the {@code name} as the first 1172 * argument and the value ({@code arg}) as the second argument to compose 1173 * the message for the {@code ValidationException} in case the validation 1174 * failed.</p> 1175 * <p>The validation is also responsible for the {@null}-check; that 1176 * means, the method 1177 * {@link Predicate#test(Object) test()} 1178 * of the validation may be called with {@null} as the argument.</p> 1179 * 1180 * @param <T> The type of the value to check. 1181 * @param arg The value to check; can be {@null}. 1182 * @param name The name of the argument; this is used for the error 1183 * message. 1184 * @param validation The validation 1185 * @param messageSupplier The function that generates the message for the 1186 * exception. 1187 * @return The value if the validation succeeds. 1188 * @throws ValidationException {@code arg} failed the validation. 1189 * @throws NullArgumentException {@code name}, {@code validation} or 1190 * {@code messageProvider} is {@null}. 1191 * @throws EmptyArgumentException {@code name} is the empty String. 1192 * 1193 * @since 0.25.11 1194 */ 1195 @API( status = STABLE, since = "0.25.11" ) 1196 public static final <T> T requireValidArgument( final T arg, final String name, final Predicate<? super T> validation, final BiFunction<String,T,String> messageSupplier ) 1197 { 1198 requireNotBlankArgument( name, "name" ); 1199 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1200 1201 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1202 { 1203 throw new ValidationException( messageSupplier.apply( name, arg ) ); 1204 } 1205 1206 //---* Done *---------------------------------------------------------- 1207 return arg; 1208 } // requireValidArgument() 1209 1210 /** 1211 * Applies the given validation on the given value, and if that fails, an 1212 * {@link ValidationException} 1213 * with a default message is thrown. 1214 * 1215 * @param arg The value to check. 1216 * @param name The name of the argument; this is used for the error 1217 * message. 1218 * @param validation The validation 1219 * @return The value if the validation succeeds. 1220 * @throws ValidationException {@code arg} failed the validation. 1221 * @throws NullArgumentException {@code name} or {@code validation} is 1222 * {@null}. 1223 * @throws EmptyArgumentException {@code name} is the empty String. 1224 * 1225 * @since 0.2.0 1226 */ 1227 @API( status = STABLE, since = "0.2.0" ) 1228 public static final double requireValidDoubleArgument( final double arg, final String name, final DoublePredicate validation ) 1229 { 1230 requireNotBlankArgument( name, "name" ); 1231 1232 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1233 { 1234 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1235 } 1236 1237 //---* Done *---------------------------------------------------------- 1238 return arg; 1239 } // requireValidDoubleArgument() 1240 1241 /** 1242 * <p>{@summary Applies the given validation on the given value, and if 1243 * that fails, a 1244 * {@link ValidationException} 1245 * is thrown.} The message for the exception will be provided by the given 1246 * message supplier that takes the name of the argument as an 1247 * argument.</p> 1248 * 1249 * @param arg The value to check. 1250 * @param name The name of the argument; this is used for the error 1251 * message. 1252 * @param validation The validation 1253 * @param messageSupplier The function that generates the message for the 1254 * exception. 1255 * @return The value if the validation succeeds. 1256 * @throws ValidationException {@code arg} failed the validation. 1257 * @throws NullArgumentException {@code name}, {@code validation} or 1258 * {@code messageProvider} is {@null}. 1259 * @throws EmptyArgumentException {@code name} is the empty String. 1260 * 1261 * @since 0.2.0 1262 * @deprecated Consider to migrate to 1263 * {@link #requireValidDoubleArgument(double,String,DoublePredicate,BiFunction)} 1264 */ 1265 @API( status = DEPRECATED, since = "0.2.0" ) 1266 @Deprecated( since = "0.25.11", forRemoval = true ) 1267 public static final double requireValidDoubleArgument( final double arg, final String name, final DoublePredicate validation, final UnaryOperator<String> messageSupplier ) 1268 { 1269 requireNotBlankArgument( name, "name" ); 1270 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1271 1272 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1273 { 1274 throw new ValidationException( messageSupplier.apply( name ) ); 1275 } 1276 1277 //---* Done *---------------------------------------------------------- 1278 return arg; 1279 } // requireValidDoubleArgument() 1280 1281 /** 1282 * <p>{@summary Applies the given validation on the given value, and if 1283 * that fails, a 1284 * {@link ValidationException} 1285 * is thrown.} The message for the exception will be provided by the given 1286 * {@code messageSupplier} that takes the {@code name} as the first 1287 * argument and the value ({@code arg}) as the second argument to compose 1288 * the message for the {@code ValidationException} in case the validation 1289 * failed.</p> 1290 * 1291 * @param arg The value to check. 1292 * @param name The name of the argument; this is used for the error 1293 * message. 1294 * @param validation The validation 1295 * @param messageSupplier The function that generates the message for the 1296 * exception. 1297 * @return The value if the validation succeeds. 1298 * @throws ValidationException {@code arg} failed the validation. 1299 * @throws NullArgumentException {@code name}, {@code validation} or 1300 * {@code messageProvider} is {@null}. 1301 * @throws EmptyArgumentException {@code name} is the empty String. 1302 * 1303 * @since 0.25.11 1304 */ 1305 @API( status = STABLE, since = "0.25.11" ) 1306 public static final double requireValidDoubleArgument( final double arg, final String name, final DoublePredicate validation, final BiFunction<String,Double,String> messageSupplier ) 1307 { 1308 requireNotBlankArgument( name, "name" ); 1309 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1310 1311 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1312 { 1313 throw new ValidationException( messageSupplier.apply( name, Double.valueOf( arg ) ) ); 1314 } 1315 1316 //---* Done *---------------------------------------------------------- 1317 return arg; 1318 } // requireValidDoubleArgument() 1319 1320 /** 1321 * Applies the given validation on the given value, and if that fails, an 1322 * {@link ValidationException} 1323 * with a default message is thrown. 1324 * 1325 * @param arg The value to check. 1326 * @param name The name of the argument; this is used for the error 1327 * message. 1328 * @param validation The validation 1329 * @return The value if the validation succeeds. 1330 * @throws ValidationException {@code arg} failed the validation. 1331 * @throws NullArgumentException {@code name} or {@code validation} is 1332 * {@null}. 1333 * @throws EmptyArgumentException {@code name} is the empty String. 1334 * 1335 * @since 0.2.0 1336 */ 1337 @API( status = STABLE, since = "0.2.0" ) 1338 public static final int requireValidIntegerArgument( final int arg, final String name, final IntPredicate validation ) 1339 { 1340 requireNotBlankArgument( name, "name" ); 1341 1342 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1343 { 1344 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1345 } 1346 1347 //---* Done *---------------------------------------------------------- 1348 return arg; 1349 } // requireValidIntegerArgument() 1350 1351 /** 1352 * <p>{@summary Applies the given validation on the given value, and if 1353 * that fails, a 1354 * {@link ValidationException} 1355 * is thrown.} The message for the exception will be provided by the given 1356 * message supplier that takes the name of the argument as an 1357 * argument.</p> 1358 * 1359 * @param arg The value to check. 1360 * @param name The name of the argument; this is used for the error 1361 * message. 1362 * @param validation The validation 1363 * @param messageSupplier The function that generates the message for the 1364 * exception. 1365 * @return The value if the validation succeeds. 1366 * @throws ValidationException {@code arg} failed the validation. 1367 * @throws NullArgumentException {@code name}, {@code validation} or 1368 * {@code messageProvider} is {@null}. 1369 * @throws EmptyArgumentException {@code name} is the empty String. 1370 * 1371 * @since 0.2.0 1372 * @deprecated Consider the migration to 1373 * {@link #requireValidIntegerArgument(int,String,IntPredicate,BiFunction)} 1374 */ 1375 @API( status = DEPRECATED, since = "0.2.0" ) 1376 @Deprecated( since = "0.25.11", forRemoval = true ) 1377 public static final int requireValidIntegerArgument( final int arg, final String name, final IntPredicate validation, final UnaryOperator<String> messageSupplier ) 1378 { 1379 requireNotBlankArgument( name, "name" ); 1380 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1381 1382 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1383 { 1384 throw new ValidationException( messageSupplier.apply( name ) ); 1385 } 1386 1387 //---* Done *---------------------------------------------------------- 1388 return arg; 1389 } // requireValidIntegerArgument() 1390 1391 /** 1392 * <p>{@summary Applies the given validation on the given value, and if 1393 * that fails, a 1394 * {@link ValidationException} 1395 * is thrown.} The message for the exception will be provided by the given 1396 * {@code messageSupplier} that takes the {@code name} as the first 1397 * argument and the value ({@code arg}) as the second argument to compose 1398 * the message for the {@code ValidationException} in case the validation 1399 * failed.</p> 1400 * 1401 * @param arg The value to check. 1402 * @param name The name of the argument; this is used for the error 1403 * message. 1404 * @param validation The validation 1405 * @param messageSupplier The function that generates the message for the 1406 * exception. 1407 * @return The value if the validation succeeds. 1408 * @throws ValidationException {@code arg} failed the validation. 1409 * @throws NullArgumentException {@code name}, {@code validation} or 1410 * {@code messageProvider} is {@null}. 1411 * @throws EmptyArgumentException {@code name} is the empty String. 1412 * 1413 * @since 0.25.11 1414 */ 1415 @API( status = STABLE, since = "0.25.11" ) 1416 public static final int requireValidIntegerArgument( final int arg, final String name, final IntPredicate validation, final BiFunction<String,Integer,String> messageSupplier ) 1417 { 1418 requireNotBlankArgument( name, "name" ); 1419 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1420 1421 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1422 { 1423 throw new ValidationException( messageSupplier.apply( name, Integer.valueOf( arg ) ) ); 1424 } 1425 1426 //---* Done *---------------------------------------------------------- 1427 return arg; 1428 } // requireValidIntegerArgument() 1429 1430 /** 1431 * Applies the given validation on the given value, and if that fails, an 1432 * {@link ValidationException} 1433 * with a default message is thrown. 1434 * 1435 * @param arg The value to check. 1436 * @param name The name of the argument; this is used for the error 1437 * message. 1438 * @param validation The validation 1439 * @return The value if the validation succeeds. 1440 * @throws ValidationException {@code arg} failed the validation. 1441 * @throws NullArgumentException {@code name} or {@code validation} is 1442 * {@null}. 1443 * @throws EmptyArgumentException {@code name} is the empty String. 1444 * 1445 * @since 0.2.0 1446 */ 1447 @API( status = STABLE, since = "0.2.0" ) 1448 public static final long requireValidLongArgument( final long arg, final String name, final LongPredicate validation ) 1449 { 1450 requireNotBlankArgument( name, "name" ); 1451 1452 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1453 { 1454 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1455 } 1456 1457 //---* Done *---------------------------------------------------------- 1458 return arg; 1459 } // requireValidLongArgument() 1460 1461 /** 1462 * <p>{@summary Applies the given validation on the given value, and if 1463 * that fails, a 1464 * {@link ValidationException} 1465 * is thrown.} The message for the exception will be provided by the given 1466 * message supplier that takes the name of the argument as an 1467 * argument.</p> 1468 * 1469 * @param arg The value to check. 1470 * @param name The name of the argument; this is used for the error 1471 * message. 1472 * @param validation The validation 1473 * @param messageSupplier The function that generates the message for the 1474 * exception. 1475 * @return The value if the validation succeeds. 1476 * @throws ValidationException {@code arg} failed the validation. 1477 * @throws NullArgumentException {@code name}, {@code validation} or 1478 * {@code messageProvider} is {@null}. 1479 * @throws EmptyArgumentException {@code name} is the empty String. 1480 * 1481 * @since 0.2.0 1482 * @deprecated Consider the migration to 1483 * {@link #requireValidLongArgument(long,String,LongPredicate,BiFunction)}. 1484 */ 1485 @API( status = DEPRECATED, since = "0.2.0" ) 1486 @Deprecated( since = "0.25.11" ) 1487 public static final long requireValidLongArgument( final long arg, final String name, final LongPredicate validation, final UnaryOperator<String> messageSupplier ) 1488 { 1489 requireNotBlankArgument( name, "name" ); 1490 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1491 1492 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1493 { 1494 throw new ValidationException( messageSupplier.apply( name ) ); 1495 } 1496 1497 //---* Done *---------------------------------------------------------- 1498 return arg; 1499 } // requireValidLongArgument() 1500 1501 /** 1502 * <p>{@summary Applies the given validation on the given value, and if 1503 * that fails, a 1504 * {@link ValidationException} 1505 * is thrown.} The message for the exception will be provided by the given 1506 * {@code messageSupplier} that takes the {@code name} as the first 1507 * argument and the value ({@code arg}) as the second argument to compose 1508 * the message for the {@code ValidationException} in case the validation 1509 * failed.</p> 1510 * 1511 * @param arg The value to check. 1512 * @param name The name of the argument; this is used for the error 1513 * message. 1514 * @param validation The validation 1515 * @param messageSupplier The function that generates the message for the 1516 * exception. 1517 * @return The value if the validation succeeds. 1518 * @throws ValidationException {@code arg} failed the validation. 1519 * @throws NullArgumentException {@code name}, {@code validation} or 1520 * {@code messageProvider} is {@null}. 1521 * @throws EmptyArgumentException {@code name} is the empty String. 1522 * 1523 * @since 0.25.11 1524 */ 1525 @API( status = STABLE, since = "0.25.11" ) 1526 public static final long requireValidLongArgument( final long arg, final String name, final LongPredicate validation, final BiFunction<String,Long,String> messageSupplier ) 1527 { 1528 requireNotBlankArgument( name, "name" ); 1529 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1530 1531 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1532 { 1533 throw new ValidationException( messageSupplier.apply( name, Long.valueOf( arg ) ) ); 1534 } 1535 1536 //---* Done *---------------------------------------------------------- 1537 return arg; 1538 } // requireValidLongArgument() 1539 1540 /** 1541 * <p>{@summary Applies the given validation on the given value (that must 1542 * not be {@null}), and if that fails, an 1543 * {@link ValidationException} 1544 * with a default message is thrown.}</p> 1545 * <p>If the value is {@null}, the validation is never triggered.</p> 1546 * 1547 * @param <T> The type of the value to check. 1548 * @param arg The value to check. 1549 * @param name The name of the argument; this is used for the error 1550 * message. 1551 * @param validation The validation 1552 * @return The value if the validation succeeds. 1553 * @throws ValidationException {@code a} failed the validation. 1554 * @throws NullArgumentException {@code arg}, {@code name} or 1555 * {@code validation} is {@null}. 1556 * @throws EmptyArgumentException {@code name} is the empty String. 1557 * 1558 * @since 0.1.0 1559 */ 1560 @API( status = STABLE, since = "0.1.0" ) 1561 public static final <T> T requireValidNonNullArgument( final T arg, final String name, final Predicate<? super T> validation ) 1562 { 1563 requireNotBlankArgument( name, "name" ); 1564 1565 if( !requireNonNullArgument( validation, "validation" ).test( requireNonNullArgument( arg, "name" ) ) ) 1566 { 1567 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1568 } 1569 1570 //---* Done *---------------------------------------------------------- 1571 return arg; 1572 } // requireValidNonNullArgument() 1573 1574 /** 1575 * <p>{@summary Applies the given validation on the given value (that must 1576 * not be {@null}), and if that fails, a 1577 * {@link ValidationException} 1578 * is thrown.} The message for the exception will be provided by the given 1579 * message supplier that takes the name of the argument as an 1580 * argument.</p> 1581 * 1582 * @param <T> The type of the value to check. 1583 * @param arg The value to check. 1584 * @param name The name of the argument; this is used for the error 1585 * message. 1586 * @param validation The validation 1587 * @param messageSupplier The function that generates the message for the 1588 * exception. 1589 * @return The value if the validation succeeds. 1590 * @throws ValidationException {@code arg} failed the validation. 1591 * @throws NullArgumentException {@code arg}, {@code name}, 1592 * {@code validation} or {@code messageProvider} is {@null}. 1593 * @throws EmptyArgumentException {@code name} is the empty String. 1594 * 1595 * @since 0.1.0 1596 * @deprecated Consider the migration to 1597 * {@link #requireValidNonNullArgument(Object,String,Predicate,BiFunction)} 1598 */ 1599 @API( status = DEPRECATED, since = "0.1.0" ) 1600 @Deprecated( since = "0.25.11", forRemoval = true ) 1601 public static final <T> T requireValidNonNullArgument( final T arg, final String name, final Predicate<? super T> validation, final UnaryOperator<String> messageSupplier ) 1602 { 1603 requireNotBlankArgument( name, "name" ); 1604 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1605 1606 if( !requireNonNullArgument( validation, "validation" ).test( requireNonNullArgument( arg, "name" ) ) ) 1607 { 1608 throw new ValidationException( messageSupplier.apply( name ) ); 1609 } 1610 1611 //---* Done *---------------------------------------------------------- 1612 return arg; 1613 } // requireValidNonNullArgument() 1614 1615 /** 1616 * <p>{@summary Applies the given validation on the given value (that must 1617 * not be {@null}), and if that fails, a 1618 * {@link ValidationException} 1619 * is thrown.} The message for the exception will be provided by the given 1620 * {@code messageSupplier} that takes the {@code name} as the first 1621 * argument and the value ({@code arg}) as the second argument to compose 1622 * the message for the {@code ValidationException} in case the validation 1623 * failed.</p> 1624 * 1625 * @param <T> The type of the value to check. 1626 * @param arg The value to check. 1627 * @param name The name of the argument; this is used for the error 1628 * message. 1629 * @param validation The validation 1630 * @param messageSupplier The function that generates the message for the 1631 * exception. 1632 * @return The value if the validation succeeds. 1633 * @throws ValidationException {@code arg} failed the validation. 1634 * @throws NullArgumentException {@code arg}, {@code name}, 1635 * {@code validation} or {@code messageProvider} is {@null}. 1636 * @throws EmptyArgumentException {@code name} is the empty String. 1637 * 1638 * @since 0.25.11 1639 */ 1640 @API( status = STABLE, since = "0.25.11" ) 1641 public static final <T> T requireValidNonNullArgument( final T arg, final String name, final Predicate<? super T> validation, final BiFunction<String,T,String> messageSupplier ) 1642 { 1643 requireNotBlankArgument( name, "name" ); 1644 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1645 1646 if( !requireNonNullArgument( validation, "validation" ).test( requireNonNullArgument( arg, "name" ) ) ) 1647 { 1648 throw new ValidationException( messageSupplier.apply( name, arg ) ); 1649 } 1650 1651 //---* Done *---------------------------------------------------------- 1652 return arg; 1653 } // requireValidNonNullArgument() 1654 1655 /** 1656 * <p>{@summary Converts the given argument {@code object} into a 1657 * {@link String}, 1658 * usually by calling its 1659 * {@link Object#toString() toString()} 1660 * method.} If the value of the argument is {@null}, the text 1661 * "{@link org.tquadrat.foundation.lang.CommonConstants#NULL_STRING null}" 1662 * will be returned instead. Arrays will be converted to a String through 1663 * calling the respective {@code toString()} method from 1664 * {@link java.util.Arrays} 1665 * (this distinguishes this implementation from 1666 * {link java.util.Objects#toString(Object, String) java.util.Objects.toString()}). 1667 * Values of type 1668 * {@link java.util.Date} or 1669 * {@link java.util.Calendar} 1670 * will be translated based on the default locale - whatever that is. 1671 * 1672 * @param object The object; may be {@null}. 1673 * @return The object's string representation. 1674 * 1675 * @see java.util.Arrays#toString(boolean[]) 1676 * @see java.util.Arrays#toString(byte[]) 1677 * @see java.util.Arrays#toString(char[]) 1678 * @see java.util.Arrays#toString(double[]) 1679 * @see java.util.Arrays#toString(float[]) 1680 * @see java.util.Arrays#toString(int[]) 1681 * @see java.util.Arrays#toString(long[]) 1682 * @see java.util.Arrays#toString(Object[]) 1683 * @see java.util.Arrays#toString(short[]) 1684 * @see java.util.Arrays#deepToString(Object[]) 1685 * @see java.util.Locale#getDefault() 1686 * @see org.tquadrat.foundation.lang.CommonConstants#NULL_STRING 1687 * 1688 * @since 0.0.5 1689 */ 1690 @API( status = STABLE, since = "0.0.5" ) 1691 public static final String toString( final Object object ) 1692 { 1693 return toString( object, NULL_STRING ); 1694 } // toString() 1695 1696 /** 1697 * <p>{@summary Converts the given argument {@code object} into a 1698 * {@link String}, 1699 * usually by calling its 1700 * {@link Object#toString() toString()} 1701 * method.} If the value of the argument is {@null}, the text 1702 * provided as the {@code nullDefault} argument will be returned 1703 * instead.</p> 1704 * <p>Arrays will be converted to a string through calling the respective 1705 * {@code toString()} method from 1706 * {@link java.util.Arrays} 1707 * (this distinguishes this implementation from 1708 * {link java.util.Objects#toString(Object,String) java.util.Objects.toString(Object,String)}).</p> 1709 * <p>Values of type 1710 * {@link java.util.Date} or 1711 * {@link java.util.Calendar} 1712 * will be translated based on the 1713 * {@link java.util.Locale#getDefault() default locale} 1714 * – whatever that is.</p> 1715 * 1716 * @param object The object; may be {@null}. 1717 * @param nullDefault The text that should be returned if {@code object} 1718 * is {@null}. 1719 * @return The object's string representation. 1720 * 1721 * @see java.util.Arrays#toString(boolean[]) 1722 * @see java.util.Arrays#toString(byte[]) 1723 * @see java.util.Arrays#toString(char[]) 1724 * @see java.util.Arrays#toString(double[]) 1725 * @see java.util.Arrays#toString(float[]) 1726 * @see java.util.Arrays#toString(int[]) 1727 * @see java.util.Arrays#toString(long[]) 1728 * @see java.util.Arrays#toString(Object[]) 1729 * @see java.util.Arrays#toString(short[]) 1730 * @see java.util.Arrays#deepToString(Object[]) 1731 * @see java.util.Locale#getDefault() 1732 * 1733 * @since 0.0.5 1734 */ 1735 @SuppressWarnings( {"IfStatementWithTooManyBranches", "ChainOfInstanceofChecks", "OverlyComplexMethod"} ) 1736 @API( status = STABLE, since = "0.0.5" ) 1737 public static final String toString( final Object object, final String nullDefault ) 1738 { 1739 var retValue = requireNonNullArgument( nullDefault, "nullDefault" ); 1740 if( nonNull( object ) ) 1741 { 1742 final var objectClass = object.getClass(); 1743 if( objectClass.isArray() ) 1744 { 1745 if( objectClass == byte [].class ) 1746 { 1747 retValue = Arrays.toString( (byte []) object ); 1748 } 1749 else if( objectClass == short [].class ) 1750 { 1751 retValue = Arrays.toString( (short []) object ); 1752 } 1753 else if( objectClass == int [].class ) 1754 { 1755 retValue = Arrays.toString( (int []) object ); 1756 } 1757 else if( objectClass == long [].class ) 1758 { 1759 retValue = Arrays.toString( (long []) object ); 1760 } 1761 else if( objectClass == char [].class ) 1762 { 1763 retValue = Arrays.toString( (char []) object ); 1764 } 1765 else if( objectClass == float [].class ) 1766 { 1767 retValue = Arrays.toString( (float []) object ); 1768 } 1769 else if( objectClass == double [].class ) 1770 { 1771 retValue = Arrays.toString( (double []) object ); 1772 } 1773 else if( objectClass == boolean [].class ) 1774 { 1775 retValue = Arrays.toString( (boolean []) object ); 1776 } 1777 else 1778 { 1779 retValue = deepToString( (Object []) object ); 1780 } 1781 } 1782 else 1783 { 1784 retValue = object.toString(); 1785 } 1786 } 1787 1788 //---* Done *---------------------------------------------------------- 1789 return retValue; 1790 } // toString() 1791 1792 /** 1793 * <p>{@summary Converts the given argument into a 1794 * {@link String} 1795 * using the given instance of 1796 * {@link Stringer}.} 1797 * If the value of the argument is {@null}, the text 1798 * provided as the {@code nullDefault} argument will be returned 1799 * instead.</p> 1800 * 1801 * @param <T> The type of the object. 1802 * @param value The object; may be {@null}. 1803 * @param stringer The method that is used to convert the given object 1804 * to a String. 1805 * @param nullDefault The text that should be returned if {@code object} 1806 * is {@null}. 1807 * @return The object's string representation. 1808 * 1809 * @see Stringer 1810 * 1811 * @since 0.0.5 1812 */ 1813 @API( status = STABLE, since = "0.0.5" ) 1814 public static final <T> String toString( final T value, final Stringer<? super T> stringer, final String nullDefault ) 1815 { 1816 requireNonNullArgument( nullDefault, "nullDefault" ); 1817 1818 final var retValue = nonNull( value ) ? requireNonNullArgument( stringer, "stringer" ).toString( value ) : nullDefault; 1819 1820 //---* Done *---------------------------------------------------------- 1821 return retValue; 1822 } // toString() 1823} 1824// class Objects 1825 1826/* 1827 * End of File 1828 */