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