package com.mistraltech.smog;

import org.hamcrest.Description;
import org.hamcrest.Matcher;

/**
 * A helper class that interposes in the invocation of the matches() method of multiple matchers and
 * coordinates the building of a cumulative mismatch description for those that fail.
 */
public final class MatchAccumulator {
    public static final String    MISMATCH_JOINING_STRING = "\n     and: ";

    private boolean matches = true;
    private Description mismatchDescription;

    private MatchAccumulator(Description mismatchDescription, boolean currentlyMatching) {
        this.mismatchDescription = mismatchDescription;
        this.matches = currentlyMatching;
    }

    private MatchAccumulator(Description mismatchDescription) {
        this(mismatchDescription, true);
    }

    /**
     * Factory method for use by non-inheriting matchers.
     *
     * @param mismatchDescription the description object used for recording the mismatch description
     * @return a new MatchAccumulator instance
     */
    public static MatchAccumulator matchAccumulator(Description mismatchDescription) {
        return new MatchAccumulator(mismatchDescription);
    }

    /**
     * Factory method for use by non-inheriting matchers.
     *
     * @param mismatchDescription the description object used for recording the mismatch description
     * @param currentlyMatching a flag to indicate if, in the case that this instance is participating as
     * a sub-scope of a larger matching process, the larger matching process is already failing.
     * @return a new MatchAccumulator instance
     */
    public static MatchAccumulator matchAccumulator(Description mismatchDescription, boolean currentlyMatching) {
        return new MatchAccumulator(mismatchDescription, currentlyMatching);
    }

    public <P> MatchAccumulator matches(Matcher<? super P> matcher, P item) {
        boolean localMatches = matcher.matches(item);

        if (!localMatches) {
            if (!matches) // i.e. this is not the first failure
            {
                mismatchDescription.appendText(MISMATCH_JOINING_STRING);
            }

            matcher.describeMismatch(item, mismatchDescription);
            matches = false;
        }

        return this;
    }

    /**
     * The cumulative matches result.
     *
     * @return true if this instance was constructed with currentlyMatching equal to or
     * defaulted to true and all subsequent matches() invocations were successful; false otherwise.
     */
    public boolean result() {
        return matches;
    }
}

@@ -1201,36 +1201,32 @@
 thod for use by 
-non-
 inheriting match
@@ -1220,32 +1220,328 @@
 eriting matchers
+ - that is, matchers that inherit some of their%0A     * properties from a superclass.%0A     * %3Cp/%3E%0A     * In this case it is desirable to construct the MatchAccumulator with%0A     * an indicator of whether preceding property matches (performed by the matcher superclass) have%0A     * passed or failed
 .%0A     *%0A     * 
@@ -2086,24 +2086,462 @@
 ng);%0A    %7D%0A%0A
+    /**%0A     * Invokes the %7B@link Matcher#matches(java.lang.Object)%7D method on the supplied matcher against a given target object%0A     * and appends relevant text to the mismatch description if the match fails.%0A     *%0A     * @param matcher the matcher to invoke%0A     * @param item the target object to be matched%0A     * @param %3CP%3E the type of item to be matched%0A     * @return this instance, to allow multiple calls to be chained%0A     */%0A
     public %3C

Correct and improve javadoc comments in MatchAccumulator.