org.apache.wicket.util.parse.metapattern.MetaPattern.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.wicket.util.parse.metapattern.MetaPattern.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.wicket.util.parse.metapattern;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.wicket.util.io.IClusterable;

/**
 * Useful class for constructing readable and reusable regular expressions.
 * <p>
 * MetaPatterns can be constructed from a simple regular expression String, from other MetaPatterns
 * (copy constructor), from a list of MetaPatterns or from an array of MetaPatterns. In this way, it
 * is easy to build up larger patterns while transparently binding the capturing groups of each
 * MetaPattern for easy object oriented access to capturing group matches.
 * <p>
 * A given MetaPattern can be converted to a Matcher or Pattern. Groups within the MetaPattern can
 * be used to automatically reference capturing group values when a match is made with a Matcher
 * object.
 * <p>
 * A variety of static constants are provided for use in constructing compound MetaPatterns. Also, a
 * number of simple parsers have been constructed using MetaPatterns in the parsers subpackage.
 * 
 * @author Jonathan Locke
 */
public class MetaPattern implements IClusterable {
    private static final long serialVersionUID = 1L;

    /**
     * Compiled regular expression pattern, or null if patterns variable is valid instead
     */
    private Pattern pattern;

    /** List of patterns, or null if pattern variable is valid instead */
    private List<MetaPattern> patterns;

    /** The compiled MetaPattern */
    private Pattern compiledPattern;

    // Regexps that are used multiple times in defining meta patterns
    private static final String _DOUBLE_QUOTED_STRING = "\"[^\"]*?\"";
    private static final String _SINGLE_QUOTED_STRING = "'[^']*?\'";
    private static final String _STRING = "(?:[\\w\\-\\.]+|" + _DOUBLE_QUOTED_STRING + "|" + _SINGLE_QUOTED_STRING
            + ")";
    private static final String _OPTIONAL_STRING = _STRING + "?";
    private static final String _VARIABLE_NAME = "[A-Za-z_][A-Za-z0-9_]*";
    private static final String _XML_NAME = "[A-Za-z_][A-Za-z0-9_.-]*";

    // Delimiters and punctuation
    /** Constant for whitespace. */
    public static final MetaPattern WHITESPACE = new MetaPattern("\\s+");

    /** Constant for optional whitespace. */
    public static final MetaPattern OPTIONAL_WHITESPACE = new MetaPattern("\\s*");

    /** Constant for non-word. */
    public static final MetaPattern NON_WORD = new MetaPattern("\\W+");

    /** Constant for comma. */
    public static final MetaPattern COMMA = new MetaPattern(",");

    /** Constant for colon. */
    public static final MetaPattern COLON = new MetaPattern(":");

    /** Constant for semicolon. */
    public static final MetaPattern SEMICOLON = new MetaPattern(";");

    /** Constant for slash. */
    public static final MetaPattern SLASH = new MetaPattern("/");

    /** Constant for backslash. */
    public static final MetaPattern BACKSLASH = new MetaPattern("\\\\");

    /** Constant for dot. */
    public static final MetaPattern DOT = new MetaPattern("\\.");

    /** Constant for plus. */
    public static final MetaPattern PLUS = new MetaPattern("\\+");

    /** Constant for minus. */
    public static final MetaPattern MINUS = new MetaPattern("-");

    /** Constant for dash. */
    public static final MetaPattern DASH = new MetaPattern("-");

    /** Constant for underscore. */
    public static final MetaPattern UNDERSCORE = new MetaPattern("_");

    /** Constant for ampersand. */
    public static final MetaPattern AMPERSAND = new MetaPattern("&");

    /** Constant for percent. */
    public static final MetaPattern PERCENT = new MetaPattern("%");

    /** Constant for dollar. */
    public static final MetaPattern DOLLAR_SIGN = new MetaPattern("$");

    /** Constant for pound. */
    public static final MetaPattern POUND_SIGN = new MetaPattern("#");

    /** Constant for at. */
    public static final MetaPattern AT_SIGN = new MetaPattern("@");

    /** Constant for excl. */
    public static final MetaPattern EXCLAMATION_POINT = new MetaPattern("!");

    /** Constant for tilde. */
    public static final MetaPattern TILDE = new MetaPattern("~");

    /** Constant for equals. */
    public static final MetaPattern EQUALS = new MetaPattern("=");

    /** Constant for star. */
    public static final MetaPattern STAR = new MetaPattern("\\*");

    /** Constant for pipe. */
    public static final MetaPattern PIPE = new MetaPattern("\\|");

    /** Constant for left paren. */
    public static final MetaPattern LEFT_PAREN = new MetaPattern("\\(");

    /** Constant for right paren. */
    public static final MetaPattern RIGHT_PAREN = new MetaPattern("\\)");

    /** Constant for left curly braces. */
    public static final MetaPattern LEFT_CURLY = new MetaPattern("\\{");

    /** Constant for right curly braces. */
    public static final MetaPattern RIGHT_CURLY = new MetaPattern("\\}");

    /** Constant for left square bracket. */
    public static final MetaPattern LEFT_SQUARE = new MetaPattern("\\[");

    /** Constant for right square bracket. */
    public static final MetaPattern RIGHT_SQUARE = new MetaPattern("\\]");

    /** Constant for digit. */
    public static final MetaPattern DIGIT = new MetaPattern("\\d");

    /** Constant for digits. */
    public static final MetaPattern DIGITS = new MetaPattern("\\d+");

    /** Constant for an integer (of any size). */
    public static final MetaPattern INTEGER = new MetaPattern("-?\\d+");

    /** Constant for a floating point number. */
    public static final MetaPattern FLOATING_POINT_NUMBER = new MetaPattern("-?\\d+\\.?\\d*|-?\\.\\d+");

    /** Constant for a positive integer. */
    public static final MetaPattern POSITIVE_INTEGER = new MetaPattern("\\d+");

    /** Constant for hex digit. */
    public static final MetaPattern HEXADECIMAL_DIGIT = new MetaPattern("[0-9a-fA-F]");

    /** Constant for hex digits. */
    public static final MetaPattern HEXADECIMAL_DIGITS = new MetaPattern("[0-9a-fA-F]+");

    /** Constant for anything (string). */
    public static final MetaPattern ANYTHING = new MetaPattern(".*");

    /** Constant for anything non-empty (string). */
    public static final MetaPattern ANYTHING_NON_EMPTY = new MetaPattern(".+");

    /** Constant for a word. */
    public static final MetaPattern WORD = new MetaPattern("\\w+");

    /** Constant for an optional word. */
    public static final MetaPattern OPTIONAL_WORD = new MetaPattern("\\w*");

    /** Constant for a variable name. */
    public static final MetaPattern VARIABLE_NAME = new MetaPattern(_VARIABLE_NAME);

    /** Constant for an XML element name. */
    public static final MetaPattern XML_ELEMENT_NAME = new MetaPattern(_XML_NAME);

    /** Constant for an XML attribute name. */
    public static final MetaPattern XML_ATTRIBUTE_NAME = new MetaPattern(_XML_NAME);

    /** Constant for perl interpolation. */
    public static final MetaPattern PERL_INTERPOLATION = new MetaPattern("$\\{" + _VARIABLE_NAME + "\\}");

    /** Constant for a double quoted string. */
    public static final MetaPattern DOUBLE_QUOTED_STRING = new MetaPattern(_DOUBLE_QUOTED_STRING);

    /** Constant for a string. */
    public static final MetaPattern STRING = new MetaPattern(_STRING);

    /** Constant for an optional string. */
    public static final MetaPattern OPTIONAL_STRING = new MetaPattern(_OPTIONAL_STRING);

    /**
     * Constructor for a simple pattern.
     * 
     * @param pattern
     *            The regular expression pattern to compile
     */
    public MetaPattern(final String pattern) {
        this.pattern = Pattern.compile(pattern);
    }

    /**
     * Copy constructor.
     * 
     * @param pattern
     *            The meta pattern to copy
     */
    public MetaPattern(final MetaPattern pattern) {
        this.pattern = pattern.pattern;
        patterns = pattern.patterns;
        compiledPattern = pattern.compiledPattern;
    }

    /**
     * Constructs from an array of MetaPatterns.
     * 
     * @param patterns
     *            Array of MetaPatterns
     */
    public MetaPattern(final MetaPattern... patterns) {
        this(Arrays.asList(patterns));
    }

    /**
     * Constructs from a list of MetaPatterns
     * 
     * @param patterns
     *            List of MetaPatterns
     */
    public MetaPattern(final List<MetaPattern> patterns) {
        this.patterns = patterns;
    }

    /**
     * Creates a matcher against a given input character sequence.
     * 
     * @param input
     *            The input to match against
     * @return The matcher
     */
    public final Matcher matcher(final CharSequence input) {
        return matcher(input, 0);
    }

    /**
     * Creates a matcher with the given regexp compile flags. Once you call this method with a given
     * regexp compile flag value, the pattern will be compiled. Calling it again with a different
     * value for flags will not recompile the pattern.
     * 
     * @param input
     *            The input to match
     * @param flags
     *            One or more of the standard Java regular expression compile flags (see
     *            {@link Pattern#compile(String, int)})
     * @return The matcher
     */
    public final Matcher matcher(final CharSequence input, final int flags) {
        compile(flags);
        return compiledPattern.matcher(input);
    }

    /**
     * Gets the regular expression Pattern for this MetaPattern by compiling it.
     * 
     * @return Pattern compiled with default Java regular expression compile flags
     */
    public final Pattern pattern() {
        return pattern(0);
    }

    /**
     * Gets the regular expression Pattern for this MetaPattern by compiling it using the given
     * flags.
     * 
     * @param flags
     *            One or more of the standard Java regular expression compile flags (see
     *            {@link Pattern#compile(String, int)})
     * @return Equivalent Java regular expression Pattern compiled with the given flags
     */
    public final Pattern pattern(final int flags) {
        compile(flags);
        return compiledPattern;
    }

    /**
     * Converts this MetaPattern to a String.
     * 
     * @return A String representing this MetaPattern
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        if (pattern != null) {
            return pattern.pattern();
        } else {
            final StringBuilder buffer = new StringBuilder();
            for (MetaPattern metaPattern : patterns) {
                buffer.append(metaPattern);
            }
            return buffer.toString();
        }
    }

    /**
     * Compiles this MetaPattern with the given Java regular expression flags.
     * 
     * @param flags
     *            One or more of the standard Java regular expression compile flags (see
     *            {@link Pattern#compile(String, int)})
     */
    private synchronized void compile(final int flags) {
        if (compiledPattern == null) {
            bind(1);
            compiledPattern = Pattern.compile(toString(), flags);
        }
    }

    /**
     * Binds this MetaPattern to one or more capturing groups. Since MetaPatterns can nest, the
     * binding process can recurse.
     * 
     * @param group
     *            The initial capturing group number
     * @return The final capturing group (for use in recursion)
     */
    private int bind(int group) {
        if (this instanceof Group) {
            ((Group) this).bind(group++);
        }

        if (patterns != null) {
            for (MetaPattern metaPattern : patterns) {
                group = metaPattern.bind(group);
            }
        }

        return group;
    }
}