/*
 * Copyright (c) 2010-2017. Axon Framework
 *
 * 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.
 */

package org.axonframework.common;

import java.util.Objects;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Utility class (inspired by Springs Assert class) for doing assertions on parameters and object state. To remove the
 * need for explicit dependencies on Spring, the functionality of that class is migrated to this class.
 *
 * @author Allard Buijze
 * @since 0.3
 */
public abstract class Assert {

    private Assert() {
        // utility class
    }

    /**
     * Asserts that the value of {@code state} is true. If not, an IllegalStateException is thrown.
     *
     * @param state           the state validation expression
     * @param messageSupplier Supplier of the exception message if state evaluates to false
     */
    public static void state(boolean state, Supplier<String> messageSupplier) {
        if (!state) {
            throw new IllegalStateException(messageSupplier.get());
        }
    }

    /**
     * Asserts that the given {@code expression} is true. If not, an IllegalArgumentException is thrown.
     *
     * @param expression      the state validation expression
     * @param messageSupplier Supplier of the exception message if the expression evaluates to false
     */
    public static void isTrue(boolean expression, Supplier<String> messageSupplier) {
        if (!expression) {
            throw new IllegalArgumentException(messageSupplier.get());
        }
    }

    /**
     * Asserts that the given {@code expression} is false. If not, an IllegalArgumentException is thrown.
     *
     * @param expression      the state validation expression
     * @param messageSupplier Supplier of the exception message if the expression evaluates to true
     */
    public static void isFalse(boolean expression, Supplier<String> messageSupplier) {
        if (expression) {
            throw new IllegalArgumentException(messageSupplier.get());
        }
    }

    /**
     * Assert that the given {@code value} is not {@code null}. If not, an IllegalArgumentException is
     * thrown.
     *
     * @param value           the value not to be {@code null}
     * @param messageSupplier Supplier of the exception message if the assertion fails
     */
    public static void notNull(Object value, Supplier<String> messageSupplier) {
        isTrue(value != null, messageSupplier);
    }

    /**
     * Assert that the given {@code value} is not {@code null}. If not, an IllegalArgumentException is
     * thrown.
     *
     * @param value           the value not to be {@code null}
     * @param messageSupplier Supplier of the exception message if the assertion fails
     * @return the provided {@code value}
     */
    public static <T> T nonNull(T value, Supplier<String> messageSupplier) {
        isTrue(value != null, messageSupplier);
        return value;
    }

    /**
     * Assert that the given {@code value} will result to {@code true} through the {@code assertion} {@link Predicate}.
     * If not, the {@code exceptionSupplier} provides an exception
     * to be thrown.
     *
     * @param value             a {@code T} specifying the value to assert
     * @param assertion         a {@link Predicate} to test {@code value} against
     * @param exceptionSupplier a {@link Supplier} of the exception {@code X} if {@code assertion} evaluates to false
     * @param <T>               a generic specifying the type of the {@code value}, which is the input for the
     *                          {@code assertion}
     * @param <X>               a generic extending {@link Throwable} which will be provided by the
     *                          {@code exceptionSupplier}
     * @throws X if the {@code value} asserts to {@code false} by the {@code assertion}
     */
    @SuppressWarnings("RedundantThrows") // Throws signature required for correct compilation
    public static <T, X extends Throwable> void assertThat(T value,
                                                           Predicate<T> assertion,
                                                           Supplier<? extends X> exceptionSupplier) throws X {
        if (!assertion.test(value)) {
            throw exceptionSupplier.get();
        }
    }

    /**
     * Assert that the given {@code value} is non null. If not, the {@code exceptionSupplier} provides an exception to
     * be thrown.
     *
     * @param value             a {@code T} specifying the value to assert
     * @param exceptionSupplier a {@link Supplier} of the exception {@code X} if {@code value} equals null
     * @param <T>               a generic specifying the type of the {@code value}, which is the input for the
     *                          {@code assertion}
     * @param <X>               a generic extending {@link Throwable} which will be provided by the
     *                          {@code exceptionSupplier}
     * @throws X if the {@code value} equals {@code null}
     */
    public static <T, X extends Throwable> void assertNonNull(T value,
                                                              Supplier<? extends X> exceptionSupplier) throws X {
        assertThat(value, Objects::nonNull, exceptionSupplier);
    }
}

@@ -25,9 +25,9 @@
 -201
-7
+8
 . Ax
@@ -225,17 +225,16 @@
 at%0A *%0A *
- 
     http
@@ -662,16 +662,54 @@
 bjects;%0A
+import java.util.concurrent.TimeUnit;%0A
 import j
@@ -5836,11 +5836,987 @@
 );%0A    %7D
+%0A%0A    // TODO Ok to move this guy here?%0A    /**%0A     * Assert that the given %7B@code assertion%7D succeeds with the given %7B@code time%7D and %7B@code unit%7D.%0A     *%0A     * @param time      an %7B@code int%7D which paired with the %7B@code unit%7D specifies the time in which the assertion must%0A     *                  pass%0A     * @param unit      a %7B@link TimeUnit%7D in which %7B@code time%7D is expressed%0A     * @param assertion a %7B@link Runnable%7D containing the assertion to succeed within the deadline%0A     */%0A    public static void assertWithin(int time, TimeUnit unit, Runnable assertion) %7B%0A        long now = System.currentTimeMillis();%0A        long deadline = now + unit.toMillis(time);%0A        do %7B%0A            try %7B%0A                assertion.run();%0A                break;%0A            %7D catch (AssertionError e) %7B%0A                if (now %3E= deadline) %7B%0A                    throw e;%0A                %7D%0A            %7D%0A            now = System.currentTimeMillis();%0A        %7D while (true);%0A    %7D
 %0A%7D%0A

Add assertWithin()