1 package org.hamcrest.comparator; 2 3 import org.hamcrest.Description; 4 import org.hamcrest.Matcher; 5 import org.hamcrest.TypeSafeMatcher; 6 7 import java.util.Comparator; 8 9 import static java.lang.Integer.signum; 10 11 public final class ComparatorMatcherBuilder<T> { 12 13 private final Comparator<T> comparator; 14 private final boolean includeComparatorInDescription; 15 16 /** 17 * Creates a matcher factory for matchers of {@code Comparable}s. 18 * For example: 19 * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1))</pre> 20 */ 21 public static <T extends Comparable<T>> ComparatorMatcherBuilder<T> usingNaturalOrdering() { 22 return new ComparatorMatcherBuilder<T>(new Comparator<T>() { 23 @Override 24 public int compare(T o1, T o2) { 25 return o1.compareTo(o2); 26 } 27 }, false); 28 } 29 30 /** 31 * Creates a matcher factory for matchers of {@code Comparators}s of {@code T}. 32 * For example: 33 * <pre>assertThat(5, comparedBy(new Comparator<Integer>() { 34 * public int compare(Integer o1, Integer o2) { 35 * return -o1.compareTo(o2); 36 * } 37 * }).lessThan(4))</pre> 38 */ 39 public static <T> ComparatorMatcherBuilder<T> comparedBy(Comparator<T> comparator) { 40 return new ComparatorMatcherBuilder<T>(comparator, true); 41 } 42 43 private ComparatorMatcherBuilder(Comparator<T> comparator, boolean includeComparatorInDescription) { 44 this.comparator = comparator; 45 this.includeComparatorInDescription = includeComparatorInDescription; 46 } 47 48 private static final class ComparatorMatcher<T> extends TypeSafeMatcher<T> { 49 private static final int LESS_THAN = -1; 50 private static final int GREATER_THAN = 1; 51 private static final int EQUAL = 0; 52 53 private final Comparator<T> comparator; 54 private final T expected; 55 private final int minCompare; 56 private final int maxCompare; 57 private final boolean includeComparatorInDescription; 58 59 private static final String[] comparisonDescriptions = { 60 "less than", 61 "equal to", 62 "greater than" 63 }; 64 65 private ComparatorMatcher(Comparator<T> comparator, T expected, int minCompare, int maxCompare, boolean includeComparatorInDescription) { 66 this.comparator = comparator; 67 this.expected = expected; 68 this.minCompare = minCompare; 69 this.maxCompare = maxCompare; 70 this.includeComparatorInDescription = includeComparatorInDescription; 71 } 72 73 @Override 74 public boolean matchesSafely(T actual) { 75 try { 76 int compare = signum(comparator.compare(actual, expected)); 77 return minCompare <= compare && compare <= maxCompare; 78 } catch (ClassCastException e) { 79 return false; // type erasure means someone can shonk in a non-T :( 80 } 81 } 82 83 @Override 84 public void describeMismatchSafely(T actual, Description mismatchDescription) { 85 mismatchDescription.appendValue(actual).appendText(" was ") 86 .appendText(asText(comparator.compare(actual, expected))) 87 .appendText(" ").appendValue(expected); 88 if (includeComparatorInDescription) { 89 mismatchDescription.appendText(" when compared by ").appendValue(comparator); 90 } 91 } 92 93 @Override 94 public void describeTo(Description description) { 95 description.appendText("a value ").appendText(asText(minCompare)); 96 if (minCompare != maxCompare) { 97 description.appendText(" or ").appendText(asText(maxCompare)); 98 } 99 description.appendText(" ").appendValue(expected); 100 if (includeComparatorInDescription) { 101 description.appendText(" when compared by ").appendValue(comparator); 102 } 103 } 104 105 private static String asText(int comparison) { 106 return comparisonDescriptions[signum(comparison) + 1]; 107 } 108 } 109 110 /** 111 * Creates a matcher of {@code T} object that matches when the examined object is 112 * equal to the specified value, as reported by the {@code Comparator} used to 113 * create this builder. 114 * For example: 115 * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().comparesEqualTo(1))</pre> 116 * 117 * @param value the value which, when passed to the Comparator supplied to this builder, should return zero 118 */ 119 public Matcher<T> comparesEqualTo(T value) { 120 return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.EQUAL, includeComparatorInDescription); 121 } 122 123 /** 124 * Creates a matcher of {@code T} object that matches when the examined object is 125 * greater than the specified value, as reported by the {@code Comparator} used to 126 * create this builder. 127 * For example: 128 * <pre>assertThat(2, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThan(1))</pre> 129 * 130 * @param value the value which, when passed to the Comparator supplied to this builder, should return greater 131 * than zero 132 */ 133 public Matcher<T> greaterThan(T value) { 134 return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.GREATER_THAN, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription); 135 } 136 137 /** 138 * Creates a matcher of {@code T} object that matches when the examined object is 139 * greater than or equal to the specified value, as reported by the {@code Comparator} used to 140 * create this builder. 141 * For example: 142 * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThanOrEqualTo(1))</pre> 143 * 144 * @param value the value which, when passed to the Comparator supplied to this builder, should return greater 145 * than or equal to zero 146 */ 147 public Matcher<T> greaterThanOrEqualTo(T value) { 148 return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription); 149 } 150 151 /** 152 * Creates a matcher of {@code T} object that matches when the examined object is 153 * less than the specified value, as reported by the {@code Comparator} used to 154 * create this builder. 155 * For example: 156 * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThan(2))</pre> 157 * 158 * @param value the value which, when passed to the Comparator supplied to this builder, should return less 159 * than zero 160 */ 161 public Matcher<T> lessThan(T value) { 162 return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.LESS_THAN, includeComparatorInDescription); 163 } 164 165 /** 166 * Creates a matcher of {@code T} object that matches when the examined object is 167 * less than or equal to the specified value, as reported by the {@code Comparator} used to 168 * create this builder. 169 * For example: 170 * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1))</pre> 171 * 172 * @param value the value which, when passed to the Comparator supplied to this builder, should return less 173 * than or equal to zero 174 */ 175 public Matcher<T> lessThanOrEqualTo(T value) { 176 return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.EQUAL, includeComparatorInDescription); 177 } 178 } 179