001 /* Copyright (c) 2000-2006 hamcrest.org 002 */ 003 package org.hamcrest.core; 004 005 import org.hamcrest.BaseMatcher; 006 import org.hamcrest.Description; 007 import org.hamcrest.Factory; 008 import org.hamcrest.Matcher; 009 010 import java.lang.reflect.Array; 011 012 013 /** 014 * Is the value equal to another value, as tested by the 015 * {@link java.lang.Object#equals} invokedMethod? 016 */ 017 public class IsEqual<T> extends BaseMatcher<T> { 018 private final Object expectedValue; 019 020 public IsEqual(T equalArg) { 021 expectedValue = equalArg; 022 } 023 024 @Override 025 public boolean matches(Object actualValue) { 026 return areEqual(actualValue, expectedValue); 027 } 028 029 @Override 030 public void describeTo(Description description) { 031 description.appendValue(expectedValue); 032 } 033 034 private static boolean areEqual(Object actual, Object expected) { 035 if (actual == null) { 036 return expected == null; 037 } 038 039 if (expected != null && isArray(actual)) { 040 return isArray(expected) && areArraysEqual(actual, expected); 041 } 042 043 return actual.equals(expected); 044 } 045 046 private static boolean areArraysEqual(Object actualArray, Object expectedArray) { 047 return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray); 048 } 049 050 private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) { 051 return Array.getLength(actualArray) == Array.getLength(expectedArray); 052 } 053 054 private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray) { 055 for (int i = 0; i < Array.getLength(actualArray); i++) { 056 if (!areEqual(Array.get(actualArray, i), Array.get(expectedArray, i))) { 057 return false; 058 } 059 } 060 return true; 061 } 062 063 private static boolean isArray(Object o) { 064 return o.getClass().isArray(); 065 } 066 067 /** 068 * Creates a matcher that matches when the examined object is logically equal to the specified 069 * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on 070 * the <b>examined</b> object. 071 * 072 * <p>If the specified operand is <code>null</code> then the created matcher will only match if 073 * the examined object's <code>equals</code> method returns <code>true</code> when passed a 074 * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the 075 * examined object itself is <code>null</code>, in which case the matcher will return a positive 076 * match.</p> 077 * 078 * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby 079 * it will match if both the operand and the examined object are arrays of the same length and 080 * contain items that are equal to each other (according to the above rules) <b>in the same 081 * indexes</b>.</p> 082 * <p/> 083 * For example: 084 * <pre> 085 * assertThat("foo", equalTo("foo")); 086 * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"})); 087 * </pre> 088 * 089 */ 090 @Factory 091 public static <T> Matcher<T> equalTo(T operand) { 092 return new IsEqual<T>(operand); 093 } 094 }