    001    /*  Copyright (c) 2000-2006 hamcrest.org
    002     */
    003    package org.hamcrest.core;
    004
    005    import org.hamcrest.Description;
    006    import org.hamcrest.DiagnosingMatcher;
    007    import org.hamcrest.Factory;
    008    import org.hamcrest.Matcher;
    009
    010
    011    /**
    012     * Tests whether the value is an instance of a class.
    013     * Classes of basic types will be converted to the relevant "Object" classes
    014     */
    015    public class IsInstanceOf extends DiagnosingMatcher<Object> {
    016        private final Class<?> expectedClass;
    017        private final Class<?> matchableClass;
    018
    019        /**
    020         * Creates a new instance of IsInstanceOf
    021         *
    022         * @param expectedClass The predicate evaluates to true for instances of this class
    023         *                 or one of its subclasses.
    024         */
    025        public IsInstanceOf(Class<?> expectedClass) {
    026            this.expectedClass = expectedClass;
    027            this.matchableClass = matchableClass(expectedClass);
    028        }
    029
    030        private static Class<?> matchableClass(Class<?> expectedClass) {
    031          if (boolean.class.equals(expectedClass)) return Boolean.class;
    032          if (byte.class.equals(expectedClass)) return Byte.class;
    033          if (char.class.equals(expectedClass)) return Character.class;
    034          if (double.class.equals(expectedClass)) return Double.class;
    035          if (float.class.equals(expectedClass)) return Float.class;
    036          if (int.class.equals(expectedClass)) return Integer.class;
    037          if (long.class.equals(expectedClass)) return Long.class;
    038          if (short.class.equals(expectedClass)) return Short.class;
    039          return expectedClass;
    040        }
    041
    042        @Override
    043        protected boolean matches(Object item, Description mismatch) {
    044          if (null == item) {
    045            mismatch.appendText("null");
    046            return false;
    047          }
    048
    049          if (!matchableClass.isInstance(item)) {
    050            mismatch.appendValue(item).appendText(" is a " + item.getClass().getName());
    051            return false;
    052          }
    053
    054          return true;
    055        }
    056
    057        @Override
    058        public void describeTo(Description description) {
    059            description.appendText("an instance of ").appendText(expectedClass.getName());
    060        }
    061
    062        /**
    063         * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
    064         * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
    065         * the examined object.
    066         *
    067         * <p>The created matcher assumes no relationship between specified type and the examined object.</p>
    068         * <p/>
    069         * For example:
    070         * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre>
    071         *
    072         */
    073        @SuppressWarnings("unchecked")
    074        @Factory
    075        public static <T> Matcher<T> instanceOf(Class<?> type) {
    076            return (Matcher<T>) new IsInstanceOf(type);
    077        }
    078
    079        /**
    080         * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
    081         * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
    082         * the examined object.
    083         *
    084         * <p>The created matcher forces a relationship between specified type and the examined object, and should be
    085         * used when it is necessary to make generics conform, for example in the JMock clause
    086         * <code>with(any(Thing.class))</code></p>
    087         * <p/>
    088         * For example:
    089         * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre>
    090         *
    091         */
    092        @SuppressWarnings("unchecked")
    093        @Factory
    094        public static <T> Matcher<T> any(Class<T> type) {
    095            return (Matcher<T>) new IsInstanceOf(type);
    096        }
    097
    098    }