1/*  Copyright (c) 2000-2006 hamcrest.org
2 */
3package org.hamcrest.core;
4
5import java.util.regex.Pattern;
6
7import org.hamcrest.Description;
8import org.hamcrest.Matcher;
9import org.hamcrest.Factory;
10import org.hamcrest.BaseMatcher;
11
12/**
13 * Provides a custom description to another matcher.
14 */
15public class DescribedAs<T> extends BaseMatcher<T> {
16    private final String descriptionTemplate;
17    private final Matcher<T> matcher;
18    private final Object[] values;
19
20    private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)");
21
22    public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) {
23        this.descriptionTemplate = descriptionTemplate;
24        this.matcher = matcher;
25        this.values = values.clone();
26    }
27
28    public boolean matches(Object o) {
29        return matcher.matches(o);
30    }
31
32    public void describeTo(Description description) {
33        java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate);
34
35        int textStart = 0;
36        while (arg.find()) {
37            description.appendText(descriptionTemplate.substring(textStart, arg.start()));
38            int argIndex = Integer.parseInt(arg.group(1));
39            description.appendValue(values[argIndex]);
40            textStart = arg.end();
41        }
42
43        if (textStart < descriptionTemplate.length()) {
44            description.appendText(descriptionTemplate.substring(textStart));
45        }
46    }
47
48    /**
49     * Wraps an existing matcher and overrides the description when it fails.
50     */
51    @Factory
52    public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {
53        return new DescribedAs<T>(description, matcher, values);
54    }
55}
56