Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class Main {
    /**
     * Allowed flags by our regular expression evaluator
     */
    public static final String allowedFlags = "sim";

    /**
     * Determines if a given regular expression is strict enough to meet out requirements.
     * @param re Format as: /^ABC, 123$/gim
     * @return
     */
    public static boolean validRegularExpression(String re) {
        /*
         * Steps before building:
         * 1) We need to determine which flags we support (i.e. /hi/gim, the "gim" part)
         * 
         * During evaluation:
         * 1) If null, return false
         * 2) Strip off valid flags from the end. If invalid flag is found, return false
         * 3) Strip off the / at the start and / at the end.
         * 4) If first character is not start anchor (^), return false
         * 5) If last character is not end anchor ($), return false
         * 6) Strip anchors.  At this point, we have our entire regular expression to validate.
         * 7) We need to not allow huge wildcards... i.e. we should ban the use of *, +, and {#,} (this last one leaves open arbitrarily long messages)
         *       NOTE: We don't ban {,#} because they are willingly implementing a max limit
         *       NOTE2: Be careful to not ban \* or \+... those are valid escaped characters
         * 
         * 8) At this point, I think everything should be valid and not overly inefficient
         * 9) Make sure it is a valid expression based on the regular expression validator(CHRIS)
         * 
         * 
         * NOTE: What about if they escape that last /?   (i.e. /hi\/  wouldn't be valid)
         */
        if (re == null || re.isEmpty()) {
            return false;
        }
        int flag_index = 0;
        ArrayList<String> flags = new ArrayList<String>();
        for (int i = (re.length() - 1); i >= 0; i--) {
            String cur_char = re.substring(i, i + 1);
            if (cur_char.equals("/")) {
                flag_index = i;
                break;
            }
            if (!isValidFlag(cur_char)) {
                return false;
            } else {
                flags.add(cur_char);
            }
        }
        if (flag_index == 0) {
            System.out.println("flag_index == 0");
            return false;
        }
        String flagless = re.substring(0, flag_index + 1);
        if (!flagless.substring(0, 1).equals("/")
                || !flagless.substring(flagless.length() - 1, flagless.length()).equals("/")
                || flagless.substring(flagless.length() - 2, flagless.length() - 1).equals("\\")) {
            return false;
        }
        String no_slash = flagless.substring(1, flagless.length() - 1); //is this right?
        if (!no_slash.substring(0, 1).equals("^")
                || !no_slash.substring(no_slash.length() - 1, no_slash.length()).equals("$")
                || no_slash.substring(no_slash.length() - 2, no_slash.length() - 1).equals("\\")) {
            return false;
        }
        String no_anchor = no_slash.substring(1, no_slash.length() - 1); //is this right?
        for (int i = 0; i < no_anchor.length(); i++) {
            String cur_char = no_anchor.substring(i, i + 1);
            String before_char = no_anchor.substring(i, i + 1);
            if (i != 0) {
                before_char = no_anchor.substring(i - 1, i);
            }

            if ((cur_char.equals("+") || cur_char.equals("*")) && !before_char.equals("\\")) {
                return false;
            }
            if (cur_char.equals("{") && !before_char.equals("\\")) {
                //2 bad cases: {,} and {#,}
                if (no_anchor.substring(i, i + 3).equals("{,}")) {
                    return false;
                }
                Pattern p = Pattern.compile("\\{\\d+,\\}");
                if (matchesPattern(p, no_anchor.substring(i))) { //might be slow
                    return false;
                }
            }
        }
        try {
            int flag_value = convertFlagsToConstants(flags);
            Pattern.compile(no_slash, flag_value); //doesn't handle flags
        } catch (PatternSyntaxException exception) {
            return false;
        }
        return true;
    }

    /**
     * Is the potential flag valid?
     * @param potentialFlag The length 1 string to check
     * @return True if valid, false otherwise
     */
    public static boolean isValidFlag(String potentialFlag) {
        return potentialFlag.length() == 1 && allowedFlags.indexOf(potentialFlag) >= 0;
    }

    private static boolean matchesPattern(Pattern p, String sentence) {
        Matcher m = p.matcher(sentence);

        if (m.find()) {
            return true;
        }

        return false;
    }

    /**
     * Converts the string flags to their pattern constants
     * @param flags
     * @return
     */
    public static int convertFlagsToConstants(ArrayList<String> flags) {
        int ret = 0;
        for (String s : flags) {
            if (s.equals("i")) {
                ret |= Pattern.CASE_INSENSITIVE;
            } else if (s.equals("m")) {
                ret |= Pattern.MULTILINE;
            } else {
                ret |= Pattern.DOTALL;
            }
        }
        return ret;
    }
}