Home | History | Annotate | Download | only in core
      1 package org.hamcrest.core;
      2 
      3 import org.hamcrest.BaseMatcher;
      4 import org.hamcrest.Description;
      5 import org.hamcrest.Matcher;
      6 
      7 import java.util.regex.Pattern;
      8 
      9 import static java.lang.Integer.parseInt;
     10 
     11 /**
     12  * Provides a custom description to another matcher.
     13  */
     14 public class DescribedAs<T> extends BaseMatcher<T> {
     15     private final String descriptionTemplate;
     16     private final Matcher<T> matcher;
     17     private final Object[] values;
     18 
     19     private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)");
     20 
     21     public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) {
     22         this.descriptionTemplate = descriptionTemplate;
     23         this.matcher = matcher;
     24         this.values = values.clone();
     25     }
     26 
     27     @Override
     28     public boolean matches(Object o) {
     29         return matcher.matches(o);
     30     }
     31 
     32     @Override
     33     public void describeTo(Description description) {
     34         java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate);
     35 
     36         int textStart = 0;
     37         while (arg.find()) {
     38             description.appendText(descriptionTemplate.substring(textStart, arg.start()));
     39             description.appendValue(values[parseInt(arg.group(1))]);
     40             textStart = arg.end();
     41         }
     42 
     43         if (textStart < descriptionTemplate.length()) {
     44             description.appendText(descriptionTemplate.substring(textStart));
     45         }
     46     }
     47 
     48     @Override
     49     public void describeMismatch(Object item, Description description) {
     50         matcher.describeMismatch(item, description);
     51     }
     52 
     53     /**
     54      * Wraps an existing matcher, overriding its description with that specified.  All other functions are
     55      * delegated to the decorated matcher, including its mismatch description.
     56      * For example:
     57      * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre>
     58      *
     59      * @param description
     60      *     the new description for the wrapped matcher
     61      * @param matcher
     62      *     the matcher to wrap
     63      * @param values
     64      *     optional values to insert into the tokenised description
     65      */
     66     public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {
     67         return new DescribedAs<T>(description, matcher, values);
     68     }
     69 }
     70