Home | History | Annotate | Download | only in text
      1 package org.hamcrest.text;
      2 
      3 import org.hamcrest.Description;
      4 import org.hamcrest.Matcher;
      5 import org.hamcrest.TypeSafeMatcher;
      6 
      7 import static java.lang.Character.isWhitespace;
      8 
      9 /**
     10  * Tests if a string is equal to another string, ignoring any changes in whitespace.
     11  */
     12 public class IsEqualIgnoringWhiteSpace extends TypeSafeMatcher<String> {
     13 
     14     // TODO: Replace String with CharSequence to allow for easy interoperability between
     15     //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
     16 
     17     private final String string;
     18 
     19     public IsEqualIgnoringWhiteSpace(String string) {
     20         if (string == null) {
     21             throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");
     22         }
     23         this.string = string;
     24     }
     25 
     26     @Override
     27     public boolean matchesSafely(String item) {
     28         return stripSpace(string).equalsIgnoreCase(stripSpace(item));
     29     }
     30 
     31     @Override
     32     public void describeMismatchSafely(String item, Description mismatchDescription) {
     33       mismatchDescription.appendText("was  ").appendText(stripSpace(item));
     34     }
     35 
     36     @Override
     37     public void describeTo(Description description) {
     38         description.appendText("equalToIgnoringWhiteSpace(")
     39                 .appendValue(string)
     40                 .appendText(")");
     41     }
     42 
     43     public String stripSpace(String toBeStripped) {
     44         final StringBuilder result = new StringBuilder();
     45         boolean lastWasSpace = true;
     46         for (int i = 0; i < toBeStripped.length(); i++) {
     47             char c = toBeStripped.charAt(i);
     48             if (isWhitespace(c)) {
     49                 if (!lastWasSpace) {
     50                     result.append(' ');
     51                 }
     52                 lastWasSpace = true;
     53             } else {
     54                 result.append(c);
     55                 lastWasSpace = false;
     56             }
     57         }
     58         return result.toString().trim();
     59     }
     60 
     61     /**
     62      * Creates a matcher of {@link String} that matches when the examined string is equal to
     63      * the specified expectedString, when whitespace differences are (mostly) ignored.  To be
     64      * exact, the following whitespace rules are applied:
     65      * <ul>
     66      *   <li>all leading and trailing whitespace of both the expectedString and the examined string are ignored</li>
     67      *   <li>any remaining whitespace, appearing within either string, is collapsed to a single space before comparison</li>
     68      * </ul>
     69      * For example:
     70      * <pre>assertThat("   my\tfoo  bar ", equalToIgnoringWhiteSpace(" my  foo bar"))</pre>
     71      *
     72      * @param expectedString
     73      *     the expected value of matched strings
     74      */
     75     public static Matcher<String> equalToIgnoringWhiteSpace(String expectedString) {
     76         return new IsEqualIgnoringWhiteSpace(expectedString);
     77     }
     78 
     79 }
     80