001 package org.hamcrest; 002 003 /** 004 * A Condition implements part of a multi-step match. We sometimes need to write matchers 005 * that have a sequence of steps, where each step depends on the result of the previous 006 * step and we can stop processing as soon as a step fails. These classes provide 007 * infrastructure for writing such a sequence. 008 * 009 * Based on https://github.com/npryce/maybe-java 010 * @author Steve Freeman 2012 http://www.hamcrest.com 011 */ 012 013 public abstract class Condition<T> { 014 public static final NotMatched<Object> NOT_MATCHED = new NotMatched<Object>(); 015 016 public interface Step<I, O> { 017 Condition<O> apply(I value, Description mismatch); 018 } 019 020 private Condition() { } 021 022 public abstract boolean matching(Matcher<T> match, String message); 023 public abstract <U> Condition<U> and(Step<? super T, U> mapping); 024 025 public final boolean matching(Matcher<T> match) { return matching(match, ""); } 026 public final <U> Condition<U> then(Step<? super T, U> mapping) { return and(mapping); } 027 028 @SuppressWarnings("unchecked") 029 public static <T> Condition<T> notMatched() { 030 return (Condition<T>) NOT_MATCHED; 031 } 032 033 public static <T> Condition<T> matched(final T theValue, final Description mismatch) { 034 return new Matched<T>(theValue, mismatch); 035 } 036 037 private static final class Matched<T> extends Condition<T> { 038 private final T theValue; 039 private final Description mismatch; 040 041 private Matched(T theValue, Description mismatch) { 042 this.theValue = theValue; 043 this.mismatch = mismatch; 044 } 045 046 @Override 047 public boolean matching(Matcher<T> matcher, String message) { 048 if (matcher.matches(theValue)) { 049 return true; 050 } 051 mismatch.appendText(message); 052 matcher.describeMismatch(theValue, mismatch); 053 return false; 054 } 055 056 @Override 057 public <U> Condition<U> and(Step<? super T, U> next) { 058 return next.apply(theValue, mismatch); 059 } 060 } 061 062 private static final class NotMatched<T> extends Condition<T> { 063 @Override public boolean matching(Matcher<T> match, String message) { return false; } 064 065 @Override public <U> Condition<U> and(Step<? super T, U> mapping) { 066 return notMatched(); 067 } 068 } 069 }