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 org.apiguardian.api.API; 022import org.tquadrat.foundation.annotation.ClassVersion; 023import org.tquadrat.foundation.annotation.UtilityClass; 024import org.tquadrat.foundation.exception.BlankArgumentException; 025import org.tquadrat.foundation.exception.EmptyArgumentException; 026import org.tquadrat.foundation.exception.NullArgumentException; 027import org.tquadrat.foundation.exception.PrivateConstructorForStaticClassCalledError; 028import org.tquadrat.foundation.exception.ValidationException; 029 030import java.lang.reflect.Array; 031import java.util.Arrays; 032import java.util.Collection; 033import java.util.Collections; 034import java.util.Comparator; 035import java.util.Enumeration; 036import java.util.List; 037import java.util.Map; 038import java.util.Optional; 039import java.util.function.DoublePredicate; 040import java.util.function.Function; 041import java.util.function.IntPredicate; 042import java.util.function.LongPredicate; 043import java.util.function.Predicate; 044import java.util.function.Supplier; 045import java.util.function.UnaryOperator; 046 047import static java.lang.Integer.signum; 048import static java.util.Arrays.deepToString; 049import static org.apiguardian.api.API.Status.STABLE; 050import static org.tquadrat.foundation.lang.CommonConstants.NULL_STRING; 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 1163 2026-03-20 15:28:33Z tquadrat $ 073 * @since 0.0.1 074 * 075 * @UMLGraph.link 076 */ 077@UtilityClass 078@SuppressWarnings( {"ClassWithTooManyMethods", "UseOfObsoleteDateTimeApi", "OverlyComplexClass"} ) 079@ClassVersion( sourceVersion = "$Id: Objects.java 1163 2026-03-20 15:28:33Z 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 * <div class="source-container"><pre>… 202 * if( !<<i>condition</i>> ) 203 * { 204 * throw new <<i>WhatEver</i>>Exception( <<i>WhatEverMessage</i>> ); 205 * } 206 * …</pre></div> 207 * <p>Code using this method may be easier to read than the {@code if} 208 * statement above:</p> 209 * <div class="source-container"><pre>… 210 * checkState( <<i>condition</i>>, () -> new <<i>WhatEver</i>>Exception( <<i>WhatEverMessage</i>> ) ); 211 * …</pre></div> 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 * <div class="source-container"><pre>Optional.ofNullable( value ).orElseGet( supplier );</pre></div> 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 * <div class="source-container"><pre>Optional.ofNullable( value ).orElse( replacement );</pre></div> 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 @SuppressWarnings( "OverlyComplexMethod" ) 829 @API( status = STABLE, since = "0.1.0" ) 830 public static final <T extends CharSequence> T requireNotBlankArgument( final T arg, final String name ) 831 { 832 if( isNull( name ) ) throw new NullArgumentException( "name" ); 833 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 834 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 835 836 switch( arg ) 837 { 838 case null -> throw new NullArgumentException( name ); 839 case final String string -> 840 { 841 if( string.isEmpty() ) throw new EmptyArgumentException( name ); 842 if( string.isBlank() ) throw new BlankArgumentException( name ); 843 } 844 case final CharSequence charSequence -> 845 { 846 if( charSequence.isEmpty() ) throw new EmptyArgumentException( name ); 847 if( charSequence.toString().isBlank() ) throw new BlankArgumentException( name ); 848 } 849 } 850 851 //---* Done *---------------------------------------------------------- 852 return arg; 853 } // requireNotBlankArgument() 854 855 /** 856 * <p>{@summary Checks if the given argument {@code arg} is {@code null} or 857 * empty and throws a 858 * {@link NullArgumentException} 859 * if it is {@code null}, or an 860 * {@link EmptyArgumentException} 861 * if it is empty.}</p> 862 * <p>Strings, arrays, instances of 863 * {@link java.util.Collection} and 864 * {@link java.util.Map} 865 * as well as instances of 866 * {@link java.lang.StringBuilder}, 867 * {@link java.lang.StringBuffer}, 868 * and 869 * {@link java.lang.CharSequence} 870 * will be checked on being empty.</p> 871 * <p>For an instance of 872 * {@link java.util.Optional}, 873 * the presence of a value is checked in order to determine whether the 874 * {@link Optional} is empty or not.</p> 875 * <p>Because the interface 876 * {@link java.util.Enumeration} 877 * does not provide an API for the check on emptiness 878 * ({@link java.util.Enumeration#hasMoreElements() hasMoreElements()} 879 * will return {@code false} after all elements have been taken from 880 * the {@code Enumeration} instance), the result for arguments of this 881 * type has to be taken with caution.</p> 882 * <p>For instances of 883 * {@link java.util.stream.Stream}, 884 * this method will only check for {@code null} (like 885 * {@link #requireNonNullArgument(Object,String)}. 886 * This is because any operation on the stream itself would render it 887 * unusable for later processing.</p> 888 * <p>In case the argument is of type 889 * {@link Optional}, 890 * this method behaves different from 891 * {@link #requireNotEmptyArgument(Optional,String)}; 892 * this one will return the {@code Optional} instance, while the other 893 * method will return the contents of the {@code Optional}.</p> 894 * <p>This method will not work properly for instances of 895 * {@link java.util.StringJoiner}, because its method 896 * {@link java.util.StringJoiner#length() length()} 897 * will not return 0 when a prefix, suffix, or an 898 * "{@linkplain java.util.StringJoiner#setEmptyValue(CharSequence) empty value}" 899 * was provided.</p> 900 * 901 * @param <T> The type of the argument to check. 902 * @param arg The argument to check; may be {@code null}. 903 * @param name The name of the argument; this is used for the error 904 * message. 905 * @return The argument if it is not {@code null} or empty. 906 * @throws NullArgumentException {@code arg} is {@code null}. 907 * @throws EmptyArgumentException {@code arg} is empty. 908 * 909 * @since 0.0.5 910 */ 911 @SuppressWarnings( "OverlyComplexMethod" ) 912 @API( status = STABLE, since = "0.0.5" ) 913 public static final <T> T requireNotEmptyArgument( final T arg, final String name ) 914 { 915 if( isNull( name ) ) throw new NullArgumentException( "name" ); 916 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 917 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 918 919 switch( arg ) 920 { 921 /* 922 * When using guarding expressions, the code would not get better 923 * to read and to understand, as the positive cases will be handled 924 * all by the default case. 925 */ 926 case null -> throw new NullArgumentException( name ); 927 case final CharSequence charSequence -> 928 { 929 if( charSequence.isEmpty() ) throw new EmptyArgumentException( name ); 930 } 931 case final Collection<?> collection -> 932 { 933 if( collection.isEmpty() ) throw new EmptyArgumentException( name ); 934 } 935 case final Map<?,?> map -> 936 { 937 if( map.isEmpty() ) throw new EmptyArgumentException( name ); 938 } 939 case final Enumeration<?> enumeration -> 940 { 941 /* 942 * The funny thing with an Enumeration is that it could have 943 * been not empty in the beginning, but it may be empty 944 * (= having no more elements) now. 945 * The good thing is that Enumeration.hasMoreElements() will 946 * not change the state of the Enumeration - at least it should 947 * not do so. 948 */ 949 if( !enumeration.hasMoreElements() ) throw new EmptyArgumentException( name ); 950 } 951 case final Optional<?> optional -> 952 { 953 /* 954 * This is different from the behaviour of 955 * requireNotEmptyArgument(Optional,String) as the Optional 956 * will be returned here. 957 */ 958 if( optional.isEmpty() ) throw new EmptyArgumentException( name ); 959 } 960 default -> 961 { 962 if( arg.getClass().isArray() ) 963 { 964 if( Array.getLength( arg ) == 0 ) throw new EmptyArgumentException( name ); 965 } 966 else 967 { 968 /* 969 * Other data types are not further processed; in 970 * particular, instances of Stream cannot be checked on 971 * being empty. This is because any operation on the Stream 972 * itself will change its state and may make the Stream 973 * unusable. 974 */ 975 } 976 } 977 } 978 979 //---* Done *---------------------------------------------------------- 980 return arg; 981 } // requireNotEmptyArgument() 982 983 /** 984 * <p>{@summary Checks if the given argument {@code optional} of type 985 * {@link Optional} 986 * is {@code null} or 987 * {@linkplain Optional#empty() empty} 988 * and throws a 989 * {@link NullArgumentException} 990 * if it is {@code null}, or a 991 * {@link EmptyArgumentException} 992 * if it is empty.}</p> 993 * <p>Otherwise it returns the value of the {@code Optional}.</p> 994 * <p>This is different from the behaviour of 995 * {@link #requireNotEmptyArgument(Object,String)} 996 * with an instance of {@code Optional} as the argument to test.</p> 997 * 998 * @param <T> The type of the given {@code Optional} to check. 999 * @param optional The argument to check; can be {@code null}. 1000 * @param name The name of the argument; this is used for the error 1001 * message. 1002 * @return The value of the argument if {@code optional} is not 1003 * {@code null} 1004 * and not 1005 * {@linkplain Optional#empty() empty}. This could be the empty 1006 * string! 1007 * @throws NullArgumentException {@code optional} is {@code null}. 1008 * @throws EmptyArgumentException {@code optional} is empty. 1009 * 1010 * @since 0.0.5 1011 */ 1012 @API( status = STABLE, since = "0.0.5" ) 1013 public static final <T> T requireNotEmptyArgument( @SuppressWarnings( "OptionalUsedAsFieldOrParameterType" ) final Optional<T> optional, final String name ) 1014 { 1015 if( isNull( name ) ) throw new NullArgumentException( "name" ); 1016 if( name.isEmpty() ) throw new EmptyArgumentException( "name" ); 1017 if( name.isBlank() ) throw new BlankArgumentException( "name" ); 1018 1019 //---* Check for null *------------------------------------------------ 1020 if( isNull( optional ) ) throw new NullArgumentException( name ); 1021 final var retValue = optional.orElseThrow( () -> new EmptyArgumentException( name ) ); 1022 1023 //---* Done *---------------------------------------------------------- 1024 return retValue; 1025 } // requireNotEmptyArgument() 1026 1027 /** 1028 * <p>{@summary Returns the first argument if it is not {@code null}, 1029 * otherwise it returns the non-{@code null} second argument.}</p> 1030 * <p>This implementation behaves different from that in 1031 * {@link java.util.Objects#requireNonNullElse(Object,Object) java.util.Objects.requireNonNullElse(Object,Object)} 1032 * as it will always check that the default is not {@code null}.</p> 1033 * 1034 * @param <T> The type of the references. 1035 * @param obj An object reference. 1036 * @param defaultObj Another object reference to be returned if the 1037 * first argument is {@code null}. 1038 * @return The first argument if it is not {@code null}, otherwise the 1039 * second argument if it is not {@code null}. 1040 * @throws NullArgumentException The {@code defaultObj} is {@code null}. 1041 * 1042 * @see java.util.Objects#requireNonNullElse(Object, Object) 1043 * 1044 * @since 0.0.5 1045 */ 1046 @API( status = STABLE, since = "0.0.5" ) 1047 public static final <T> T requireNonNullElse( final T obj, final T defaultObj ) throws NullArgumentException 1048 { 1049 return java.util.Objects.requireNonNullElse( obj, requireNonNullArgument( defaultObj, "defaultObj" ) ); 1050 } // requireNonNullElse() 1051 1052 /** 1053 * <p>{@summary Returns the first argument if it is not {@code null}, 1054 * otherwise it returns the non-{@code null} value returned by 1055 * {@link Supplier#get() supplier.get()}.}</p> 1056 * <p>This implementation behaves different from that in 1057 * {@link java.util.Objects#requireNonNullElseGet(Object,Supplier) java.util.Objects.requireNonNullElseGet(Object,Supplier)} 1058 * as it will always check that the supplier is not {@code null}.</p> 1059 * 1060 * @note Although the provided {@code Supplier} may not be {@code null}, 1061 * it may <i>return</i> {@code null}. 1062 * 1063 * @param <T> The type of the reference. 1064 * @param obj An object reference. 1065 * @param supplier The supplier of a non-{@code null} object of type 1066 * {code T} to return if the first argument is {@code null}. 1067 * @return The first argument if it is not {@code null}, otherwise the 1068 * value returned by a call to {@code supplier.get()} if it is not 1069 * {@code null}. 1070 * @throws NullArgumentException The {@code supplier} is {@code null}. 1071 * @throws NullPointerException {@code obj} is {@code null} and the 1072 * return value of {@code supplier.get()} value is {@code null}, too. 1073 * 1074 * @since 0.0.5 1075 */ 1076 @SuppressWarnings( "ProhibitedExceptionDeclared" ) 1077 @API( status = STABLE, since = "0.0.5" ) 1078 public static final <T> T requireNonNullElseGet( final T obj, final Supplier<? extends T> supplier ) throws NullArgumentException, NullPointerException 1079 { 1080 return java.util.Objects.requireNonNullElseGet( obj, requireNonNullArgument( supplier, "supplier" ) ); 1081 } // requireNonNullElseGet() 1082 1083 /** 1084 * <p>{@summary Applies the given validation on the given value, and if 1085 * that fails, an 1086 * {@link ValidationException} 1087 * with a default message is thrown.} The validation is also responsible 1088 * for the {@code null}-check; that means, the method 1089 * {@link Predicate#test(Object) test()} 1090 * of the validation may be called with {@code null} as the argument.</p> 1091 * 1092 * @param <T> The type of the value to check. 1093 * @param arg The value to check; can be {@code null}. 1094 * @param name The name of the argument; this is used for the error 1095 * message. 1096 * @param validation The validation 1097 * @return The value if the validation succeeds. 1098 * @throws ValidationException {@code arg} failed the validation. 1099 * @throws NullArgumentException {@code name} or {@code validation} is 1100 * {@code null}. 1101 * @throws EmptyArgumentException {@code name} is the empty String. 1102 * 1103 * @since 0.1.0 1104 */ 1105 @API( status = STABLE, since = "0.1.0" ) 1106 public static final <T> T requireValidArgument( final T arg, final String name, final Predicate<? super T> validation ) 1107 { 1108 requireNotBlankArgument( name, "name" ); 1109 1110 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1111 { 1112 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1113 } 1114 1115 //---* Done *---------------------------------------------------------- 1116 return arg; 1117 } // requireValidArgument() 1118 1119 /** 1120 * <p>{@summary Applies the given validation on the given value, and if 1121 * that fails, a 1122 * {@link ValidationException} 1123 * is thrown.} The message for the exception will be provided by the given 1124 * message supplier that takes the name of the argument as an 1125 * argument.</p> 1126 * <p>The validation is also responsible for the {@code null}-check; that 1127 * means, the method 1128 * {@link Predicate#test(Object) test()} 1129 * of the validation may be called with {@code null} as the argument.</p> 1130 * 1131 * @param <T> The type of the value to check. 1132 * @param arg The value to check; can be {@code null}. 1133 * @param name The name of the argument; this is used for the error 1134 * message. 1135 * @param validation The validation 1136 * @param messageSupplier The function that generates the message for the 1137 * exception. 1138 * @return The value if the validation succeeds. 1139 * @throws ValidationException {@code arg} failed the validation. 1140 * @throws NullArgumentException {@code name}, {@code validation} or 1141 * {@code messageProvider} is {@code null}. 1142 * @throws EmptyArgumentException {@code name} is the empty String. 1143 * 1144 * @since 0.1.0 1145 */ 1146 @API( status = STABLE, since = "0.1.0" ) 1147 public static final <T> T requireValidArgument( final T arg, final String name, final Predicate<? super T> validation, final UnaryOperator<String> messageSupplier ) 1148 { 1149 requireNotBlankArgument( name, "name" ); 1150 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1151 1152 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1153 { 1154 throw new ValidationException( messageSupplier.apply( name ) ); 1155 } 1156 1157 //---* Done *---------------------------------------------------------- 1158 return arg; 1159 } // requireValidArgument() 1160 1161 /** 1162 * Applies the given validation on the given value, and if that fails, an 1163 * {@link ValidationException} 1164 * with a default message is thrown. 1165 * 1166 * @param arg The value to check. 1167 * @param name The name of the argument; this is used for the error 1168 * message. 1169 * @param validation The validation 1170 * @return The value if the validation succeeds. 1171 * @throws ValidationException {@code arg} failed the validation. 1172 * @throws NullArgumentException {@code name} or {@code validation} is 1173 * {@code null}. 1174 * @throws EmptyArgumentException {@code name} is the empty String. 1175 * 1176 * @since 0.2.0 1177 */ 1178 @API( status = STABLE, since = "0.2.0" ) 1179 public static final double requireValidDoubleArgument( final double arg, final String name, final DoublePredicate validation ) 1180 { 1181 requireNotBlankArgument( name, "name" ); 1182 1183 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1184 { 1185 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1186 } 1187 1188 //---* Done *---------------------------------------------------------- 1189 return arg; 1190 } // requireValidDoubleArgument() 1191 1192 /** 1193 * <p>{@summary Applies the given validation on the given value, and if 1194 * that fails, a 1195 * {@link ValidationException} 1196 * is thrown.} The message for the exception will be provided by the given 1197 * message supplier that takes the name of the argument as an 1198 * argument.</p> 1199 * 1200 * @param arg The value to check. 1201 * @param name The name of the argument; this is used for the error 1202 * message. 1203 * @param validation The validation 1204 * @param messageSupplier The function that generates the message for the 1205 * exception. 1206 * @return The value if the validation succeeds. 1207 * @throws ValidationException {@code arg} failed the validation. 1208 * @throws NullArgumentException {@code name}, {@code validation} or 1209 * {@code messageProvider} is {@code null}. 1210 * @throws EmptyArgumentException {@code name} is the empty String. 1211 * 1212 * @since 0.2.0 1213 */ 1214 @API( status = STABLE, since = "0.2.0" ) 1215 public static final double requireValidDoubleArgument( final double arg, final String name, final DoublePredicate validation, final UnaryOperator<String> messageSupplier ) 1216 { 1217 requireNotBlankArgument( name, "name" ); 1218 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1219 1220 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1221 { 1222 throw new ValidationException( messageSupplier.apply( name ) ); 1223 } 1224 1225 //---* Done *---------------------------------------------------------- 1226 return arg; 1227 } // requireValidDoubleArgument() 1228 1229 /** 1230 * Applies the given validation on the given value, and if that fails, an 1231 * {@link ValidationException} 1232 * with a default message is thrown. 1233 * 1234 * @param arg The value to check. 1235 * @param name The name of the argument; this is used for the error 1236 * message. 1237 * @param validation The validation 1238 * @return The value if the validation succeeds. 1239 * @throws ValidationException {@code arg} failed the validation. 1240 * @throws NullArgumentException {@code name} or {@code validation} is 1241 * {@code null}. 1242 * @throws EmptyArgumentException {@code name} is the empty String. 1243 * 1244 * @since 0.2.0 1245 */ 1246 @API( status = STABLE, since = "0.2.0" ) 1247 public static final int requireValidIntegerArgument( final int arg, final String name, final IntPredicate validation ) 1248 { 1249 requireNotBlankArgument( name, "name" ); 1250 1251 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1252 { 1253 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1254 } 1255 1256 //---* Done *---------------------------------------------------------- 1257 return arg; 1258 } // requireValidIntegerArgument() 1259 1260 /** 1261 * <p>{@summary Applies the given validation on the given value, and if 1262 * that fails, a 1263 * {@link ValidationException} 1264 * is thrown.} The message for the exception will be provided by the given 1265 * message supplier that takes the name of the argument as an 1266 * argument.</p> 1267 * 1268 * @param arg The value to check. 1269 * @param name The name of the argument; this is used for the error 1270 * message. 1271 * @param validation The validation 1272 * @param messageSupplier The function that generates the message for the 1273 * exception. 1274 * @return The value if the validation succeeds. 1275 * @throws ValidationException {@code arg} failed the validation. 1276 * @throws NullArgumentException {@code name}, {@code validation} or 1277 * {@code messageProvider} is {@code null}. 1278 * @throws EmptyArgumentException {@code name} is the empty String. 1279 * 1280 * @since 0.2.0 1281 */ 1282 @API( status = STABLE, since = "0.2.0" ) 1283 public static final int requireValidIntegerArgument( final int arg, final String name, final IntPredicate validation, final UnaryOperator<String> messageSupplier ) 1284 { 1285 requireNotBlankArgument( name, "name" ); 1286 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1287 1288 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1289 { 1290 throw new ValidationException( messageSupplier.apply( name ) ); 1291 } 1292 1293 //---* Done *---------------------------------------------------------- 1294 return arg; 1295 } // requireValidIntegerArgument() 1296 1297 /** 1298 * Applies the given validation on the given value, and if that fails, an 1299 * {@link ValidationException} 1300 * with a default message is thrown. 1301 * 1302 * @param arg The value to check. 1303 * @param name The name of the argument; this is used for the error 1304 * message. 1305 * @param validation The validation 1306 * @return The value if the validation succeeds. 1307 * @throws ValidationException {@code arg} failed the validation. 1308 * @throws NullArgumentException {@code name} or {@code validation} is 1309 * {@code null}. 1310 * @throws EmptyArgumentException {@code name} is the empty String. 1311 * 1312 * @since 0.2.0 1313 */ 1314 @API( status = STABLE, since = "0.2.0" ) 1315 public static final long requireValidLongArgument( final long arg, final String name, final LongPredicate validation ) 1316 { 1317 requireNotBlankArgument( name, "name" ); 1318 1319 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1320 { 1321 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1322 } 1323 1324 //---* Done *---------------------------------------------------------- 1325 return arg; 1326 } // requireValidLongArgument() 1327 1328 /** 1329 * <p>{@summary Applies the given validation on the given value, and if 1330 * that fails, a 1331 * {@link ValidationException} 1332 * is thrown.} The message for the exception will be provided by the given 1333 * message supplier that takes the name of the argument as an 1334 * argument.</p> 1335 * 1336 * @param arg The value to check. 1337 * @param name The name of the argument; this is used for the error 1338 * message. 1339 * @param validation The validation 1340 * @param messageSupplier The function that generates the message for the 1341 * exception. 1342 * @return The value if the validation succeeds. 1343 * @throws ValidationException {@code arg} failed the validation. 1344 * @throws NullArgumentException {@code name}, {@code validation} or 1345 * {@code messageProvider} is {@code null}. 1346 * @throws EmptyArgumentException {@code name} is the empty String. 1347 * 1348 * @since 0.2.0 1349 */ 1350 @API( status = STABLE, since = "0.2.0" ) 1351 public static final long requireValidLongArgument( final long arg, final String name, final LongPredicate validation, final UnaryOperator<String> messageSupplier ) 1352 { 1353 requireNotBlankArgument( name, "name" ); 1354 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1355 1356 if( !requireNonNullArgument( validation, "validation" ).test( arg ) ) 1357 { 1358 throw new ValidationException( messageSupplier.apply( name ) ); 1359 } 1360 1361 //---* Done *---------------------------------------------------------- 1362 return arg; 1363 } // requireValidLongArgument() 1364 1365 /** 1366 * <p>{@summary Applies the given validation on the given value (that must 1367 * not be {@code null}), and if that fails, an 1368 * {@link ValidationException} 1369 * with a default message is thrown.}</p> 1370 * <p>If the value is {@code null}, the validation is never triggered.</p> 1371 * 1372 * @param <T> The type of the value to check. 1373 * @param arg The value to check. 1374 * @param name The name of the argument; this is used for the error 1375 * message. 1376 * @param validation The validation 1377 * @return The value if the validation succeeds. 1378 * @throws ValidationException {@code a} failed the validation. 1379 * @throws NullArgumentException {@code arg}, {@code name} or 1380 * {@code validation} is {@code null}. 1381 * @throws EmptyArgumentException {@code name} is the empty String. 1382 * 1383 * @since 0.1.0 1384 */ 1385 @API( status = STABLE, since = "0.1.0" ) 1386 public static final <T> T requireValidNonNullArgument( final T arg, final String name, final Predicate<? super T> validation ) 1387 { 1388 requireNotBlankArgument( name, "name" ); 1389 1390 if( !requireNonNullArgument( validation, "validation" ).test( requireNonNullArgument( arg, "name" ) ) ) 1391 { 1392 throw new ValidationException( "Validation failed for '%s'".formatted( name ) ); 1393 } 1394 1395 //---* Done *---------------------------------------------------------- 1396 return arg; 1397 } // requireValidNonNullArgument() 1398 1399 /** 1400 * <p>{@summary Applies the given validation on the given value (that must 1401 * not be {@code null}), and if that fails, a 1402 * {@link ValidationException} 1403 * is thrown.} The message for the exception will be provided by the given 1404 * message supplier that takes the name of the argument as an 1405 * argument.</p> 1406 * 1407 * @param <T> The type of the value to check. 1408 * @param arg The value to check. 1409 * @param name The name of the argument; this is used for the error 1410 * message. 1411 * @param validation The validation 1412 * @param messageSupplier The function that generates the message for the 1413 * exception. 1414 * @return The value if the validation succeeds. 1415 * @throws ValidationException {@code arg} failed the validation. 1416 * @throws NullArgumentException {@code arg}, {@code name}, 1417 * {@code validation} or {@code messageProvider} is {@code null}. 1418 * @throws EmptyArgumentException {@code name} is the empty String. 1419 * 1420 * @since 0.1.0 1421 */ 1422 @API( status = STABLE, since = "0.1.0" ) 1423 public static final <T> T requireValidNonNullArgument( final T arg, final String name, final Predicate<? super T> validation, final UnaryOperator<String> messageSupplier ) 1424 { 1425 requireNotBlankArgument( name, "name" ); 1426 requireNonNullArgument( messageSupplier, "messageSupplier" ); 1427 1428 if( !requireNonNullArgument( validation, "validation" ).test( requireNonNullArgument( arg, "name" ) ) ) 1429 { 1430 throw new ValidationException( messageSupplier.apply( name ) ); 1431 } 1432 1433 //---* Done *---------------------------------------------------------- 1434 return arg; 1435 } // requireValidNonNullArgument() 1436 1437 /** 1438 * <p>{@summary Converts the given argument {@code object} into a 1439 * {@link String}, 1440 * usually by calling its 1441 * {@link Object#toString() toString()} 1442 * method.} If the value of the argument is {@code null}, the text 1443 * "{@link org.tquadrat.foundation.lang.CommonConstants#NULL_STRING null}" 1444 * will be returned instead. Arrays will be converted to a String through 1445 * calling the respective {@code toString()} method from 1446 * {@link java.util.Arrays} 1447 * (this distinguishes this implementation from 1448 * {link java.util.Objects#toString(Object, String) java.util.Objects.toString()}). 1449 * Values of type 1450 * {@link java.util.Date} or 1451 * {@link java.util.Calendar} 1452 * will be translated based on the default locale - whatever that is. 1453 * 1454 * @param object The object; may be {@code null}. 1455 * @return The object's string representation. 1456 * 1457 * @see java.util.Arrays#toString(boolean[]) 1458 * @see java.util.Arrays#toString(byte[]) 1459 * @see java.util.Arrays#toString(char[]) 1460 * @see java.util.Arrays#toString(double[]) 1461 * @see java.util.Arrays#toString(float[]) 1462 * @see java.util.Arrays#toString(int[]) 1463 * @see java.util.Arrays#toString(long[]) 1464 * @see java.util.Arrays#toString(Object[]) 1465 * @see java.util.Arrays#toString(short[]) 1466 * @see java.util.Arrays#deepToString(Object[]) 1467 * @see java.util.Locale#getDefault() 1468 * @see org.tquadrat.foundation.lang.CommonConstants#NULL_STRING 1469 * 1470 * @since 0.0.5 1471 */ 1472 @API( status = STABLE, since = "0.0.5" ) 1473 public static final String toString( final Object object ) 1474 { 1475 return toString( object, NULL_STRING ); 1476 } // toString() 1477 1478 /** 1479 * <p>{@summary Converts the given argument {@code object} into a 1480 * {@link String}, 1481 * usually by calling its 1482 * {@link Object#toString() toString()} 1483 * method.} If the value of the argument is {@code null}, the text 1484 * provided as the {@code nullDefault} argument will be returned 1485 * instead.</p> 1486 * <p>Arrays will be converted to a string through calling the respective 1487 * {@code toString()} method from 1488 * {@link java.util.Arrays} 1489 * (this distinguishes this implementation from 1490 * {link java.util.Objects#toString(Object,String) java.util.Objects.toString(Object,String)}).</p> 1491 * <p>Values of type 1492 * {@link java.util.Date} or 1493 * {@link java.util.Calendar} 1494 * will be translated based on the 1495 * {@link java.util.Locale#getDefault() default locale} 1496 * – whatever that is.</p> 1497 * 1498 * @param object The object; may be {@code null}. 1499 * @param nullDefault The text that should be returned if {@code object} 1500 * is {@code null}. 1501 * @return The object's string representation. 1502 * 1503 * @see java.util.Arrays#toString(boolean[]) 1504 * @see java.util.Arrays#toString(byte[]) 1505 * @see java.util.Arrays#toString(char[]) 1506 * @see java.util.Arrays#toString(double[]) 1507 * @see java.util.Arrays#toString(float[]) 1508 * @see java.util.Arrays#toString(int[]) 1509 * @see java.util.Arrays#toString(long[]) 1510 * @see java.util.Arrays#toString(Object[]) 1511 * @see java.util.Arrays#toString(short[]) 1512 * @see java.util.Arrays#deepToString(Object[]) 1513 * @see java.util.Locale#getDefault() 1514 * 1515 * @since 0.0.5 1516 */ 1517 @SuppressWarnings( {"IfStatementWithTooManyBranches", "ChainOfInstanceofChecks", "OverlyComplexMethod"} ) 1518 @API( status = STABLE, since = "0.0.5" ) 1519 public static final String toString( final Object object, final String nullDefault ) 1520 { 1521 var retValue = requireNonNullArgument( nullDefault, "nullDefault" ); 1522 if( nonNull( object ) ) 1523 { 1524 final var objectClass = object.getClass(); 1525 if( objectClass.isArray() ) 1526 { 1527 if( objectClass == byte [].class ) 1528 { 1529 retValue = Arrays.toString( (byte []) object ); 1530 } 1531 else if( objectClass == short [].class ) 1532 { 1533 retValue = Arrays.toString( (short []) object ); 1534 } 1535 else if( objectClass == int [].class ) 1536 { 1537 retValue = Arrays.toString( (int []) object ); 1538 } 1539 else if( objectClass == long [].class ) 1540 { 1541 retValue = Arrays.toString( (long []) object ); 1542 } 1543 else if( objectClass == char [].class ) 1544 { 1545 retValue = Arrays.toString( (char []) object ); 1546 } 1547 else if( objectClass == float [].class ) 1548 { 1549 retValue = Arrays.toString( (float []) object ); 1550 } 1551 else if( objectClass == double [].class ) 1552 { 1553 retValue = Arrays.toString( (double []) object ); 1554 } 1555 else if( objectClass == boolean [].class ) 1556 { 1557 retValue = Arrays.toString( (boolean []) object ); 1558 } 1559 else 1560 { 1561 retValue = deepToString( (Object []) object ); 1562 } 1563 } 1564 else 1565 { 1566 retValue = object.toString(); 1567 } 1568 } 1569 1570 //---* Done *---------------------------------------------------------- 1571 return retValue; 1572 } // toString() 1573 1574 /** 1575 * <p>{@summary Converts the given argument into a 1576 * {@link String} 1577 * using the given instance of 1578 * {@link Stringer}.} 1579 * If the value of the argument is {@code null}, the text 1580 * provided as the {@code nullDefault} argument will be returned 1581 * instead.</p> 1582 * 1583 * @param <T> The type of the object. 1584 * @param value The object; may be {@code null}. 1585 * @param stringer The method that is used to convert the given object 1586 * to a String. 1587 * @param nullDefault The text that should be returned if {@code object} 1588 * is {@code null}. 1589 * @return The object's string representation. 1590 * 1591 * @see Stringer 1592 * 1593 * @since 0.0.5 1594 */ 1595 @API( status = STABLE, since = "0.0.5" ) 1596 public static final <T> String toString( final T value, final Stringer<? super T> stringer, final String nullDefault ) 1597 { 1598 requireNonNullArgument( nullDefault, "nullDefault" ); 1599 1600 final var retValue = nonNull( value ) ? requireNonNullArgument( stringer, "stringer" ).toString( value ) : nullDefault; 1601 1602 //---* Done *---------------------------------------------------------- 1603 return retValue; 1604 } // toString() 1605} 1606// class Objects 1607 1608/* 1609 * End of File 1610 */