1 package org.hamcrest; 2 3 import org.hamcrest.internal.ReflectiveTypeFinder; 4 5 /** 6 * Supporting class for matching a feature of an object. Implement <code>featureValueOf()</code> 7 * in a subclass to pull out the feature to be matched against. 8 * 9 * @param <T> The type of the object to be matched 10 * @param <U> The type of the feature to be matched 11 */ 12 public abstract class FeatureMatcher<T, U> extends TypeSafeDiagnosingMatcher<T> { 13 private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("featureValueOf", 1, 0); 14 private final Matcher<? super U> subMatcher; 15 private final String featureDescription; 16 private final String featureName; 17 18 /** 19 * Constructor 20 * @param subMatcher The matcher to apply to the feature 21 * @param featureDescription Descriptive text to use in describeTo 22 * @param featureName Identifying text for mismatch message 23 */ 24 public FeatureMatcher(Matcher<? super U> subMatcher, String featureDescription, String featureName) { 25 super(TYPE_FINDER); 26 this.subMatcher = subMatcher; 27 this.featureDescription = featureDescription; 28 this.featureName = featureName; 29 } 30 31 /** 32 * Implement this to extract the interesting feature. 33 * @param actual the target object 34 * @return the feature to be matched 35 */ 36 protected abstract U featureValueOf(T actual); 37 38 @Override 39 protected boolean matchesSafely(T actual, Description mismatch) { 40 final U featureValue = featureValueOf(actual); 41 if (!subMatcher.matches(featureValue)) { 42 mismatch.appendText(featureName).appendText(" "); 43 subMatcher.describeMismatch(featureValue, mismatch); 44 return false; 45 } 46 return true; 47 } 48 49 @Override 50 public final void describeTo(Description description) { 51 description.appendText(featureDescription).appendText(" ") 52 .appendDescriptionOf(subMatcher); 53 } 54 } 55