/*
 * Copyright (c) 2007 Mockito contributors
 * This program is made available under the terms of the MIT License.
 */
package org.mockito;

import org.hamcrest.Matcher;
import org.mockito.internal.matchers.*;
import org.mockito.internal.matchers.apachecommons.ReflectionEquals;
import org.mockito.internal.progress.HandyReturnValues;
import org.mockito.internal.progress.MockingProgress;
import org.mockito.internal.progress.ThreadSafeMockingProgress;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Allow flexible verification or stubbing. See also {@link AdditionalMatchers}.
 * <p>
 * {@link Mockito} extends Matchers so to get access to all matchers just import Mockito class statically.
 * <pre class="code"><code class="java">
 *  //stubbing using anyInt() argument matcher
 *  when(mockedList.get(anyInt())).thenReturn("element");
 *  
 *  //following prints "element"
 *  System.out.println(mockedList.get(999));
 *  
 *  //you can also verify using argument matcher
 *  verify(mockedList).get(anyInt());
 * </code></pre>
 * Scroll down to see all methods - full list of matchers.
 * <p>
 * <b>Warning:</b>
 * <p>
 * If you are using argument matchers, <b>all arguments</b> have to be provided by matchers.
 * <p>
 * E.g: (example shows verification but the same applies to stubbing):
 * <pre class="code"><code class="java">
 *   verify(mock).someMethod(anyInt(), anyString(), <b>eq("third argument")</b>);
 *   //above is correct - eq() is also an argument matcher
 *   
 *   verify(mock).someMethod(anyInt(), anyString(), <b>"third argument"</b>);
 *   //above is incorrect - exception will be thrown because third argument is given without argument matcher.
 * </code></pre>
 * <p>
 * Matcher methods like <code>anyObject()</code>, <code>eq()</code> <b>do not</b> return matchers.
 * Internally, they record a matcher on a stack and return a dummy value (usually null).
 * This implementation is due static type safety imposed by java compiler.
 * The consequence is that you cannot use <code>anyObject()</code>, <code>eq()</code> methods outside of verified/stubbed method.
 *
 * <p>
 * <b>Warning 2:</b>
 * <p>
 * The any family methods <b>*doesn't do any type checks*</b>, those are only here to avoid casting
 * in your code. If you want to perform type checks use the {@link #isA(Class)} method.
 * This <b>might</b> however change (type checks could be added) in a future major release.
 *
 * <h1>Custom Argument Matchers</h1>
 * 
 * Use {@link Matchers#argThat} method and pass an instance of hamcrest {@link Matcher}.
 * <p>
 * Before you start implementing your own custom argument matcher, make sure you check out {@link ArgumentCaptor} api.
 * <p>
 * So, how to implement your own argument matcher?
 * First, you might want to subclass {@link ArgumentMatcher} which is an hamcrest matcher with predefined describeTo() method.
 * Default description generated by describeTo() uses <b>decamelized class name</b> - to promote meaningful class names.
 * <p>
 * Example:
 * 
 * <pre class="code"><code class="java">
 *   class IsListOfTwoElements extends ArgumentMatcher&lt;List&gt; {
 *      public boolean matches(Object list) {
 *          return ((List) list).size() == 2;
 *      }
 *   }
 *   
 *   List mock = mock(List.class);
 *   
 *   when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);
 *   
 *   mock.addAll(Arrays.asList("one", "two"));
 *   
 *   verify(mock).addAll(argThat(new IsListOfTwoElements()));
 * </code></pre>
 * 
 * To keep it readable you may want to extract method, e.g:
 * <pre class="code"><code class="java">
 *   verify(mock).addAll(<b>argThat(new IsListOfTwoElements())</b>);
 *   //becomes
 *   verify(mock).addAll(<b>listOfTwoElements()</b>);
 * </code></pre>
 *
 * <b>Warning:</b> Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable. 
 * Sometimes it's better to implement equals() for arguments that are passed to mocks 
 * (Mockito naturally uses equals() for argument matching). 
 * This can make the test cleaner. 
 * <p>
 * Also, <b>sometimes {@link ArgumentCaptor} may be a better fit</b> than custom matcher. 
 * For example, if custom argument matcher is not likely to be reused
 * or you just need it to assert on argument values to complete verification of behavior.
 */
@SuppressWarnings("unchecked")
public class Matchers {
    
    private static final MockingProgress MOCKING_PROGRESS = new ThreadSafeMockingProgress();

    /**
     * Any <code>boolean</code>, <code>Boolean</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>false</code>.
     */
    public static boolean anyBoolean() {
        return reportMatcher(Any.ANY).returnFalse();
    }

    /**
     * Any <code>byte</code>, <code>Byte</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static byte anyByte() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>char</code>, <code>Character</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static char anyChar() {
        return reportMatcher(Any.ANY).returnChar();
    }

    /**
     * Any int, Integer or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static int anyInt() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>long</code>, <code>Long</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static long anyLong() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>float</code>, <code>Float</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static float anyFloat() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>double</code>, <code>Double</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static double anyDouble() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>short</code>, <code>Short</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>0</code>.
     */
    public static short anyShort() {
        return reportMatcher(Any.ANY).returnZero();
    }

    /**
     * Any <code>Object</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * Has aliases: {@link #any()} and {@link #any(Class clazz)}
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>null</code>.
     */
    public static <T> T anyObject() {
        return (T) reportMatcher(Any.ANY).returnNull();
    }

    /**
     * Any vararg, meaning any number and values of arguments.
     * <p>
     * Example:
     * <pre class="code"><code class="java">
     *   //verification:
     *   mock.foo(1, 2);
     *   mock.foo(1, 2, 3, 4);
     *
     *   verify(mock, times(2)).foo(anyVararg());
     *
     *   //stubbing:
     *   when(mock.foo(anyVararg()).thenReturn(100);
     *
     *   //prints 100
     *   System.out.println(mock.foo(1, 2));
     *   //also prints 100
     *   System.out.println(mock.foo(1, 2, 3, 4));
     * </code></pre>
     * See examples in javadoc for {@link Matchers} class
     *
     * @return <code>null</code>.
     */
    public static <T> T anyVararg() {
        return (T) reportMatcher(AnyVararg.ANY_VARARG).returnNull();
    }
    
    /**
     * Any kind object, not necessary of the given class.
     * The class argument is provided only to avoid casting.
     * <p>
     * Sometimes looks better than <code>anyObject()</code> - especially when explicit casting is required
     * <p>
     * Alias to {@link Matchers#anyObject()}
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param clazz The type to avoid casting
     * @return <code>null</code>.
     */
    public static <T> T any(Class<T> clazz) {
        return (T) reportMatcher(Any.ANY).returnFor(clazz);
    }
    
    /**
     * Any object or <code>null</code>.
     * <p>
     * Shorter alias to {@link Matchers#anyObject()}
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>null</code>.
     */
    public static <T> T any() {
        return (T) anyObject();
    }

    /**
     * Any <code>String</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return empty String ("")
     */
    public static String anyString() {
        return reportMatcher(Any.ANY).returnString();
    }
    
    /**
     * Any <code>List</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return empty List.
     */
    public static List anyList() {
        return reportMatcher(Any.ANY).returnList();
    }    
    
    /**
     * Generic friendly alias to {@link Matchers#anyList()}.
     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.
     * <p>
     * Any <code>List</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param clazz Type owned by the list to avoid casting
     * @return empty List.
     */
    public static <T> List<T> anyListOf(Class<T> clazz) {
        return (List) reportMatcher(Any.ANY).returnList();
    }    
    
    /**
     * Any <code>Set</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @return empty Set
     */
    public static Set anySet() {
        return reportMatcher(Any.ANY).returnSet();
    }
    
    /**
     * Generic friendly alias to {@link Matchers#anySet()}.
     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.
     * <p>
     * Any <code>Set</code> or <code>null</code>
     * <p>
     * This method <b>*dones't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @param clazz Type owned by the Set to avoid casting
     * @return empty Set
     */
    public static <T> Set<T> anySetOf(Class<T> clazz) {
        return (Set) reportMatcher(Any.ANY).returnSet();
    }

    /**
     * Any <code>Map</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return empty Map.
     */
    public static Map anyMap() {
        return reportMatcher(Any.ANY).returnMap();
    }

    /**
     * Generic friendly alias to {@link Matchers#anyMap()}.
     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.
     * <p>
     * Any <code>Map</code> or <code>null</code>
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @param keyClazz Type of the map key to avoid casting
     * @param valueClazz Type of the value to avoid casting
     * @return empty Map.
     */
    public static <K, V>  Map<K, V> anyMapOf(Class<K> keyClazz, Class<V> valueClazz) {
        return reportMatcher(Any.ANY).returnMap();
    }
    
    /**
     * Any <code>Collection</code> or <code>null</code>.
     * <p>
     * This method <b>*dones't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return empty Collection.
     */
    public static Collection anyCollection() {
        return reportMatcher(Any.ANY).returnList();
    }    
    
    /**
     * Generic friendly alias to {@link Matchers#anyCollection()}.
     * It's an alternative to &#064;SuppressWarnings("unchecked") to keep code clean of compiler warnings.     
     * <p>
     * Any <code>Collection</code> or <code>null</code>.
     * <p>
     * This method <b>*doesn't do any type checks*</b>, it is only there to avoid casting
     * in your code. This might however change (type checks could be added) in a
     * future major release.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param clazz Type owned by the collection to avoid casting
     * @return empty Collection.
     */
    public static <T> Collection<T> anyCollectionOf(Class<T> clazz) {
        return (Collection) reportMatcher(Any.ANY).returnList();
    }    

    /**
     * <code>Object</code> argument that implements the given class.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param <T>
     *            the accepted type.
     * @param clazz
     *            the class of the accepted type.
     * @return <code>null</code>.
     */
    public static <T> T isA(Class<T> clazz) {
        return reportMatcher(new InstanceOf(clazz)).<T>returnFor(clazz);
    }

    /**
     * <code>boolean</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static boolean eq(boolean value) {
        return reportMatcher(new Equals(value)).returnFalse();
    }

    /**
     * <code>byte</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static byte eq(byte value) {
        return reportMatcher(new Equals(value)).returnZero();
    }

    /**
     * <code>char</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static char eq(char value) {
        return reportMatcher(new Equals(value)).returnChar();
    }

    /**
     * <code>double</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static double eq(double value) {
        return reportMatcher(new Equals(value)).returnZero();
    }

    /**
     * <code>float</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static float eq(float value) {
        return reportMatcher(new Equals(value)).returnZero();
    }
    
    /**
     * <code>int</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static int eq(int value) {
        return reportMatcher(new Equals(value)).returnZero();
    }

    /**
     * <code>long</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static long eq(long value) {
        return reportMatcher(new Equals(value)).returnZero();
    }

    /**
     * <code>short</code> argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>0</code>.
     */
    public static short eq(short value) {
        return reportMatcher(new Equals(value)).returnZero();
    }

    /**
     * Object argument that is equal to the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @return <code>null</code>.
     */
    public static <T> T eq(T value) {
        return (T) reportMatcher(new Equals(value)).<T>returnFor(value);
    }

    /**
     * Object argument that is reflection-equal to the given value with support for excluding
     * selected fields from a class.
     * <p>
     * This matcher can be used when equals() is not implemented on compared objects.
     * Matcher uses java reflection API to compare fields of wanted and actual object.
     * <p>
     * Works similarly to EqualsBuilder.reflectionEquals(this, other, exlucdeFields) from
     * apache commons library.
     * <p>
     * <b>Warning</b> The equality check is shallow!
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param value
     *            the given value.
     * @param excludeFields
     *            fields to exclude, if field does not exist it is ignored.
     * @return <code>null</code>.
     */
    public static <T> T refEq(T value, String... excludeFields) {
        return reportMatcher(new ReflectionEquals(value, excludeFields)).<T>returnNull();
    }
    
    /**
     * Object argument that is the same as the given value.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param <T>
     *            the type of the object, it is passed through to prevent casts.
     * @param value
     *            the given value.
     * @return <code>null</code>.
     */
    public static <T> T same(T value) {
        return (T) reportMatcher(new Same(value)).<T>returnFor(value);
    }

    /**
     * <code>null</code> argument.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>null</code>.
     */
    public static Object isNull() {
        return reportMatcher(Null.NULL).returnNull();
    }

    /**
     * <code>null</code> argument.
     * The class argument is provided to avoid casting.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @param clazz Type to avoid casting
     * @return <code>null</code>.
     */
    public static <T> T isNull(Class<T> clazz) {
        return (T) reportMatcher(Null.NULL).returnNull();
    }

    /**
     * Not <code>null</code> argument.
     * <p>
     * alias to {@link Matchers#isNotNull()}
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>null</code>.
     */
    public static Object notNull() {
        return reportMatcher(NotNull.NOT_NULL).returnNull();
    }

    /**
     * Not <code>null</code> argument, not necessary of the given class.
     * The class argument is provided to avoid casting.
     * <p>
     * alias to {@link Matchers#isNotNull(Class)}
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @param clazz Type to avoid casting
     * @return <code>null</code>.
     */
    public static <T> T notNull(Class<T> clazz) {
        return (T) reportMatcher(NotNull.NOT_NULL).returnNull();
    }
    
    /**
     * Not <code>null</code> argument.
     * <p>
     * alias to {@link Matchers#notNull()}
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @return <code>null</code>.
     */
    public static Object isNotNull() {
        return notNull();
    }

    /**
     * Not <code>null</code> argument, not necessary of the given class.
     * The class argument is provided to avoid casting.
     * <p>
     * alias to {@link Matchers#notNull(Class)}
     * <p>
     * See examples in javadoc for {@link Matchers} class
     *
     * @param clazz Type to avoid casting
     * @return <code>null</code>.
     */
    public static <T> T isNotNull(Class<T> clazz) {
        return notNull(clazz);
    }

    /**
     * <code>String</code> argument that contains the given substring.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param substring
     *            the substring.
     * @return empty String ("").
     */
    public static String contains(String substring) {
        return reportMatcher(new Contains(substring)).returnString();
    }

    /**
     * <code>String</code> argument that matches the given regular expression.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param regex
     *            the regular expression.
     * @return empty String ("").
     */
    public static String matches(String regex) {
        return reportMatcher(new Matches(regex)).returnString();
    }

    /**
     * <code>String</code> argument that ends with the given suffix.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param suffix
     *            the suffix.
     * @return empty String ("").
     */
    public static String endsWith(String suffix) {
        return reportMatcher(new EndsWith(suffix)).returnString();
    }

    /**
     * <code>String</code> argument that starts with the given prefix.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param prefix
     *            the prefix.
     * @return empty String ("").
     */
    public static String startsWith(String prefix) {
        return reportMatcher(new StartsWith(prefix)).returnString();
    }

    /**
     * Allows creating custom argument matchers.
     * <p>
     * In rare cases when the parameter is a primitive then you <b>*must*</b> use relevant intThat(), floatThat(), etc. method.
     * This way you will avoid <code>NullPointerException</code> during auto-unboxing.
     * <p>
     * See examples in javadoc for {@link ArgumentMatcher} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>null</code>.
     */
    public static <T> T argThat(Matcher<T> matcher) {
        return reportMatcher(matcher).<T>returnNull();
    }
    
    /**
     * Allows creating custom <code>Character</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static char charThat(Matcher<Character> matcher) {
        return reportMatcher(matcher).returnChar();
    }
    
    /**
     * Allows creating custom <code>Boolean</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>false</code>.
     */
    public static boolean booleanThat(Matcher<Boolean> matcher) {
        return reportMatcher(matcher).returnFalse();
    }
    
    /**
     * Allows creating custom <code>Byte</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static byte byteThat(Matcher<Byte> matcher) {
        return reportMatcher(matcher).returnZero();
    }
    
    /**
     * Allows creating custom <code>Short</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static short shortThat(Matcher<Short> matcher) {
        return reportMatcher(matcher).returnZero();
    }
    
    /**
     * Allows creating custom <code>Integer</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static int intThat(Matcher<Integer> matcher) {
        return reportMatcher(matcher).returnZero();
    }

    /**
     * Allows creating custom <code>Long</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static long longThat(Matcher<Long> matcher) {
        return reportMatcher(matcher).returnZero();
    }
    
    /**
     * Allows creating custom <code>Float</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static float floatThat(Matcher<Float> matcher) {
        return reportMatcher(matcher).returnZero();
    }
    
    /**
     * Allows creating custom <code>Double</code> argument matchers.
     * <p>
     * See examples in javadoc for {@link Matchers} class
     * 
     * @param matcher decides whether argument matches
     * @return <code>0</code>.
     */
    public static double doubleThat(Matcher<Double> matcher) {
        return reportMatcher(matcher).returnZero();
    }

    private static HandyReturnValues reportMatcher(Matcher<?> matcher) {
        return MOCKING_PROGRESS.getArgumentMatcherStorage().reportMatcher(matcher);
    }
}
