/*
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * Copyright 2012-2023 the original author or authors.
 */
package org.assertj.core.api;

import static org.assertj.core.api.Assertions.catchThrowable;

import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Spliterator;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.DoublePredicate;
import java.util.function.IntPredicate;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.assertj.core.configuration.PreferredAssumptionException;
import org.assertj.core.util.CheckReturnValue;

/**
 * A unified entry point to all assumptions from both the new Java 8 core API and the pre-Java 8 core API.
 *
 * As a convenience, the methods are defined in an interface so that no static imports are necessary if the test class
 * implements this interface.
 */
@CheckReturnValue
public interface WithAssumptions {

  /**
   * Creates a new instance of <code>{@link ObjectArrayAssert}</code> assumption.
   *
   * @param <T> the type of elements.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <T> ObjectArrayAssert<T> assumeThat(final T[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Object2DArrayAssert}</code> assumption.
   *
   * @param <T> the type of elements.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default <T> Object2DArrayAssert<T> assumeThat(final T[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link MapAssert}</code> assumption.
   *
   * @param <K> the type of keys in the map.
   * @param <V> the type of values in the map.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <K, V> MapAssert<K, V> assumeThat(final Map<K, V> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ShortAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractShortAssert<?> assumeThat(final short actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link LongAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLongAssert<?> assumeThat(final long actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link LongAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLongAssert<?> assumeThat(final Long actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link LongArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLongArrayAssert<?> assumeThat(final long[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Long2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Long2DArrayAssert assumeThat(final long[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ObjectAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <T> the type of the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <T> ObjectAssert<T> assumeThat(final T actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link StringAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractStringAssert<?> assumeThat(final String actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link DateAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractDateAssert<?> assumeThat(final Date actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ThrowableAssert}</code> assumption.
   *
   * @param <T> the type of the actual value.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <T extends Throwable> AbstractThrowableAssert<?, T> assumeThat(final T actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link BigDecimalAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractBigDecimalAssert<?> assumeThat(final BigDecimal actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link BigIntegerAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractBigIntegerAssert<?> assumeThat(BigInteger actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicBooleanAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AtomicBooleanAssert assumeThat(AtomicBoolean actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicIntegerAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @return the created assertion object.
   */
  default AtomicIntegerAssert assumeThat(AtomicInteger actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates int[] assumption for {@link AtomicIntegerArray}.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AtomicIntegerArrayAssert assumeThat(AtomicIntegerArray actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicIntegerFieldUpdaterAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @param <OBJECT> the type of the object holding the updatable field.
   * @return the created assertion object.
   */
  default <OBJECT> AtomicIntegerFieldUpdaterAssert<OBJECT> assumeThat(AtomicIntegerFieldUpdater<OBJECT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link LongAdderAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @return the created assertion object.
   */
  default LongAdderAssert assumeThat(LongAdder actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicLongAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @return the created assertion object.
   */
  default AtomicLongAssert assumeThat(AtomicLong actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicLongArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @return the created assertion object.
   */
  default AtomicLongArrayAssert assumeThat(AtomicLongArray actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicLongFieldUpdaterAssert}</code> assumption.
   *
   * @param actual the actual value.
   *
   * @param <OBJECT> the type of the object holding the updatable field.
   * @return the created assertion object.
   */
  default <OBJECT> AtomicLongFieldUpdaterAssert<OBJECT> assumeThat(AtomicLongFieldUpdater<OBJECT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicReferenceAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <VALUE> the type of the value contained in the {@link AtomicReference}.
   *
   * @return the created assertion object.
   */
  default <VALUE> AtomicReferenceAssert<VALUE> assumeThat(AtomicReference<VALUE> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicReferenceArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <ELEMENT> the type of the value contained in the {@link AtomicReferenceArray}.
   *
   * @return the created assertion object.
   */
  default <ELEMENT> AtomicReferenceArrayAssert<ELEMENT> assumeThat(AtomicReferenceArray<ELEMENT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicReferenceFieldUpdaterAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <FIELD> the type of the field which gets updated by the {@link AtomicReferenceFieldUpdater}.
   * @param <OBJECT> the type of the object holding the updatable field.
   *
   * @return the created assertion object.
   */
  default <FIELD, OBJECT> AtomicReferenceFieldUpdaterAssert<FIELD, OBJECT> assumeThat(AtomicReferenceFieldUpdater<OBJECT, FIELD> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicMarkableReferenceAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <VALUE> the type of the value contained in the {@link AtomicMarkableReference}.
   *
   * @return the created assertion object.
   */
  default <VALUE> AtomicMarkableReferenceAssert<VALUE> assumeThat(AtomicMarkableReference<VALUE> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link AtomicStampedReferenceAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @param <VALUE> the type of the value contained in the {@link AtomicStampedReference}.
   *
   * @return the created assertion object.
   */
  default <VALUE> AtomicStampedReferenceAssert<VALUE> assumeThat(AtomicStampedReference<VALUE> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharSequenceAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractCharSequenceAssert<?, ? extends CharSequence> assumeThat(final CharSequence actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharSequenceAssert}</code> assumption from a {@link StringBuilder}.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.11.0
   */
  default AbstractCharSequenceAssert<?, ? extends CharSequence> assumeThat(final StringBuilder actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharSequenceAssert}</code> assumption from a {@link StringBuffer}.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.11.0
   */
  default AbstractCharSequenceAssert<?, ? extends CharSequence> assumeThat(final StringBuffer actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ShortArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractShortArrayAssert<?> assumeThat(final short[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Short2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Short2DArrayAssert assumeThat(final short[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ShortAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractShortAssert<?> assumeThat(final Short actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ClassAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default ClassAssert assumeThat(final Class<?> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharacterAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractCharacterAssert<?> assumeThat(final Character actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractCharArrayAssert<?> assumeThat(final char[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Char2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Char2DArrayAssert assumeThat(final char[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link CharacterAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractCharacterAssert<?> assumeThat(final char actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link GenericComparableAssert}</code> assumption.
   *
   * @param <T> the type of actual.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <T extends Comparable<? super T>> AbstractComparableAssert<?, T> assumeThat(final T actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link IterableAssert}</code> assumption.
   *
   * @param <ELEMENT> the type of elements.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <ELEMENT> IterableAssert<ELEMENT> assumeThat(final Iterable<? extends ELEMENT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link IteratorAssert}</code> assumption.
   * <p>
   * <b>Breaking change in version 3.12.0:</b> this method does not return anymore an {@link IterableAssert} but an {@link IteratorAssert}.
   *
   * @param <ELEMENT> the type of elements.
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <ELEMENT> IteratorAssert<ELEMENT> assumeThat(final Iterator<? extends ELEMENT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link BooleanAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractBooleanAssert<?> assumeThat(final Boolean actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link BooleanArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractBooleanArrayAssert<?> assumeThat(final boolean[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Boolean2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Boolean2DArrayAssert assumeThat(final boolean[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ByteAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractByteAssert<?> assumeThat(final byte actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ByteAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractByteAssert<?> assumeThat(final Byte actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ByteArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractByteArrayAssert<?> assumeThat(final byte[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Byte2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Byte2DArrayAssert assumeThat(final byte[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link BooleanAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractBooleanAssert<?> assumeThat(final boolean actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link FloatAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractFloatAssert<?> assumeThat(final float actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link InputStreamAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractInputStreamAssert<?, ? extends InputStream> assumeThat(final InputStream actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link FileAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractFileAssert<?> assumeThat(final File actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Create assertion for {@link FutureAssert} assumption.
   *
   * @param actual the actual value.
   * @param <RESULT> the type of the value contained in the {@link java.util.concurrent.Future}.
   *
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <RESULT> AbstractFutureAssert<?, ? extends Future<? extends RESULT>, RESULT> assumeThat(Future<RESULT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link PathAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractPathAssert<?> assumeThat(final Path actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link IntArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractIntArrayAssert<?> assumeThat(final int[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Int2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Int2DArrayAssert assumeThat(final int[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link FloatAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractFloatAssert<?> assumeThat(final Float actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Float2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Float2DArrayAssert assumeThat(final float[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link IntegerAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractIntegerAssert<?> assumeThat(final int actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link FloatArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractFloatArrayAssert<?> assumeThat(final float[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link IntegerAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractIntegerAssert<?> assumeThat(final Integer actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link DoubleAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractDoubleAssert<?> assumeThat(final double actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link DoubleAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractDoubleAssert<?> assumeThat(final Double actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ListAssert}</code> assumption.
   *
   * @param <ELEMENT> the type of elements.
   * @param list the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default <ELEMENT> FactoryBasedNavigableListAssert<ListAssert<ELEMENT>, List<? extends ELEMENT>, ELEMENT, ObjectAssert<ELEMENT>> assumeThat(List<? extends ELEMENT> list) {
    return Assumptions.assumeThat(list);
  }

  /**
   * Creates a new instance of <code>{@link ListAssert}</code> assumption from the given {@link Stream}.
   *
   * @param <ELEMENT> the type of elements.
   * @param stream the Stream to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default <ELEMENT> AbstractListAssert<?, List<? extends ELEMENT>, ELEMENT, ObjectAssert<ELEMENT>> assumeThat(Stream<? extends ELEMENT> stream) {
    return Assumptions.assumeThat(stream);
  }

  /**
   * Creates a new instance of <code>{@link ListAssert}</code> assumption from the given {@link DoubleStream}.
   *
   * @param doubleStream the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractListAssert<?, List<? extends Double>, Double, ObjectAssert<Double>> assumeThat(DoubleStream doubleStream) {
    return Assumptions.assumeThat(doubleStream);
  }

  /**
   * Creates a new instance of <code>{@link ListAssert}</code> assumption from the given {@link LongStream}.
   *
   * @param longStream the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractListAssert<?, List<? extends Long>, Long, ObjectAssert<Long>> assumeThat(LongStream longStream) {
    return Assumptions.assumeThat(longStream);
  }

  /**
   * Creates a new instance of <code>{@link ListAssert}</code> assumption from the given {@link IntStream}.
   *
   * @param intStream the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractListAssert<?, List<? extends Integer>, Integer, ObjectAssert<Integer>> assumeThat(IntStream intStream) {
    return Assumptions.assumeThat(intStream);
  }

  /**
   * Creates a new instance of <code>{@link DoubleArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractDoubleArrayAssert<?> assumeThat(final double[] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link Double2DArrayAssert}</code> assumption.
   *
   * @param actual the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default Double2DArrayAssert assumeThat(final double[][] actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of <code>{@link ZonedDateTimeAssert}</code> assumption.
   *
   * @param zonedDateTime the actual value.
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default AbstractZonedDateTimeAssert<?> assumeThat(final ZonedDateTime zonedDateTime) {
    return Assumptions.assumeThat(zonedDateTime);
  }

  /**
   * Creates a new instance of {@link CompletableFutureAssert} assumption.
   *
   * @param <RESULT> the CompletableFuture wrapped type.
   * @param future the CompletableFuture to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default <RESULT> CompletableFutureAssert<RESULT> assumeThat(final CompletableFuture<RESULT> future) {
    return Assumptions.assumeThat(future);
  }

  /**
   * Creates a new instance of {@link CompletableFutureAssert} assumption for a {@link java.util.concurrent.CompletionStage}
   * by converting it to a {@link CompletableFuture} and returning a {@link CompletableFutureAssert}.
   * <p>
   * If the given {@link java.util.concurrent.CompletionStage} is null, the {@link CompletableFuture} in the returned {@link CompletableFutureAssert} will also be null.
   *
   * @param <RESULT> the CompletableFuture wrapped type.
   * @param actual the CompletableFuture to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default <RESULT> CompletableFutureAssert<RESULT> assumeThat(CompletionStage<RESULT> actual) {
    return Assumptions.assumeThat(actual);
  }

  /**
   * Creates a new instance of {@link OptionalAssert} assumption.
   *
   * @param <VALUE> the Optional wrapped type.
   * @param optional the Optional to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default <VALUE> OptionalAssert<VALUE> assumeThat(final Optional<VALUE> optional) {
    return Assumptions.assumeThat(optional);
  }

  /**
   * Creates a new instance of <code>{@link OptionalDoubleAssert}</code> assumption.
   *
   * @param optionalDouble the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default OptionalDoubleAssert assumeThat(final OptionalDouble optionalDouble) {
    return Assumptions.assumeThat(optionalDouble);
  }

  /**
   * Creates a new instance of <code>{@link OptionalIntAssert}</code> assumption.
   *
   * @param optionalInt the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default OptionalIntAssert assumeThat(final OptionalInt optionalInt) {
    return Assumptions.assumeThat(optionalInt);
  }

  /**
   * Creates a new instance of <code>{@link OptionalLongAssert}</code> assumption.
   *
   * @param optionalLong the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default OptionalLongAssert assumeThat(final OptionalLong optionalLong) {
    return Assumptions.assumeThat(optionalLong);
  }

  /**
   * Creates a new instance of <code>{@link MatcherAssert}</code> assumption.
   *
   * @param matcher the actual Matcher.
   * @return the created assumption for assertion object.
   */
  default MatcherAssert assumeThat(final Matcher matcher) {
    return Assumptions.assumeThat(matcher);
  }

  /**
   * Creates a new instance of <code>{@link LocalDateTimeAssert}</code> assumption.
   *
   * @param localDateTime the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLocalDateTimeAssert<?> assumeThat(final LocalDateTime localDateTime) {
    return Assumptions.assumeThat(localDateTime);
  }

  /**
   * Creates a new instance of <code>{@link LocalDateAssert}</code> assumption.
   *
   * @param localDate the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLocalDateAssert<?> assumeThat(final LocalDate localDate) {
    return Assumptions.assumeThat(localDate);
  }

  /**
   * Creates a new instance of <code>{@link LocalTimeAssert}</code> assumption.
   *
   * @param localTime the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractLocalTimeAssert<?> assumeThat(final LocalTime localTime) {
    return Assumptions.assumeThat(localTime);
  }

  /**
   * Creates a new instance of <code>{@link InstantAssert}</code> assumption.
   *
   * @param instant the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractInstantAssert<?> assumeThat(final Instant instant) {
    return Assumptions.assumeThat(instant);
  }

  /**
   * Creates a new instance of <code>{@link DurationAssert}</code> assumption.
   *
   * @param duration the actual value.
   * @return the created assumption for assertion object.
   * @since 3.15.0
   */
  default AbstractDurationAssert<?> assumeThat(final Duration duration) {
    return Assumptions.assumeThat(duration);
  }

  /**
   * Creates a new instance of <code>{@link PeriodAssert}</code> assumption.
   *
   * @param period the actual value.
   * @return the created assumption for assertion object.
   * @since 3.17.0
   */
  default AbstractPeriodAssert<?> assumeThat(final Period period) {
    return Assumptions.assumeThat(period);
  }

  /**
   * Creates a new instance of <code>{@link OffsetTimeAssert}</code> assumption.
   *
   * @param offsetTime the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractOffsetTimeAssert<?> assumeThat(final OffsetTime offsetTime) {
    return Assumptions.assumeThat(offsetTime);
  }

  /**
   * Creates a new instance of <code>{@link OffsetDateTimeAssert}</code> assumption.
   *
   * @param offsetDateTime the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractOffsetDateTimeAssert<?> assumeThat(final OffsetDateTime offsetDateTime) {
    return Assumptions.assumeThat(offsetDateTime);
  }

  /**
   * Allows to capture and then assume on a {@link Throwable} (easier done with lambdas).
   * <p>
   * Example :
   * <pre><code class='java'>  {@literal @}Test
   *  public void testException() {
   *    assumeThatThrownBy(() -&gt; { throw new Exception("boom!") }).isInstanceOf(Exception.class)
   *                                                              .hasMessageContaining("boom");
   * }</code></pre>
   *
   * @param shouldRaiseThrowable The {@link ThrowingCallable} or lambda with the code that should raise the throwable.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractThrowableAssert<?, ? extends Throwable> assumeThatThrownBy(final ThrowingCallable shouldRaiseThrowable) {
    return Assumptions.assumeThatThrownBy(shouldRaiseThrowable);
  }

  /**
   * Allows to capture and then assume on a {@link Throwable} (easier done with lambdas).
   * <p>
   * Example :
   * <pre><code class='java'> ThrowingCallable callable = () -&gt; {
   *   throw new Exception("boom!");
   * };
   *
   * // assertion succeeds
   * assumeThatCode(callable).isInstanceOf(Exception.class)
   *                         .hasMessageContaining("boom");
   *
   * // assertion fails
   * assumeThatCode(callable).doesNotThrowAnyException();</code></pre>
   * <p>
   * This method was not named {@code assumeThat} because the java compiler reported it ambiguous when used directly with a lambda :(
   *
   * @param shouldRaiseOrNotThrowable The {@link ThrowingCallable} or lambda with the code that should raise the throwable.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractThrowableAssert<?, ? extends Throwable> assumeThatCode(ThrowingCallable shouldRaiseOrNotThrowable) {
    return assumeThat(catchThrowable(shouldRaiseOrNotThrowable));
  }

  /**
   * Creates a new instance of <code>{@link ObjectAssert}</code> for any object.
   * <p>
   * This overload is useful, when an overloaded method of assertThat(...) takes precedence over the generic {@link
   * #assumeThat(Object)}.
   * <p>
   * Example:
   * <p>
   * Cast necessary because {@link #assumeThat(List)} "forgets" actual type:
   * <pre>{@code assumeThat(new LinkedList<>(asList("abc"))).matches(list -> ((Deque<String>) list).getFirst().equals("abc")); }</pre>
   * No cast needed, but also no additional list assertions:
   * <pre>{@code assumeThatObject(new LinkedList<>(asList("abc"))).matches(list -> list.getFirst().equals("abc")); }</pre>
   *
   * @param <T> the type of the actual value.
   * @param actual the actual value.
   * @return the created assertion object.
   * @since 3.12.0
   */
  default <T> ObjectAssert<T> assumeThatObject(T actual) {
    return assumeThat(actual);
  }

  /**
   * Creates a new instance of {@link PredicateAssert} assumption.
   *
   * @param <T> the {@link Predicate} type.
   * @param predicate the Predicate to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default <T> PredicateAssert<T> assumeThat(final Predicate<T> predicate) {
    return Assumptions.assumeThat(predicate);
  }

  /**
   * Creates a new instance of {@link IntPredicateAssert} assumption.
   *
   * @param intPredicate the IntPredicate to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default IntPredicateAssert assumeThat(final IntPredicate intPredicate) {
    return Assumptions.assumeThat(intPredicate);
  }

  /**
   * Creates a new instance of {@link LongPredicateAssert} assumption.
   *
   * @param longPredicate the LongPredicate to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default LongPredicateAssert assumeThat(final LongPredicate longPredicate) {
    return Assumptions.assumeThat(longPredicate);
  }

  /**
   * Creates a new instance of {@link DoublePredicateAssert} assumption.
   *
   * @param doublePredicate the DoublePredicate to test
   * @return the created assumption for assertion object.
   * @since 3.9.0
   */
  default DoublePredicateAssert assumeThat(final DoublePredicate doublePredicate) {
    return Assumptions.assumeThat(doublePredicate);
  }

  /**
   * Creates a new instance of <code>{@link UrlAssert}</code> assumption.
   *
   * @param url the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractUrlAssert<?> assumeThat(final URL url) {
    return Assumptions.assumeThat(url);
  }

  /**
   * Creates a new instance of <code>{@link UriAssert}</code> assumption.
   *
   * @param uri the actual value.
   * @return the created assumption for assertion object.
   * @since 2.9.0 / 3.9.0
   */
  default AbstractUriAssert<?> assumeThat(final URI uri) {
    return Assumptions.assumeThat(uri);
  }

  /**
   * Creates a new instance of <code>{@link SpliteratorAssert}</code> assumption.
   *
   * @param <ELEMENT> the type of the elements.
   * @param spliterator the actual value.
   * @return the created assumption for assertion object.
   * @since 3.14.0
   */
  default <ELEMENT> AbstractSpliteratorAssert<?, ELEMENT> assumeThat(final Spliterator<ELEMENT> spliterator) {
    return Assumptions.assumeThat(spliterator);
  }

  /**
   * Sets which exception is thrown if an assumption is not met. 
   * <p>
   * This method is useful if you are using a testing framework that supports assumptions and expect a specific exception to be thrown when an assumption is not met. 
   * <p>
   * You can choose one of:
   * <ul>
   * <li>{@link PreferredAssumptionException#TEST_NG} to throw a {@code org.testng.SkipException} if you are using TestNG</li>
   * <li>{@link PreferredAssumptionException#JUNIT4} to throw a {@code org.junit.AssumptionViolatedException} if you are using JUnit 4</li>
   * <li>{@link PreferredAssumptionException#JUNIT5} a {@code org.opentest4j.TestAbortedException} if you are using JUnit 5</li>
   * <li>{@link PreferredAssumptionException#AUTO_DETECT} to get the default behavior where AssertJ tries different exception (explained later on)</li>
   * </ul>
   * <p>
   * Make sure that the exception you choose can be found in the classpath otherwise AssertJ will throw an {@link IllegalStateException}.
   * <p>
   * For example JUnit4 expects {@code org.junit.AssumptionViolatedException}, you can tell AssertJ to use it as shown below:
   * <pre><code class='java'> // after this call, AssertJ will throw an org.junit.AssumptionViolatedException when an assumption is not met   
   * Assertions.setPreferredAssumptionExceptions(PreferredAssumptionException.JUNIT4);
   * </code></pre>
   * <p>
   * By default, AssertJ uses the {@link PreferredAssumptionException#AUTO_DETECT AUTO_DETECT} mode and tries to throw one of the following exceptions, in this order:
   * <ol>
   * <li>{@code org.testng.SkipException} for TestNG (if available in the classpath)</li>
   * <li>{@code org.junit.AssumptionViolatedException} for JUnit 4 (if available in the classpath)</li>
   * <li>{@code org.opentest4j.TestAbortedException} for JUnit 5</li>
   * </ol> 
   *
   * @param preferredAssumptionException the preferred exception to use with {@link Assumptions}.
   * @since 3.21.0
   */
  default void setPreferredAssumptionException(PreferredAssumptionException preferredAssumptionException) {
    Assumptions.setPreferredAssumptionException(preferredAssumptionException);
  }
}
