
package org.innovateuk.ifs;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.mockito.ArgumentMatcher;

import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;

import static org.mockito.ArgumentMatchers.argThat;

/**
 * Custom Mockito matcher to leverage Java 8 lambdas
 *
 * @param <T>
 */
@SuppressWarnings("unchecked")
public class LambdaMatcher<T> extends BaseMatcher<T> implements ArgumentMatcher<T> {

    private final Predicate<T> matcher;
    private Optional<String> description = Optional.empty();

    public LambdaMatcher(Predicate<T> predicate) {
        this.matcher = value -> {

            if (value == null) {
                return false;
            }

            try {
                return predicate.test(value);
            } catch (AssertionError e) {
                this.description = Optional.of(e.getMessage());
                return false;
            }
        };
    }


    @SuppressWarnings("unchecked")
    @Override
    public boolean matches(Object argument) {
        return matcher.test((T) argument);
    }

    @Override
    public void describeTo(Description description) {
        this.description.ifPresent(description::appendText);
    }

    public static <T> LambdaMatcher<T> lambdaMatches(Predicate<T> predicate) {
        return new LambdaMatcher(predicate);
    }

    /**
     * Creates a new matcher that takes a lambda predicate and can optionally return false or throw an assertion error if
     * the parameter doesn't match the predicate test.  A null check is also performed as per all standard Mockito matchers.
     *
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> T createLambdaMatcher(Predicate<T> predicate) {
        return argThat(lambdaMatches(predicate));
    }

    /**
     * Creates a new matcher that takes a lambda consumer and can throw an assertion error in the consumer if it
     * doesn't pass the test.  A null check is also performed as per all standard Mockito matchers.
     *
     * @param consumer
     * @param <T>
     * @return
     */
    public static <T> T createLambdaMatcher(Consumer<T> consumer) {
        return argThat(lambdaMatches((T argument) -> {
            consumer.accept(argument);
            return true;
        }));
    }
}

@@ -27,74 +27,8 @@
 s;%0A%0A
-import org.hamcrest.BaseMatcher;%0Aimport org.hamcrest.Description;%0A
 impo
@@ -296,81 +296,27 @@
  */%0A
-@SuppressWarnings(%22unchecked%22)%0Apublic class LambdaMatcher%3CT%3E extends Base
+public class Lambda
 Matc
@@ -857,43 +857,8 @@
 %7D%0A%0A%0A
-    @SuppressWarnings(%22unchecked%22)%0A
     
@@ -898,14 +898,9 @@
 hes(
-Object
+T
  arg
@@ -940,12 +940,8 @@
 est(
-(T) 
 argu
@@ -958,144 +958,8 @@
  %7D%0A%0A
-    @Override%0A    public void describeTo(Description description) %7B%0A        this.description.ifPresent(description::appendText);%0A    %7D%0A%0A
     
@@ -1065,16 +1065,19 @@
 aMatcher
+%3CT%3E
 (predica

remove unchecked