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 }