1package org.hamcrest.number;
2
3import org.hamcrest.Description;
4import org.hamcrest.Matcher;
5import org.hamcrest.TypeSafeMatcher;
6
7import static java.lang.Math.abs;
8
9
10/**
11 * Is the value a number equal to a value within some range of
12 * acceptable error?
13 */
14public class IsCloseTo extends TypeSafeMatcher<Double> {
15    private final double delta;
16    private final double value;
17
18    public IsCloseTo(double value, double error) {
19        this.delta = error;
20        this.value = value;
21    }
22
23    @Override
24    public boolean matchesSafely(Double item) {
25        return actualDelta(item) <= 0.0;
26    }
27
28    @Override
29    public void describeMismatchSafely(Double item, Description mismatchDescription) {
30      mismatchDescription.appendValue(item)
31                         .appendText(" differed by ")
32                         .appendValue(actualDelta(item))
33                         .appendText(" more than delta ")
34                         .appendValue(delta);
35    }
36
37    @Override
38    public void describeTo(Description description) {
39        description.appendText("a numeric value within ")
40                .appendValue(delta)
41                .appendText(" of ")
42                .appendValue(value);
43    }
44
45    private double actualDelta(Double item) {
46      return abs(item - value) - delta;
47    }
48
49    /**
50     * Creates a matcher of {@link Double}s that matches when an examined double is equal
51     * to the specified <code>operand</code>, within a range of +/- <code>error</code>.
52     * For example:
53     * <pre>assertThat(1.03, is(closeTo(1.0, 0.03)))</pre>
54     *
55     * @param operand
56     *     the expected value of matching doubles
57     * @param error
58     *     the delta (+/-) within which matches will be allowed
59     */
60    public static Matcher<Double> closeTo(double operand, double error) {
61        return new IsCloseTo(operand, error);
62    }
63}
64