1/*  Copyright (c) 2000-2006 hamcrest.org
2 */
3package org.hamcrest.core;
4
5import org.hamcrest.Description;
6import org.hamcrest.Matcher;
7import org.hamcrest.Factory;
8import org.hamcrest.BaseMatcher;
9
10import java.lang.reflect.Array;
11
12
13/**
14 * Is the value equal to another value, as tested by the
15 * {@link java.lang.Object#equals} invokedMethod?
16 */
17public class IsEqual<T> extends BaseMatcher<T> {
18    private final Object object;
19
20    public IsEqual(T equalArg) {
21        object = equalArg;
22    }
23
24    public boolean matches(Object arg) {
25        return areEqual(object, arg);
26    }
27
28    public void describeTo(Description description) {
29        description.appendValue(object);
30    }
31
32    private static boolean areEqual(Object o1, Object o2) {
33        if (o1 == null || o2 == null) {
34            return o1 == null && o2 == null;
35        } else if (isArray(o1)) {
36            return isArray(o2) && areArraysEqual(o1, o2);
37        } else {
38            return o1.equals(o2);
39        }
40    }
41
42    private static boolean areArraysEqual(Object o1, Object o2) {
43        return areArrayLengthsEqual(o1, o2)
44                && areArrayElementsEqual(o1, o2);
45    }
46
47    private static boolean areArrayLengthsEqual(Object o1, Object o2) {
48        return Array.getLength(o1) == Array.getLength(o2);
49    }
50
51    private static boolean areArrayElementsEqual(Object o1, Object o2) {
52        for (int i = 0; i < Array.getLength(o1); i++) {
53            if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false;
54        }
55        return true;
56    }
57
58    private static boolean isArray(Object o) {
59        return o.getClass().isArray();
60    }
61
62    /**
63     * Is the value equal to another value, as tested by the
64     * {@link java.lang.Object#equals} invokedMethod?
65     */
66    @Factory
67    public static <T> Matcher<T> equalTo(T operand) {
68        return new IsEqual<T>(operand);
69    }
70
71}
72