/*
 * 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.hadoop.chukwa.util;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/*>>>
import checkers.nullness.quals.*;
import checkers.regex.quals.*;
*/

/**
 * Utility methods for regular expressions, most notably for testing whether
 * a string is a regular expression.
 */
public class RegexUtil {

  /**
   * A checked version of {@link PatternSyntaxException}.
   * <p>
   * This exception is useful when an illegal regex is detected but the
   * contextual information to report a helpful error message is not available
   * at the current depth in the call stack. By using a checked
   * PatternSyntaxException the error must be handled up the call stack where
   * a better error message can be reported.
   * <p>
   *
   * Typical usage is:
   * <pre>
   * void myMethod(...) throws CheckedPatternSyntaxException {
   *   ...
   *   if (! isRegex(myString)) {
   *     throw new CheckedPatternSyntaxException(...);
   *   }
   *   ... Pattern.compile(myString) ...
   * </pre>
   *
   * Simply calling <tt>Pattern.compile</tt> would have a similar effect,
   * in that <tt>PatternSyntaxException</tt> would be thrown at run time if
   * <tt>myString</tt> is not a regular expression.  There are two problems
   * with such an approach.  First, a client of <tt>myMethod</tt> might
   * forget to handle the exception, since <tt>PatternSyntaxException</tt>
   * is not checked.  Also, the Regex Checker would issue a warning about
   * the call to <tt>Pattern.compile</tt> that might throw an exception.
   * The above usage pattern avoids both problems.
   *
   * @see PatternSyntaxException
   */
  public static class CheckedPatternSyntaxException extends Exception {

    private static final long serialVersionUID = 6266881831979001480L;

    private final PatternSyntaxException pse;

    /**
     * Constructs a new CheckedPatternSyntaxException equivalent to the
     * given {@link PatternSyntaxException}.
     * <p>
     * Consider calling this constructor with the result of
     * {@link RegexUtil#regexError}.
     * @param pse is PatternSyntaxException object
     */
    public CheckedPatternSyntaxException(PatternSyntaxException pse) {
      this.pse = pse;
    }

    /**
     * Constructs a new CheckedPatternSyntaxException.
     *
     * @param desc A description of the error
     * @param regex The erroneous pattern
     * @param index The approximate index in the pattern of the error,
     *              or {@code -1} if the index is not known
     */
    public CheckedPatternSyntaxException(String desc, String regex, int index) {
      this(new PatternSyntaxException(desc, regex, index));
    }

    /**
     * Retrieves the description of the error.
     *
     * @return The description of the error
     */
    public String getDescription() {
      return pse.getDescription();
    }

    /**
     * Retrieves the error index.
     *
     * @return The approximate index in the pattern of the error, or {@code -1}
     *         if the index is not known
     */
    public int getIndex() {
      return pse.getIndex();
    }

    /**
     * Returns a multi-line string containing the description of the syntax
     * error and its index, the erroneous regular-expression pattern, and a
     * visual indication of the error index within the pattern.
     *
     * @return The full detail message
     */
    public String getMessage() {
      return pse.getMessage();
    }

    /**
     * Retrieves the erroneous regular-expression pattern.
     *
     * @return The erroneous pattern
     */
    public String getPattern() {
      return pse.getPattern();
    }
  }

  private RegexUtil() {
    throw new AssertionError("Class RegexUtil shouldn't be instantiated");
  }

  /**
   * Returns true if the argument is a syntactically valid regular
   * expression.
   * @param s is regular expression
   * @return true if there is a match
   */
  public static boolean isRegex(String s) {
    return isRegex(s, 0);
  }

  /**
   * Returns true if the argument is a syntactically valid regular
   * expression with at least the given number of groups.
   * @param s is regular expression
   * @param groups is number of groups to match
   * @return true if there is a match
   */
  /*>>>
  @SuppressWarnings("regex")    // RegexUtil
  */
  /*@Pure*/
  public static boolean isRegex(String s, int groups) {
    Pattern p;
    try {
      p = Pattern.compile(s);
    } catch (PatternSyntaxException e) {
      return false;
    }
    return getGroupCount(p) >= groups;
  }

  /**
   * Returns true if the argument is a syntactically valid regular
   * expression.
   * @param c is a character
   * @return true if there is a match
   */
  public static boolean isRegex(char c) {
    return isRegex(Character.toString(c));
  }

  /**
   * Returns null if the argument is a syntactically valid regular
   * expression. Otherwise returns a string describing why the argument is
   * not a regex.
   * @param s is regular expression
   * @return null if s is a regular expression
   */
  public static String regexError(String s) {
    return regexError(s, 0);
  }

  /**
   * Returns null if the argument is a syntactically valid regular
   * expression with at least the given number of groups. Otherwise returns
   * a string describing why the argument is not a regex.
   * @param s is regular expression
   * @param groups is number of groups to match
   * @return null if s is a regular expression
   */
  public static String regexError(String s, int groups) {
    try {
      Pattern p = Pattern.compile(s);
      int actualGroups = getGroupCount(p);
      if (actualGroups < groups) {
        return regexErrorMessage(s, groups, actualGroups);
      }
    } catch (PatternSyntaxException e) {
      return e.getMessage();
    }
    return null;
  }

  /**
   * Returns null if the argument is a syntactically valid regular
   * expression. Otherwise returns a PatternSyntaxException describing
   * why the argument is not a regex.
   * @param s is regular expression
   * @return null if s is a regular expression
   */
  public static PatternSyntaxException regexException(String s) {
    return regexException(s, 0);
  }

  /**
   * Returns null if the argument is a syntactically valid regular
   * expression with at least the given number of groups. Otherwise returns a
   * PatternSyntaxException describing why the argument is not a regex.
   * @param s is regular expression
   * @param groups is number of groups to match
   * @return null if s is a regular expression
   */
  public static PatternSyntaxException regexException(String s, int groups) {
    try {
      Pattern p = Pattern.compile(s);
      int actualGroups = getGroupCount(p);
      if (actualGroups < groups) {
        return new PatternSyntaxException(regexErrorMessage(s, groups, actualGroups), s, -1);
      }
    } catch (PatternSyntaxException pse) {
      return pse;
    }
    return null;
  }

  /**
   * Returns the argument as a {@code @Regex String} if it is a regex,
   * otherwise throws an error. The purpose of this method is to suppress Regex
   * Checker warnings. Once the the Regex Checker supports flow-sensitivity, it
   * should be very rarely needed.
   * @param s is a regular expression
   * @return null if s is a regular expression
   */
  public static String asRegex(String s) {
    return asRegex(s, 0);
  }

  /**
   * Returns the argument as a {@code @Regex(groups) String} if it is a regex
   * with at least the given number of groups, otherwise throws an error. The
   * purpose of this method is to suppress Regex Checker warnings. Once the the
   * Regex Checker supports flow-sensitivity, it should be very rarely needed.
   * @param s is a regular expression
   * @param groups is number of group to match
   * @return null if s is a regular expression
   */
  public static String asRegex(String s, int groups) {
    try {
      Pattern p = Pattern.compile(s);
      int actualGroups = getGroupCount(p);
      if (actualGroups < groups) {
        throw new Error(regexErrorMessage(s, groups, actualGroups));
      }
      return s;
    } catch (PatternSyntaxException e) {
      throw new Error(e);
    }
  }

  /**
   * Generates an error message for s when expectedGroups are needed, but s
   * only has actualGroups.
   */
  private static String regexErrorMessage(String s, int expectedGroups, int actualGroups) {
    return "regex \"" + s + "\" has " + actualGroups + " groups, but " +
        expectedGroups + " groups are needed.";
  }

  /**
   * Returns the count of groups in the argument.
   */
  private static int getGroupCount(Pattern p) {
    return p.matcher("").groupCount();
  }
}
