package org.hamcrest; import org.hamcrest.internal.ReflectiveTypeFinder; /** * Convenient base class for Matchers that require a non-null value of a specific type and that will report why the received value has been * rejected. This implements the null check, checks the type and then casts. To use, implement * * <pre> * matchesSafely() * </pre> * * . * * @author Neil Dunn * @author Nat Pryce * @author Steve Freeman */ public abstract class TypeSafeDiagnosingMatcher<T> extends BaseMatcher<T> { private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 2, 0); private final Class<?> expectedType; /** * Subclasses should implement this. The item will already have been checked for the specific type and will never be null. */ protected abstract boolean matchesSafely(T item, Description mismatchDescription); /** * Use this constructor if the subclass that implements <code>matchesSafely</code> is <em>not</em> the class that binds <T> to a * type. * * @param expectedType * The expectedType of the actual value. */ protected TypeSafeDiagnosingMatcher(final Class<?> expectedType) { this.expectedType = expectedType; } /** * Use this constructor if the subclass that implements <code>matchesSafely</code> is <em>not</em> the class that binds <T> to a * type. * * @param typeFinder * A type finder to extract the type */ protected TypeSafeDiagnosingMatcher(final ReflectiveTypeFinder typeFinder) { this.expectedType = typeFinder.findExpectedType(getClass()); } /** * The default constructor for simple sub types */ protected TypeSafeDiagnosingMatcher() { this(TYPE_FINDER); } @Override @SuppressWarnings("unchecked") public final boolean matches(final Object item) { return item != null && expectedType.isInstance(item) && matchesSafely((T) item, new Description.NullDescription()); } @SuppressWarnings("unchecked") @Override public final void describeMismatch(final Object item, final Description mismatchDescription) { if (item == null || !expectedType.isInstance(item)) { super.describeMismatch(item, mismatchDescription); } else { matchesSafely((T) item, mismatchDescription); } } }