package com.jmatch;

import org.apache.commons.lang3.StringUtils;

/**
 * Uses single letters to represent variables in patterns.
 */
public class SingleVariablePatternMatcher implements Matcher {
    private final String pattern;

    /**
     * Constructs a new matcher with the given pattern. The pattern should consist of single letters to represent
     * variables in the pattern. E.g. "abba" is composed of the variables 'a' and 'b'.
     *
     * @param pattern the given pattern
     */
    public SingleVariablePatternMatcher(String pattern) {
        this.pattern = pattern;
    }

    @Override
    public boolean matches(String input) {
        return matchRemaining(pattern, input);
    }

    private boolean matchRemaining(String pattern, String input) {
        // If there is no more of the pattern left to match we need an empty input String to have matched the
        // original input.
        if (pattern.isEmpty()) {
            return input.isEmpty();
        }

        // Pick the first letter in the pattern as our current variable
        final String variable = Character.toString(pattern.charAt(0));
        // Count the number of times the variable occurs in the pattern
        final int numberOfVariableOccurrencesInPattern = StringUtils.countMatches(pattern, variable);

        // Greedily attempt to assign a value to the current variable
        for (int endIndex = input.length(); endIndex > 0; endIndex--) {
            final String variableAssignment = input.substring(0, endIndex);

            // Check to make sure that the proper number of occurrences of the assigned value exist in the input
            final int numberOfAssignmentOccurrencesInInput = StringUtils.countMatches(input, variableAssignment);
            if (numberOfAssignmentOccurrencesInInput == numberOfVariableOccurrencesInPattern) {
                // Check to see if the assignment leads to a valid match
                final boolean matchSuccessful = matchRemaining(pattern.replaceAll(variable, ""), input.replaceAll
                        (variableAssignment, ""));

                if (matchSuccessful) {
                    return true;
                }
            }
        }

        return false;
    }
}

@@ -67,17 +67,64 @@
 %0A/**%0A * 
-U
+%7B@link com.jmatch.Matcher%7D implementation that u
 ses sing
@@ -170,16 +170,258 @@
 tterns.%0A
+ * %3Cp/%3E%0A * The pattern matching for this class is non-strict such that different variables are allowed to share the same value.%0A * For example, the pattern %7B@code %22xyyx%22%7D would match %7B@code %22aaaa%22%7D by assigning %7B@code %22a%22%7D to both variables.%0A
  */%0Apubl
@@ -677,15 +677,23 @@
 E.g.
+ %7B@code
  %22abba%22
+%7D
  is 
@@ -722,19 +722,35 @@
 les 
+%7B@code 
 'a'
+%7D
  and 
+%7B@code 
 'b'
+%7D
 .%0A  

Improve documentation of class