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 }