1package org.hamcrest.core; 2 3import org.hamcrest.BaseMatcher; 4import org.hamcrest.Description; 5import org.hamcrest.Matcher; 6 7import java.lang.reflect.Array; 8 9 10/** 11 * Is the value equal to another value, as tested by the 12 * {@link java.lang.Object#equals} invokedMethod? 13 */ 14public class IsEqual<T> extends BaseMatcher<T> { 15 private final Object expectedValue; 16 17 public IsEqual(T equalArg) { 18 expectedValue = equalArg; 19 } 20 21 @Override 22 public boolean matches(Object actualValue) { 23 return areEqual(actualValue, expectedValue); 24 } 25 26 @Override 27 public void describeTo(Description description) { 28 description.appendValue(expectedValue); 29 } 30 31 private static boolean areEqual(Object actual, Object expected) { 32 if (actual == null) { 33 return expected == null; 34 } 35 36 if (expected != null && isArray(actual)) { 37 return isArray(expected) && areArraysEqual(actual, expected); 38 } 39 40 return actual.equals(expected); 41 } 42 43 private static boolean areArraysEqual(Object actualArray, Object expectedArray) { 44 return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray); 45 } 46 47 private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) { 48 return Array.getLength(actualArray) == Array.getLength(expectedArray); 49 } 50 51 private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray) { 52 for (int i = 0; i < Array.getLength(actualArray); i++) { 53 if (!areEqual(Array.get(actualArray, i), Array.get(expectedArray, i))) { 54 return false; 55 } 56 } 57 return true; 58 } 59 60 private static boolean isArray(Object o) { 61 return o.getClass().isArray(); 62 } 63 64 /** 65 * Creates a matcher that matches when the examined object is logically equal to the specified 66 * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on 67 * the <b>examined</b> object. 68 * 69 * <p>If the specified operand is <code>null</code> then the created matcher will only match if 70 * the examined object's <code>equals</code> method returns <code>true</code> when passed a 71 * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the 72 * examined object itself is <code>null</code>, in which case the matcher will return a positive 73 * match.</p> 74 * 75 * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby 76 * it will match if both the operand and the examined object are arrays of the same length and 77 * contain items that are equal to each other (according to the above rules) <b>in the same 78 * indexes</b>.</p> 79 * For example: 80 * <pre> 81 * assertThat("foo", equalTo("foo")); 82 * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"})); 83 * </pre> 84 * 85 */ 86 public static <T> Matcher<T> equalTo(T operand) { 87 return new IsEqual<T>(operand); 88 } 89 90 /** 91 * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being 92 * compared to be of the same static type. 93 */ 94 public static Matcher<Object> equalToObject(Object operand) { 95 return new IsEqual<Object>(operand); 96 } 97} 98