<commit_before>package de.codescape.bitvunit.hamcrest;

import de.codescape.bitvunit.rule.Rule;
import de.codescape.bitvunit.rule.Violations;
import de.codescape.bitvunit.ruleset.BasicRuleSet;
import de.codescape.bitvunit.ruleset.RuleSet;
import de.codescape.bitvunit.util.Assert;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import static de.codescape.bitvunit.util.html.HtmlPageUtil.toHtmlPage;

/**
 * Hamcrest matcher to be used to run accessibility checks against a single {@link Rule} or a {@link RuleSet}.
 * <p/>
 * <b>Usage examples:</b>
 * <pre><code>
 * assertThat(supportedType, is(compliantTo(ruleSet)));
 * assertThat(supportedType, is(compliantTo(rule)));
 * </code></pre>
 * <p/>
 * Have a look at {@link de.codescape.bitvunit.util.html.HtmlPageUtil} methods for supported types.
 *
 * @param <T> one of the supported types
 * @author <NAME>
 * @see de.codescape.bitvunit.util.html.HtmlPageUtil
 * @since 0.4
 */
public class ComplianceMatcher<T> extends TypeSafeMatcher<T> {

    private final RuleSet ruleSet;
    private Violations violations;

    /**
     * Creates a new {@link ComplianceMatcher} against the provided {@link RuleSet}.
     *
     * @param ruleSet the {@link RuleSet} to be used
     */
    public ComplianceMatcher(RuleSet ruleSet) {
        this.ruleSet = ruleSet;
    }

    @Override
    protected boolean matchesSafely(T item) {
        violations = ruleSet.applyTo(toHtmlPage(item));
        return !violations.hasViolations();
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("compliant to ").appendText(ruleSet.toString());
    }

    @Override
    protected void describeMismatchSafely(T item, Description mismatchDescription) {
        Assert.notNull("Call matches method before.",violations);
        mismatchDescription.appendText(violations.toString());
    }

    /**
     * Returns a {@link ComplianceMatcher} that checks one of the supported types (see JavaDoc at class level) against
     * the given {@link RuleSet}.
     *
     * @param ruleSet {@link RuleSet} that should be used
     * @param <T>     supported types are contained in JavaDoc at class level
     * @return {@link ComplianceMatcher} to check against the {@link RuleSet}
     */
    @Factory
    public static <T> Matcher<T> compliantTo(RuleSet ruleSet) {
        return new ComplianceMatcher<T>(ruleSet);
    }

    /**
     * Returns a {@link ComplianceMatcher} that checks one of the supported types (see JavaDoc at class level) against<commit_msg>better error message<commit_after>package de.codescape.bitvunit.hamcrest;

import de.codescape.bitvunit.rule.Rule;
import de.codescape.bitvunit.rule.Violations;
import de.codescape.bitvunit.ruleset.BasicRuleSet;
import de.codescape.bitvunit.ruleset.RuleSet;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import static de.codescape.bitvunit.util.Assert.notNull;
import static de.codescape.bitvunit.util.html.HtmlPageUtil.toHtmlPage;

/**
 * Hamcrest matcher to be used to run accessibility checks against a single {@link Rule} or a {@link RuleSet}.
 * <p/>
 * <b>Usage examples:</b>
 * <pre><code>
 * assertThat(supportedType, is(compliantTo(ruleSet)));
 * assertThat(supportedType, is(compliantTo(rule)));
 * </code></pre>
 * <p/>
 * Have a look at {@link de.codescape.bitvunit.util.html.HtmlPageUtil} methods for supported types.
 *
 * @param <T> one of the supported types
 * @author <NAME>
 * @see de.codescape.bitvunit.util.html.HtmlPageUtil
 * @since 0.4
 */
public class ComplianceMatcher<T> extends TypeSafeMatcher<T> {

    private final RuleSet ruleSet;
    private Violations violations;

    /**
     * Creates a new {@link ComplianceMatcher} against the provided {@link RuleSet}.
     *
     * @param ruleSet the {@link RuleSet} to be used
     */
    public ComplianceMatcher(RuleSet ruleSet) {
        this.ruleSet = ruleSet;
    }

    @Override
    protected boolean matchesSafely(T item) {
        violations = ruleSet.applyTo(toHtmlPage(item));
        return !violations.hasViolations();
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("compliant to ").appendText(ruleSet.toString());
    }

    @Override
    protected void describeMismatchSafely(T item, Description mismatchDescription) {
        notNull("Method may only be called after preceding call to matches method.", violations);
        mismatchDescription.appendText(violations.toString());
    }

    /**
     * Returns a {@link ComplianceMatcher} that checks one of the supported types (see JavaDoc at class level) against
     * the given {@link RuleSet}.
     *
     * @param ruleSet {@link RuleSet} that should be used
     * @param <T>     supported types are contained in JavaDoc at class level
     * @return {@link ComplianceMatcher} to check against the {@link RuleSet}
     */
    @Factory
    public static <T> Matcher<T> compliantTo(RuleSet ruleSet) {
        return new ComplianceMatcher<T>(ruleSet);
    }

    /**
     * Returns a {@link ComplianceMatcher} that checks one of the supported types (see JavaDoc at class level) against
{'fraction_non_alphanumeric': 0.10711582134746404, 'fraction_numerical': 0.000757002271006813, 'mean_word_length': 3.735663082437276, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6747080', 'n_tokens_mistral': 1617, 'n_tokens_neox': 1568, 'n_words': 438}