1package org.hamcrest.text;
2
3import org.hamcrest.Description;
4import org.hamcrest.Matcher;
5import org.hamcrest.TypeSafeMatcher;
6
7import java.util.Arrays;
8
9public class StringContainsInOrder extends TypeSafeMatcher<String> {
10    private final Iterable<String> substrings;
11
12    public StringContainsInOrder(Iterable<String> substrings) {
13        this.substrings = substrings;
14    }
15
16    @Override
17    public boolean matchesSafely(String s) {
18        int fromIndex = 0;
19
20        for (String substring : substrings) {
21            fromIndex = s.indexOf(substring, fromIndex);
22            if (fromIndex == -1) {
23                return false;
24            }
25        }
26
27        return true;
28    }
29
30    @Override
31    public void describeMismatchSafely(String item, Description mismatchDescription) {
32        mismatchDescription.appendText("was \"").appendText(item).appendText("\"");
33    }
34
35    @Override
36    public void describeTo(Description description) {
37        description.appendText("a string containing ")
38                   .appendValueList("", ", ", "", substrings)
39                   .appendText(" in order");
40    }
41
42    /**
43     * Creates a matcher of {@link String} that matches when the examined string contains all of
44     * the specified substrings, considering the order of their appearance.
45     * For example:
46     * <pre>assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))</pre>
47     * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
48     *
49     * @param substrings
50     *     the substrings that must be contained within matching strings
51     */
52    public static Matcher<String> stringContainsInOrder(Iterable<String> substrings) {
53        return new StringContainsInOrder(substrings);
54    }
55
56    /**
57     * Creates a matcher of {@link String} that matches when the examined string contains all of
58     * the specified substrings, considering the order of their appearance.
59     * For example:
60     * <pre>assertThat("myfoobarbaz", stringContainsInOrder("bar", "foo"))</pre>
61     * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
62     *
63     * @param substrings
64     *     the substrings that must be contained within matching strings
65     */
66    public static Matcher<String> stringContainsInOrder(String... substrings) {
67        return new StringContainsInOrder(Arrays.asList(substrings));
68    }
69}
70