/*
 * 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>*don'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 MockingProgress mockingProgress = new ThreadSafeMockingProgress();

    /**
     * Any <code>boolean</code>, <code>Boolean</code> or <code>null</code>.
     * <p>
     * This method <b>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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>*don'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 mockingProgress.getArgumentMatcherStorage().reportMatcher(matcher);
    }
}
