/**
 * Copyright 2009 Wilfred Springer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.flotsam.xeger;

import dk.brics.automaton.Automaton;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.State;
import dk.brics.automaton.Transition;

import java.util.List;
import java.util.Random;

/**
 * An object that will generate text from a regular expression. In a way, it's the opposite of a regular expression
 * matcher: an instance of this class will produce text that is guaranteed to match the regular expression passed in.
 */
public class Xeger {

    private final Automaton automaton;
    private final Random random;

    /**
     * Constructs a new instance, accepting the regular expression and the randomizer.
     *
     * @param regex  The regular expression. (Not <code>null</code>.)
     * @param random The object that will randomize the way the String is generated. (Not <code>null</code>.)
     * @throws IllegalArgumentException If the regular expression is invalid.
     */
    public Xeger(String regex, Random random) {
        assert regex != null;
        assert random != null;
        this.automaton = new RegExp(regex).toAutomaton();
        this.random = random;
    }

    /**
     * As {@link nl.flotsam.xeger.Xeger#Xeger(String, java.util.Random)}, creating a {@link java.util.Random} instance
     * implicityly.
     */
    public Xeger(String regex) {
        this(regex, new Random());
    }

    /**
     * Generates a random String that is guaranteed to match the regular expression passed to the constructor.
     */
    public String generate() {
        StringBuilder builder = new StringBuilder();
        generate(builder, automaton.getInitialState());
        return builder.toString();
    }

    private void generate(StringBuilder builder, State state) {
        List<Transition> transitions = state.getSortedTransitions(true);
        if (transitions.size() == 0) {
            assert state.isAccept();
            return;
        }
        int nroptions = state.isAccept() ? transitions.size() : transitions.size() - 1;
        int option = XegerUtils.getRandomInt(0, nroptions, random);
        if (state.isAccept() && option == 0) {          // 0 is considered stop
            return;
        }
        // Moving on to next transition
        Transition transition = transitions.get(option - (state.isAccept() ? 1 : 0));
        appendChoice(builder, transition);
        generate(builder, transition.getDest());
    }

    private void appendChoice(StringBuilder builder, Transition transition) {
        char c = (char) XegerUtils.getRandomInt(transition.getMin(), transition.getMax(), random);
        builder.append(c);
    }

}

@@ -785,37 +785,9 @@
 til.
-List;%0Aimport java.util.Random
+*
 ;%0A%0A/
@@ -1122,16 +1122,789 @@
 andom;%0A%0A
+    /**%0A     * The predefined character classes supported.%0A     * %3Cp%3E%0A     * An immutable map containing as keys the character classes and values the equivalent regular expression syntax.%0A     */%0A    private static final Map%3CString, String%3E PREDEFINED_CHARACTER_CLASSES;%0A%0A    static %7B%0A        Map%3CString, String%3E characterClasses = new HashMap%3CString, String%3E();%0A        characterClasses.put(%22%5C%5C%5C%5Cd%22, %22%5B0-9%5D%22);%0A        characterClasses.put(%22%5C%5C%5C%5CD%22, %22%5B%5E0-9%5D%22);%0A        characterClasses.put(%22%5C%5C%5C%5Cs%22, %22%5B %5Ct%5Cn%5Cf%5Cr%5D%22);%0A        characterClasses.put(%22%5C%5C%5C%5CS%22, %22%5B%5E %5Ct%5Cn%5Cf%5Cr%5D%22);%0A        characterClasses.put(%22%5C%5C%5C%5Cw%22, %22%5Ba-zA-Z_0-9%5D%22);%0A        characterClasses.put(%22%5C%5C%5C%5CW%22, %22%5B%5Ea-zA-Z_0-9%5D%22);%0A        PREDEFINED_CHARACTER_CLASSES = Collections.unmodifiableMap(characterClasses);%0A    %7D%0A%0A
     /**%0A
@@ -2364,32 +2364,263 @@
 random != null;%0A
+%0A        String finalRegex = regex;%0A        for (Map.Entry%3CString, String%3E charClass : PREDEFINED_CHARACTER_CLASSES.entrySet()) %7B%0A            finalRegex = finalRegex.replaceAll(charClass.getKey(), charClass.getValue());%0A        %7D%0A%0A
         this.aut
@@ -2639,17 +2639,22 @@
  RegExp(
-r
+finalR
 egex).to

Add support for character class shortcuts in Xeger