org.etk.entity.base.utils.UtilValidate.java Source code

Java tutorial

Introduction

Here is the source code for org.etk.entity.base.utils.UtilValidate.java

Source

/*
 * Copyright (C) 2003-2011 eXo Platform SAS.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.etk.entity.base.utils;

import java.sql.Timestamp;
import com.ibm.icu.util.Calendar;
import java.util.Collection;
import java.util.Map;

import org.apache.commons.validator.EmailValidator;
import org.etk.entity.base.lang.IsEmpty;

/**
 * Created by The eXo Platform SAS
 * Author : eXoPlatform
 *          exo@exoplatform.com
 * Sep 6, 2011  
 */
/**
 * General input/data validation methods Utility methods for validating data,
 * especially input. See detailed description below. <br/>
 * SUMMARY <br/>
 * <br/>
 * This is a set of meethods for validating input. Functions are provided to
 * validate: <br/>
 * - U.S. and international phone/fax numbers <br/>
 * - U.S. ZIP codes(5 or 9 digit postal codes) <br/>
 * - U.S. Postal Codes(2 letter abbreviations for names of states) <br/>
 * - U.S. Social Security Numbers(abbreviated as SSNs) <br/>
 * - email addresses <br/>
 * - dates(entry of year, month, and day and validity of combined date) <br/>
 * - credit card numbers <br/>
 * <br/>
 * Supporting utility functions validate that: <br/>
 * - characters are Letter, Digit, or LetterOrDigit <br/>
 * - strings are a Signed, Positive, Negative, Nonpositive, or Nonnegative
 * integer <br/>
 * - strings are a Float or a SignedFloat <br/>
 * - strings are Alphabetic, Alphanumeric, or Whitespace <br/>
 * - strings contain an integer within a specified range <br/>
 * <br/>
 * Other utility functions are provided to: <br/>
 * - remove from a string characters which are/are not in a "bag" of selected
 * characters <br/>
 * - strip whitespace/leading whitespace from a string <br/>
 * <br/>
 * ============================================================================
 * == <br/>
 * NOTE: This code was adapted from the Netscape JavaScript form validation
 * code, <br/>
 * usually found in "FormChek.js". Credit card verification functions Originally <br/>
 * included as Starter Application 1.0.0 in LivePayment. <br/>
 * ============================================================================
 * ==
 * 
 */

public class UtilValidate {

    public static final String module = UtilValidate.class.getName();

    /**
     * boolean specifying by default whether or not it is okay for a String to be
     * empty
     */
    public static final boolean defaultEmptyOK = true;

    /** digit characters */
    public static final String digits = "0123456789";

    /** hex digit characters */
    public static final String hexDigits = digits + "abcdefABCDEF";

    /** lower-case letter characters */
    public static final String lowercaseLetters = "abcdefghijklmnopqrstuvwxyz";

    /** upper-case letter characters */
    public static final String uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /** letter characters */
    public static final String letters = lowercaseLetters + uppercaseLetters;

    /** whitespace characters */
    public static final String whitespace = " \t\n\r";

    /** decimal point character differs by language and culture */
    public static final String decimalPointDelimiter = ".";

    /** non-digit characters which are allowed in phone numbers */
    public static final String phoneNumberDelimiters = "()- ";

    /** characters which are allowed in US phone numbers */
    public static final String validUSPhoneChars = digits + phoneNumberDelimiters;

    /**
     * characters which are allowed in international phone numbers(a leading + is
     * OK)
     */
    public static final String validWorldPhoneChars = digits + phoneNumberDelimiters + "+";

    /** non-digit characters which are allowed in Social Security Numbers */
    public static final String SSNDelimiters = "- ";

    /** characters which are allowed in Social Security Numbers */
    public static final String validSSNChars = digits + SSNDelimiters;

    /**
     * U.S. Social Security Numbers have 9 digits. They are formatted as
     * 123-45-6789.
     */
    public static final int digitsInSocialSecurityNumber = 9;

    /**
     * U.S. phone numbers have 10 digits. They are formatted as 123 456 7890
     * or(123) 456-7890.
     */
    public static final int digitsInUSPhoneNumber = 10;

    public static final int digitsInUSPhoneAreaCode = 3;

    public static final int digitsInUSPhoneMainNumber = 7;

    /** non-digit characters which are allowed in ZIP Codes */
    public static final String ZipCodeDelimiters = "-";

    /** our preferred delimiter for reformatting ZIP Codes */
    public static final String ZipCodeDelimeter = "-";

    /** characters which are allowed in Social Security Numbers */
    public static final String validZipCodeChars = digits + ZipCodeDelimiters;

    /**
     * U.S. ZIP codes have 5 or 9 digits. They are formatted as 12345 or
     * 12345-6789.
     */
    public static final int digitsInZipCode1 = 5;

    /**
     * U.S. ZIP codes have 5 or 9 digits. They are formatted as 12345 or
     * 12345-6789.
     */
    public static final int digitsInZipCode2 = 9;

    /** non-digit characters which are allowed in credit card numbers */
    public static final String creditCardDelimiters = " -";

    public static final String isNotEmptyMsg = "This field cannot be empty, please enter a value.";

    public static final String isStateCodeMsg = "The State Code must be a valid two character U.S. state abbreviation(like CA for California).";

    public static final String isContiguousStateCodeMsg = "The State Code must be a valid two character U.S. state abbreviation for one of the 48 contiguous United States (like CA for California).";

    public static final String isZipCodeMsg = "The ZIP Code must be a 5 or 9 digit U.S. ZIP Code(like 94043).";

    public static final String isUSPhoneMsg = "The US Phone must be a 10 digit U.S. phone number(like 415-555-1212).";

    public static final String isUSPhoneAreaCodeMsg = "The Phone Number Area Code must be 3 digits.";

    public static final String isUSPhoneMainNumberMsg = "The Phone Number must be 7 digits.";

    public static final String isContiguousZipCodeMsg = "Zip Code is not a valid Zip Code for one of the 48 contiguous United States .";

    public static final String isInternationalPhoneNumberMsg = "The World Phone must be a valid international phone number.";

    public static final String isSSNMsg = "The SSN must be a 9 digit U.S. social security number(like 123-45-6789).";

    public static final String isEmailMsg = "The Email must be a valid email address(like john@email.com). Please re-enter it now.";

    public static final String isAnyCardMsg = "The credit card number is not a valid card number.";

    public static final String isCreditCardPrefixMsg = " is not a valid ";

    public static final String isCreditCardSuffixMsg = " credit card number.";

    public static final String isDayMsg = "The Day must be a day number between 1 and 31. ";

    public static final String isMonthMsg = "The Month must be a month number between 1 and 12. ";

    public static final String isYearMsg = "The Year must be a 2 or 4 digit year number. ";

    public static final String isDatePrefixMsg = "The Day, Month, and Year for ";

    public static final String isDateSuffixMsg = " do not form a valid date.  Please reenter them now.";

    public static final String isHourMsg = "The Hour must be a number between 0 and 23.";

    public static final String isMinuteMsg = "The Hour must be a number between 0 and 59.";

    public static final String isSecondMsg = "The Hour must be a number between 0 and 59.";

    public static final String isTimeMsg = "The Time must be a valid time formed like: HH:MM or HH:MM:SS.";

    public static final String isDateMsg = "The Date must be a valid date formed like: MM/YY, MM/YYYY, MM/DD/YY, or MM/DD/YYYY.";

    public static final String isDateAfterToday = "The Date must be a valid date after today, and formed like: MM/YY, MM/YYYY, MM/DD/YY, or MM/DD/YYYY.";

    public static final String isIntegerMsg = "The Number must be a valid unsigned whole decimal number.";

    public static final String isSignedIntegerMsg = "The Number must be a valid signed whole decimal number.";

    public static final String isLongMsg = "The Number must be a valid unsigned whole decimal number.";

    public static final String isSignedLongMsg = "The Number must be a valid signed whole decimal number.";

    public static final String isFloatMsg = "The Number must be a valid unsigned decimal number.";

    public static final String isSignedFloatMsg = "The Number must be a valid signed decimal number.";

    public static final String isSignedDoubleMsg = "The Number must be a valid signed decimal number.";

    /**
     * An array of ints representing the number of days in each month of the year.
     * Note: February varies depending on the year
     */
    public static final int[] daysInMonth = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    /** Delimiter for USStateCodes String */
    public static final String USStateCodeDelimiter = "|";

    /**
     * Valid U.S. Postal Codes for states, territories, armed forces, etc. See
     * http://www.usps.gov/ncsc/lookups/abbr_state.txt.
     */
    public static final String USStateCodes = "AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AE|AE|AP";

    /** Valid contiguous U.S. postal codes */
    public static final String ContiguousUSStateCodes = "AL|AZ|AR|CA|CO|CT|DE|DC|FL|GA|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY";

    public static boolean areEqual(Object obj, Object obj2) {
        if (obj == null) {
            return obj2 == null;
        } else {
            return obj.equals(obj2);
        }
    }

    /**
     * Check whether an object is empty, will see if it is a String, Map,
     * Collection, etc.
     */
    public static boolean isEmpty(Object o) {
        return ObjectType.isEmpty(o);
    }

    /**
     * Check whether an object is NOT empty, will see if it is a String, Map,
     * Collection, etc.
     */
    public static boolean isNotEmpty(Object o) {
        return !ObjectType.isEmpty(o);
    }

    /** Check whether IsEmpty o is empty. */
    public static boolean isEmpty(IsEmpty o) {
        return o == null || o.isEmpty();
    }

    /** Check whether IsEmpty o is NOT empty. */
    public static boolean isNotEmpty(IsEmpty o) {
        return o != null && !o.isEmpty();
    }

    /** Check whether string s is empty. */
    public static boolean isEmpty(String s) {
        return ((s == null) || (s.length() == 0));
    }

    /** Check whether collection c is empty. */
    public static <E> boolean isEmpty(Collection<E> c) {
        return ((c == null) || (c.size() == 0));
    }

    /** Check whether map m is empty. */
    public static <K, E> boolean isEmpty(Map<K, E> m) {
        return ((m == null) || (m.size() == 0));
    }

    /** Check whether charsequence c is empty. */
    public static <E> boolean isEmpty(CharSequence c) {
        return ((c == null) || (c.length() == 0));
    }

    /** Check whether string s is NOT empty. */
    public static boolean isNotEmpty(String s) {
        return ((s != null) && (s.length() > 0));
    }

    /** Check whether collection c is NOT empty. */
    public static <E> boolean isNotEmpty(Collection<E> c) {
        return ((c != null) && (c.size() > 0));
    }

    /** Check whether charsequence c is NOT empty. */
    public static <E> boolean isNotEmpty(CharSequence c) {
        return ((c != null) && (c.length() > 0));
    }

    public static boolean isString(Object obj) {
        return ((obj != null) && (obj instanceof java.lang.String));
    }

    /** Returns true if string s is empty or whitespace characters only. */
    public static boolean isWhitespace(String s) {
        // Is s empty?
        if (isEmpty(s))
            return true;

        // Search through string's characters one by one
        // until we find a non-whitespace character.
        // When we do, return false; if we don't, return true.
        for (int i = 0; i < s.length(); i++) {
            // Check that current character isn't whitespace.
            char c = s.charAt(i);

            if (whitespace.indexOf(c) == -1)
                return false;
        }
        // All characters are whitespace.
        return true;
    }

    /** Removes all characters which appear in string bag from string s. */
    public static String stripCharsInBag(String s, String bag) {
        int i;
        String returnString = "";

        // Search through string's characters one by one.
        // If character is not in bag, append to returnString.
        for (i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (bag.indexOf(c) == -1)
                returnString += c;
        }
        return returnString;
    }

    /** Removes all characters which do NOT appear in string bag from string s. */
    public static String stripCharsNotInBag(String s, String bag) {
        int i;
        String returnString = "";

        // Search through string's characters one by one.
        // If character is in bag, append to returnString.
        for (i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (bag.indexOf(c) != -1)
                returnString += c;
        }
        return returnString;
    }

    /**
     * Removes all whitespace characters from s. Member whitespace(see above)
     * defines which characters are considered whitespace.
     */
    public static String stripWhitespace(String s) {
        return stripCharsInBag(s, whitespace);
    }

    /**
     * Returns true if single character c(actually a string) is contained within
     * string s.
     */
    public static boolean charInString(char c, String s) {
        return (s.indexOf(c) != -1);
        // for(int i = 0; i < s.length; i++) {
        // if (s.charAt(i) == c) return true;
        // }
        // return false;
    }

    /**
     * Removes initial(leading) whitespace characters from s. Member
     * whitespace(see above) defines which characters are considered whitespace.
     */
    public static String stripInitialWhitespace(String s) {
        int i = 0;

        while ((i < s.length()) && charInString(s.charAt(i), whitespace))
            i++;
        return s.substring(i);
        // return s.substring(i, s.length);
    }

    /**
     * Returns true if character c is an English letter (A .. Z, a..z). NOTE: Need
     * i18n version to support European characters. This could be tricky due to
     * different character sets and orderings for various languages and platforms.
     */
    public static boolean isLetter(char c) {
        return Character.isLetter(c);
    }

    /** Returns true if character c is a digit (0 .. 9). */
    public static boolean isDigit(char c) {
        return Character.isDigit(c);
    }

    /** Returns true if character c is a letter or digit. */
    public static boolean isLetterOrDigit(char c) {
        return Character.isLetterOrDigit(c);
    }

    /** Returns true if character c is a letter or digit. */
    public static boolean isHexDigit(char c) {
        return hexDigits.indexOf(c) >= 0;
    }

    /**
     * Returns true if all characters in string s are numbers. Accepts non-signed
     * integers only. Does not accept floating point, exponential notation, etc.
     */
    public static boolean isInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        // Search through string's characters one by one
        // until we find a non-numeric character.
        // When we do, return false; if we don't, return true.
        for (int i = 0; i < s.length(); i++) {
            // Check that current character is number.
            char c = s.charAt(i);

            if (!isDigit(c))
                return false;
        }

        // All characters are numbers.
        return true;
    }

    /**
     * Returns true if all characters are numbers; first character is allowed to
     * be + or - as well. Does not accept floating point, exponential notation,
     * etc.
     */
    public static boolean isSignedInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        try {
            Integer.parseInt(s);
            return true;
        } catch (Exception e) {
            return false;
        }

        // int startPos = 0;
        // boolean secondArg = defaultEmptyOK;

        // if (isSignedInteger.arguments.length > 1) secondArg =
        // isSignedInteger.arguments[1];

        // skip leading + or -
        // if ((s.charAt(0) == "-") ||(s.charAt(0) == "+")) startPos = 1;
        // return(isInteger(s.substring(startPos, s.length), secondArg))
    }

    /**
     * Returns true if all characters are numbers; first character is allowed to
     * be + or - as well. Does not accept floating point, exponential notation,
     * etc.
     */
    public static boolean isSignedLong(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        try {
            Long.parseLong(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Returns true if string s is an integer > 0. NOTE: using the Java Long
     * object for greatest precision
     */
    public static boolean isPositiveInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            long temp = Long.parseLong(s);

            if (temp > 0)
                return true;
            return false;
        } catch (Exception e) {
            return false;
        }

        // return(isSignedInteger(s, secondArg)
        // &&((isEmpty(s) && secondArg) ||(parseInt(s) > 0)));
    }

    /** Returns true if string s is an integer >= 0. */
    public static boolean isNonnegativeInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            int temp = Integer.parseInt(s);

            if (temp >= 0)
                return true;
            return false;
        } catch (Exception e) {
            return false;
        }

        // return(isSignedInteger(s, secondArg)
        // &&((isEmpty(s) && secondArg) ||(parseInt(s) >= 0)));
    }

    /** Returns true if string s is an integer < 0. */
    public static boolean isNegativeInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            int temp = Integer.parseInt(s);

            if (temp < 0)
                return true;
            return false;
        } catch (Exception e) {
            return false;
        }

        // return(isSignedInteger(s, secondArg)
        // &&((isEmpty(s) && secondArg) ||(parseInt(s) < 0)));
    }

    /** Returns true if string s is an integer <= 0. */
    public static boolean isNonpositiveInteger(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            int temp = Integer.parseInt(s);

            if (temp <= 0)
                return true;
            return false;
        } catch (Exception e) {
            return false;
        }

        // return(isSignedInteger(s, secondArg)
        // &&((isEmpty(s) && secondArg) ||(parseInt(s) <= 0)));
    }

    /**
     * True if string s is an unsigned floating point(real) number. Also returns
     * true for unsigned integers. If you wish to distinguish between integers and
     * floating point numbers, first call isInteger, then call isFloat. Does not
     * accept exponential notation.
     */
    public static boolean isFloat(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        boolean seenDecimalPoint = false;

        if (s.startsWith(decimalPointDelimiter))
            return false;

        // Search through string's characters one by one
        // until we find a non-numeric character.
        // When we do, return false; if we don't, return true.
        for (int i = 0; i < s.length(); i++) {
            // Check that current character is number.
            char c = s.charAt(i);

            if (c == decimalPointDelimiter.charAt(0)) {
                if (!seenDecimalPoint) {
                    seenDecimalPoint = true;
                } else {
                    return false;
                }
            } else {
                if (!isDigit(c))
                    return false;
            }
        }
        // All characters are numbers.
        return true;
    }

    /**
     * General routine for testing whether a string is a float.
     */
    public static boolean isFloat(String s, boolean allowNegative, boolean allowPositive, int minDecimal,
            int maxDecimal) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            float temp = Float.parseFloat(s);
            if (!allowNegative && temp < 0)
                return false;
            if (!allowPositive && temp > 0)
                return false;
            int decimalPoint = s.indexOf(".");
            if (decimalPoint == -1) {
                if (minDecimal > 0)
                    return false;
                return true;
            }
            // 1.2345; length=6; point=1; num=4
            int numDecimals = s.length() - decimalPoint - 1;
            if (minDecimal >= 0 && numDecimals < minDecimal)
                return false;
            if (maxDecimal >= 0 && numDecimals > maxDecimal)
                return false;
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * General routine for testing whether a string is a double.
     */
    public static boolean isDouble(String s, boolean allowNegative, boolean allowPositive, int minDecimal,
            int maxDecimal) {
        if (isEmpty(s))
            return defaultEmptyOK;

        try {
            double temp = Double.parseDouble(s);
            if (!allowNegative && temp < 0)
                return false;
            if (!allowPositive && temp > 0)
                return false;
            int decimalPoint = s.indexOf(".");
            if (decimalPoint == -1) {
                if (minDecimal > 0)
                    return false;
                return true;
            }
            // 1.2345; length=6; point=1; num=4
            int numDecimals = s.length() - decimalPoint - 1;
            if (minDecimal >= 0 && numDecimals < minDecimal)
                return false;
            if (maxDecimal >= 0 && numDecimals > maxDecimal)
                return false;
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * True if string s is a signed or unsigned floating point (real) number.
     * First character is allowed to be + or -. Also returns true for unsigned
     * integers. If you wish to distinguish between integers and floating point
     * numbers, first call isSignedInteger, then call isSignedFloat.
     */
    public static boolean isSignedFloat(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        try {
            Float.parseFloat(s);
            return true;
        } catch (Exception e) {
            return false;
        }

        // The old way:
        // int startPos = 0;
        // if (isSignedFloat.arguments.length > 1) secondArg =
        // isSignedFloat.arguments[1];
        // skip leading + or -
        // if ((s.charAt(0) == "-") ||(s.charAt(0) == "+")) startPos = 1;
        // return(isFloat(s.substring(startPos, s.length), secondArg))
    }

    /**
     * True if string s is a signed or unsigned floating point (real) number.
     * First character is allowed to be + or -. Also returns true for unsigned
     * integers. If you wish to distinguish between integers and floating point
     * numbers, first call isSignedInteger, then call isSignedFloat.
     */
    public static boolean isSignedDouble(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        try {
            Double.parseDouble(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Returns true if string s is letters only. NOTE: This should handle i18n
     * version to support European characters, etc. since it now uses
     * Character.isLetter()
     */
    public static boolean isAlphabetic(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        // Search through string's characters one by one
        // until we find a non-alphabetic character.
        // When we do, return false; if we don't, return true.
        for (int i = 0; i < s.length(); i++) {
            // Check that current character is letter.
            char c = s.charAt(i);

            if (!isLetter(c))
                return false;
        }

        // All characters are letters.
        return true;
    }

    /**
     * Returns true if string s is English letters (A .. Z, a..z) and numbers
     * only. NOTE: Need i18n version to support European characters. This could be
     * tricky due to different character sets and orderings for various languages
     * and platforms.
     */
    public static boolean isAlphanumeric(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        // Search through string's characters one by one
        // until we find a non-alphanumeric character.
        // When we do, return false; if we don't, return true.
        for (int i = 0; i < s.length(); i++) {
            // Check that current character is number or letter.
            char c = s.charAt(i);

            if (!isLetterOrDigit(c))
                return false;
        }

        // All characters are numbers or letters.
        return true;
    }

    /* ================== METHODS TO CHECK VARIOUS FIELDS. ==================== */

    /**
     * isSSN returns true if string s is a valid U.S. Social Security Number. Must
     * be 9 digits.
     */
    public static boolean isSSN(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        String normalizedSSN = stripCharsInBag(s, SSNDelimiters);

        return (isInteger(normalizedSSN) && normalizedSSN.length() == digitsInSocialSecurityNumber);
    }

    /**
     * isUSPhoneNumber returns true if string s is a valid U.S. Phone Number. Must
     * be 10 digits.
     */
    public static boolean isUSPhoneNumber(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        String normalizedPhone = stripCharsInBag(s, phoneNumberDelimiters);

        return (isInteger(normalizedPhone) && normalizedPhone.length() == digitsInUSPhoneNumber);
    }

    /**
     * isUSPhoneAreaCode returns true if string s is a valid U.S. Phone Area Code.
     * Must be 3 digits.
     */
    public static boolean isUSPhoneAreaCode(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        String normalizedPhone = stripCharsInBag(s, phoneNumberDelimiters);

        return (isInteger(normalizedPhone) && normalizedPhone.length() == digitsInUSPhoneAreaCode);
    }

    /**
     * isUSPhoneMainNumber returns true if string s is a valid U.S. Phone Main
     * Number. Must be 7 digits.
     */
    public static boolean isUSPhoneMainNumber(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        String normalizedPhone = stripCharsInBag(s, phoneNumberDelimiters);

        return (isInteger(normalizedPhone) && normalizedPhone.length() == digitsInUSPhoneMainNumber);
    }

    /**
     * isInternationalPhoneNumber returns true if string s is a valid
     * international phone number. Must be digits only; any length OK. May be
     * prefixed by + character.
     */
    public static boolean isInternationalPhoneNumber(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        String normalizedPhone = stripCharsInBag(s, phoneNumberDelimiters);

        return isPositiveInteger(normalizedPhone);
    }

    /**
     * isZIPCode returns true if string s is a valid U.S. ZIP code. Must be 5 or 9
     * digits only.
     */
    public static boolean isZipCode(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        String normalizedZip = stripCharsInBag(s, ZipCodeDelimiters);

        return (isInteger(normalizedZip)
                && ((normalizedZip.length() == digitsInZipCode1) || (normalizedZip.length() == digitsInZipCode2)));
    }

    /**
     * Returns true if string s is a valid contiguous U.S. Zip code. Must be 5 or
     * 9 digits only.
     */
    public static boolean isContiguousZipCode(String s) {
        boolean retval = false;
        if (isZipCode(s)) {
            if (isEmpty(s))
                retval = defaultEmptyOK;
            else {
                String normalizedZip = s.substring(0, 5);
                int iZip = Integer.parseInt(normalizedZip);
                if ((iZip >= 96701 && iZip <= 96898) || (iZip >= 99501 && iZip <= 99950))
                    retval = false;
                else
                    retval = true;
            }
        }
        return retval;
    }

    /** Return true if s is a valid U.S. Postal Code (abbreviation for state). */
    public static boolean isStateCode(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return ((USStateCodes.indexOf(s) != -1) && (s.indexOf(USStateCodeDelimiter) == -1));
    }

    /**
     * Return true if s is a valid contiguous U.S. Postal Code (abbreviation for
     * state).
     */
    public static boolean isContiguousStateCode(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return ((ContiguousUSStateCodes.indexOf(s) != -1) && (s.indexOf(USStateCodeDelimiter) == -1));
    }

    public static boolean isEmail(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return EmailValidator.getInstance().isValid(s);
    }

    /**
     * isUrl returns true if the string contains ://
     * 
     * @param s String to validate
     * @return true if s contains ://
     */
    public static boolean isUrl(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        if (s.indexOf("://") != -1)
            return true;
        return false;
    }

    /**
     * isYear returns true if string s is a valid Year number. Must be 2 or 4
     * digits only. For Year 2000 compliance, you are advised to use 4-digit year
     * numbers everywhere.
     */
    public static boolean isYear(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        if (!isNonnegativeInteger(s))
            return false;
        return ((s.length() == 2) || (s.length() == 4));
    }

    /**
     * isIntegerInRange returns true if string s is an integer within the range of
     * integer arguments a and b, inclusive.
     */
    public static boolean isIntegerInRange(String s, int a, int b) {
        if (isEmpty(s))
            return defaultEmptyOK;
        // Catch non-integer strings to avoid creating a NaN below,
        // which isn't available on JavaScript 1.0 for Windows.
        if (!isSignedInteger(s))
            return false;
        // Now, explicitly change the type to integer via parseInt
        // so that the comparison code below will work both on
        // JavaScript 1.2(which typechecks in equality comparisons)
        // and JavaScript 1.1 and before(which doesn't).
        int num = Integer.parseInt(s);

        return ((num >= a) && (num <= b));
    }

    /** isMonth returns true if string s is a valid month number between 1 and 12. */
    public static boolean isMonth(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return isIntegerInRange(s, 1, 12);
    }

    /** isDay returns true if string s is a valid day number between 1 and 31. */
    public static boolean isDay(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return isIntegerInRange(s, 1, 31);
    }

    /**
     * Given integer argument year, returns number of days in February of that
     * year.
     */
    public static int daysInFebruary(int year) {
        // February has 29 days in any year evenly divisible by four,
        // EXCEPT for centurial years which are not also divisible by 400.
        return (((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28);
    }

    /** isHour returns true if string s is a valid number between 0 and 23. */
    public static boolean isHour(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return isIntegerInRange(s, 0, 23);
    }

    /** isMinute returns true if string s is a valid number between 0 and 59. */
    public static boolean isMinute(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return isIntegerInRange(s, 0, 59);
    }

    /** isSecond returns true if string s is a valid number between 0 and 59. */
    public static boolean isSecond(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;
        return isIntegerInRange(s, 0, 59);
    }

    /**
     * isDate returns true if string arguments year, month, and day form a valid
     * date.
     */
    public static boolean isDate(String year, String month, String day) {
        // catch invalid years(not 2- or 4-digit) and invalid months and days.
        if (!(isYear(year) && isMonth(month) && isDay(day)))
            return false;

        int intYear = Integer.parseInt(year);
        int intMonth = Integer.parseInt(month);
        int intDay = Integer.parseInt(day);

        // catch invalid days, except for February
        if (intDay > daysInMonth[intMonth - 1])
            return false;
        if ((intMonth == 2) && (intDay > daysInFebruary(intYear)))
            return false;
        return true;
    }

    /** isDate returns true if string argument date forms a valid date. */
    public static boolean isDate(String date) {
        if (isEmpty(date))
            return defaultEmptyOK;
        String month;
        String day;
        String year;

        int dateSlash1 = date.indexOf("/");
        int dateSlash2 = date.lastIndexOf("/");

        if (dateSlash1 <= 0 || dateSlash1 == dateSlash2)
            return false;
        month = date.substring(0, dateSlash1);
        day = date.substring(dateSlash1 + 1, dateSlash2);
        year = date.substring(dateSlash2 + 1);

        return isDate(year, month, day);
    }

    /**
     * isDate returns true if string argument date forms a valid date and is after
     * today.
     */
    public static boolean isDateAfterToday(String date) {
        if (isEmpty(date))
            return defaultEmptyOK;
        int dateSlash1 = date.indexOf("/");
        int dateSlash2 = date.lastIndexOf("/");

        if (dateSlash1 <= 0)
            return false;

        java.util.Date passed = null;
        if (dateSlash1 == dateSlash2) {
            // consider the day to be optional; use the first day of the following
            // month for comparison since this is an is after test
            String month = date.substring(0, dateSlash1);
            String day = "28";
            String year = date.substring(dateSlash1 + 1);
            if (!isDate(year, month, day))
                return false;

            try {
                int monthInt = Integer.parseInt(month);
                int yearInt = Integer.parseInt(year);
                Calendar calendar = Calendar.getInstance();
                calendar.set(yearInt, monthInt - 1, 0, 0, 0, 0);
                calendar.add(Calendar.MONTH, 1);
                passed = new java.util.Date(calendar.getTime().getTime());
            } catch (Exception e) {
                passed = null;
            }
        } else {
            String month = date.substring(0, dateSlash1);
            String day = date.substring(dateSlash1 + 1, dateSlash2);
            String year = date.substring(dateSlash2 + 1);
            if (!isDate(year, month, day))
                return false;
            passed = UtilDateTime.toDate(month, day, year, "0", "0", "0");
        }

        java.util.Date now = UtilDateTime.nowDate();
        if (passed != null) {
            return passed.after(now);
        } else {
            return false;
        }
    }

    /**
     * isDate returns true if string argument date forms a valid date and is
     * before today.
     */
    public static boolean isDateBeforeToday(String date) {
        if (isEmpty(date))
            return defaultEmptyOK;
        int dateSlash1 = date.indexOf("/");
        int dateSlash2 = date.lastIndexOf("/");

        if (dateSlash1 <= 0)
            return defaultEmptyOK; // In this case an issue number has been provided
                                   // (requires a javascript check in template!)

        java.util.Date passed = null;
        if (dateSlash1 == dateSlash2) {
            // consider the day to be optional; use the first day of the following
            // month for comparison since this is an is after test
            String month = date.substring(0, dateSlash1);
            String day = "28";
            String year = date.substring(dateSlash1 + 1);
            if (!isDate(year, month, day))
                return false;

            try {
                int monthInt = Integer.parseInt(month);
                int yearInt = Integer.parseInt(year);
                Calendar calendar = Calendar.getInstance();
                calendar.set(yearInt, monthInt - 1, 0, 0, 0, 0);
                calendar.add(Calendar.MONTH, 1);
                passed = new java.util.Date(calendar.getTime().getTime());
            } catch (Exception e) {
                passed = null;
            }
        } else {
            String month = date.substring(0, dateSlash1);
            String day = date.substring(dateSlash1 + 1, dateSlash2);
            String year = date.substring(dateSlash2 + 1);
            if (!isDate(year, month, day))
                return false;
            passed = UtilDateTime.toDate(month, day, year, "0", "0", "0");
        }

        java.util.Date now = UtilDateTime.nowDate();
        if (passed != null) {
            return passed.before(now);
        } else {
            return false;
        }
    }

    public static boolean isDateBeforeNow(Timestamp date) {
        Timestamp now = UtilDateTime.nowTimestamp();
        if (date != null) {
            return date.before(now);
        } else {
            return false;
        }
    }

    public static boolean isDateAfterNow(Timestamp date) {
        Timestamp now = UtilDateTime.nowTimestamp();
        if (date != null) {
            return date.after(now);
        } else {
            return false;
        }
    }

    /**
     * isTime returns true if string arguments hour, minute, and second form a
     * valid time.
     */
    public static boolean isTime(String hour, String minute, String second) {
        // catch invalid years(not 2- or 4-digit) and invalid months and days.
        if (isHour(hour) && isMinute(minute) && isSecond(second))
            return true;
        else
            return false;
    }

    /** isTime returns true if string argument time forms a valid time. */
    public static boolean isTime(String time) {
        if (isEmpty(time))
            return defaultEmptyOK;

        String hour;
        String minute;
        String second;

        int timeColon1 = time.indexOf(":");
        int timeColon2 = time.lastIndexOf(":");

        if (timeColon1 <= 0)
            return false;
        hour = time.substring(0, timeColon1);
        if (timeColon1 == timeColon2) {
            minute = time.substring(timeColon1 + 1);
            second = "0";
        } else {
            minute = time.substring(timeColon1 + 1, timeColon2);
            second = time.substring(timeColon2 + 1);
        }
        return isTime(hour, minute, second);
    }

    /**
     * Check to see if a card number is a valid ValueLink Gift Card
     * 
     * @param stPassed a string representing a valuelink gift card
     * @return true, if the number passed simple checks
     */
    public static boolean isValueLinkCard(String stPassed) {
        if (isEmpty(stPassed))
            return defaultEmptyOK;
        String st = stripCharsInBag(stPassed, creditCardDelimiters);
        if (st.length() == 16 && (st.startsWith("7") || st.startsWith("6"))) {
            return true;
        }
        return false;
    }

    /**
     * Check to see if a card number is a valid OFB Gift Card (Certifiicate)
     * 
     * @param stPassed a string representing a gift card
     * @return tru, if the number passed simple checks
     */
    public static boolean isOFBGiftCard(String stPassed) {
        if (isEmpty(stPassed))
            return defaultEmptyOK;
        String st = stripCharsInBag(stPassed, creditCardDelimiters);
        if (st.length() == 15 && sumIsMod10(getLuhnSum(st))) {
            return true;
        }
        return false;
    }

    /**
     * Check to see if a card number is a supported Gift Card
     * 
     * @param stPassed a string representing a gift card
     * @return true, if the number passed simple checks
     */
    public static boolean isGiftCard(String stPassed) {
        if (isOFBGiftCard(stPassed)) {
            return true;
        } else if (isValueLinkCard(stPassed)) {
            return true;
        }
        return false;
    }

    public static int getLuhnSum(String stPassed) {
        stPassed = stPassed.replaceAll("\\D", ""); // nuke any non-digit characters

        int len = stPassed.length();
        int sum = 0;
        int mul = 1;
        for (int i = len - 1; i >= 0; i--) {
            int digit = Character.digit(stPassed.charAt(i), 10);
            digit *= (mul == 1) ? mul++ : mul--;
            sum += (digit >= 10) ? (digit % 10) + 1 : digit;
        }

        return sum;
    }

    public static int getLuhnCheckDigit(String stPassed) {
        int sum = getLuhnSum(stPassed);
        int mod = ((sum / 10 + 1) * 10 - sum) % 10;
        return (10 - mod);
    }

    public static boolean sumIsMod10(int sum) {
        return ((sum % 10) == 0);
    }

    public static String appendCheckDigit(String stPassed) {
        String checkDigit = Integer.toString(getLuhnCheckDigit(stPassed));
        return stPassed + checkDigit;
    }

    /**
     * Checks credit card number with Luhn Mod-10 test
     * 
     * @param stPassed a string representing a credit card number
     * @return true, if the credit card number passes the Luhn Mod-10 test, false
     *         otherwise
     */
    public static boolean isCreditCard(String stPassed) {
        if (isEmpty(stPassed))
            return defaultEmptyOK;
        String st = stripCharsInBag(stPassed, creditCardDelimiters);

        // encoding only works on cars with less the 19 digits
        if (st.length() > 19)
            return false;
        return sumIsMod10(getLuhnSum(st));
    }

    /**
     * Checks to see if the cc number is a valid Visa number
     * 
     * @param cc a string representing a credit card number; Sample number: 4111
     *          1111 1111 1111(16 digits)
     * @return true, if the credit card number is a valid VISA number, false
     *         otherwise
     */
    public static boolean isVisa(String cc) {
        if (((cc.length() == 16) || (cc.length() == 13)) && (cc.substring(0, 1).equals("4")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid Master Card number
     * 
     * @param cc a string representing a credit card number; Sample number: 5500
     *          0000 0000 0004(16 digits)
     * @return true, if the credit card number is a valid MasterCard number, false
     *         otherwise
     */
    public static boolean isMasterCard(String cc) {
        int firstdig = Integer.parseInt(cc.substring(0, 1));
        int seconddig = Integer.parseInt(cc.substring(1, 2));

        if ((cc.length() == 16) && (firstdig == 5) && ((seconddig >= 1) && (seconddig <= 5)))
            return isCreditCard(cc);
        return false;

    }

    /**
     * Checks to see if the cc number is a valid American Express number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          340000000000009(15 digits)
     * @return true, if the credit card number is a valid American Express number,
     *         false otherwise
     */
    public static boolean isAmericanExpress(String cc) {
        int firstdig = Integer.parseInt(cc.substring(0, 1));
        int seconddig = Integer.parseInt(cc.substring(1, 2));

        if ((cc.length() == 15) && (firstdig == 3) && ((seconddig == 4) || (seconddig == 7)))
            return isCreditCard(cc);
        return false;

    }

    /**
     * Checks to see if the cc number is a valid Diners Club number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          30000000000004(14 digits)
     * @return true, if the credit card number is a valid Diner's Club number,
     *         false otherwise
     */
    public static boolean isDinersClub(String cc) {
        int firstdig = Integer.parseInt(cc.substring(0, 1));
        int seconddig = Integer.parseInt(cc.substring(1, 2));

        if ((cc.length() == 14) && (firstdig == 3) && ((seconddig == 0) || (seconddig == 6) || (seconddig == 8)))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid Carte Blanche number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          30000000000004(14 digits)
     * @return true, if the credit card number is a valid Carte Blanche number,
     *         false otherwise
     */
    public static boolean isCarteBlanche(String cc) {
        return isDinersClub(cc);
    }

    /**
     * Checks to see if the cc number is a valid Discover number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          6011000000000004(16 digits)
     * @return true, if the credit card number is a valid Discover card number,
     *         false otherwise
     */
    public static boolean isDiscover(String cc) {
        String first4digs = cc.substring(0, 4);

        if ((cc.length() == 16) && (first4digs.equals("6011")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid EnRoute number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          201400000000009(15 digits)
     * @return true, if the credit card number is a valid enRoute card number,
     *         false, otherwise
     */
    public static boolean isEnRoute(String cc) {
        String first4digs = cc.substring(0, 4);

        if ((cc.length() == 15) && (first4digs.equals("2014") || first4digs.equals("2149")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid JCB number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          3088000000000009(16 digits)
     * @return true, if the credit card number is a valid JCB card number, false
     *         otherwise
     */
    public static boolean isJCB(String cc) {
        String first4digs = cc.substring(0, 4);

        if ((cc.length() == 16)
                && (first4digs.equals("3088") || first4digs.equals("3096") || first4digs.equals("3112")
                        || first4digs.equals("3158") || first4digs.equals("3337") || first4digs.equals("3528")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid Switch number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          6331100000000096(16 digits)
     * @return true, if the credit card number is a valid Switch card number,
     *         false otherwise
     */
    public static boolean isswitch(String cc) {
        String first4digs = cc.substring(0, 4);
        String first6digs = cc.substring(0, 6);

        if (((cc.length() == 16) || (cc.length() == 18) || (cc.length() == 19))
                && (first4digs.equals("4903") || first4digs.equals("4905") || first4digs.equals("4911")
                        || first4digs.equals("4936") || first6digs.equals("564182") || first6digs.equals("633110")
                        || first4digs.equals("6333") || first4digs.equals("6759")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid Solo number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          6331100000000096 (16 digits)
     * @return true, if the credit card number is a valid Solo card number, false
     *         otherwise
     */
    public static boolean isSolo(String cc) {
        String first4digs = cc.substring(0, 4);
        String first2digs = cc.substring(0, 2);
        if (((cc.length() == 16) || (cc.length() == 18) || (cc.length() == 19))
                && (first2digs.equals("63") || first4digs.equals("6767")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid Visa Electron number
     * 
     * @param cc - a string representing a credit card number; Sample number:
     *          4175000000000001(16 digits)
     * @return true, if the credit card number is a valid Visa Electron card
     *         number, false otherwise
     */
    public static boolean isVisaElectron(String cc) {
        String first6digs = cc.substring(0, 6);
        String first4digs = cc.substring(0, 4);

        if ((cc.length() == 16)
                && (first6digs.equals("417500") || first4digs.equals("4917") || first4digs.equals("4913")
                        || first4digs.equals("4508") || first4digs.equals("4844") || first4digs.equals("4027")))
            return isCreditCard(cc);
        return false;
    }

    /**
     * Checks to see if the cc number is a valid number for any accepted credit
     * card
     * 
     * @param ccPassed - a string representing a credit card number
     * @return true, if the credit card number is any valid credit card number for
     *         any of the accepted card types, false otherwise
     */
    public static boolean isAnyCard(String ccPassed) {
        if (isEmpty(ccPassed))
            return defaultEmptyOK;

        String cc = stripCharsInBag(ccPassed, creditCardDelimiters);

        if (!isCreditCard(cc))
            return false;
        if (isMasterCard(cc) || isVisa(cc) || isAmericanExpress(cc) || isDinersClub(cc) || isDiscover(cc)
                || isEnRoute(cc) || isJCB(cc) || isSolo(cc) || isswitch(cc) || isVisaElectron(cc))
            return true;
        return false;
    }

    /**
     * Checks to see if the cc number is a valid number for any accepted credit
     * card, and return the name of that type
     * 
     * @param ccPassed - a string representing a credit card number
     * @return true, if the credit card number is any valid credit card number for
     *         any of the accepted card types, false otherwise
     */
    public static String getCardType(String ccPassed) {
        if (isEmpty(ccPassed))
            return "Unknown";
        String cc = stripCharsInBag(ccPassed, creditCardDelimiters);

        if (!isCreditCard(cc))
            return "Unknown";

        if (isMasterCard(cc))
            return "MasterCard";
        if (isVisa(cc))
            return "Visa";
        if (isAmericanExpress(cc))
            return "AmericanExpress";
        if (isDinersClub(cc))
            return "DinersClub";
        if (isDiscover(cc))
            return "Discover";
        if (isEnRoute(cc))
            return "EnRoute";
        if (isJCB(cc))
            return "JCB";
        if (isSolo(cc))
            return "Solo";
        if (isswitch(cc))
            return "Switch";
        if (isVisaElectron(cc))
            return "VisaElectron";
        return "Unknown";
    }

    /**
     * Checks to see if the cc number is a valid number for the specified type
     * 
     * @param cardType - a string representing the credit card type
     * @param cardNumberPassed - a string representing a credit card number
     * @return true, if the credit card number is valid for the particular credit
     *         card type given in "cardType", false otherwise
     */
    public static boolean isCardMatch(String cardType, String cardNumberPassed) {
        if (isEmpty(cardType))
            return defaultEmptyOK;
        if (isEmpty(cardNumberPassed))
            return defaultEmptyOK;
        String cardNumber = stripCharsInBag(cardNumberPassed, creditCardDelimiters);

        if ((cardType.equalsIgnoreCase("VISA")) && (isVisa(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("MASTERCARD")) && (isMasterCard(cardNumber)))
            return true;
        if (((cardType.equalsIgnoreCase("AMERICANEXPRESS")) || (cardType.equalsIgnoreCase("AMEX")))
                && (isAmericanExpress(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("DISCOVER")) && (isDiscover(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("JCB")) && (isJCB(cardNumber)))
            return true;
        if (((cardType.equalsIgnoreCase("DINERSCLUB")) || (cardType.equalsIgnoreCase("DINERS")))
                && (isDinersClub(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("CARTEBLANCHE")) && (isCarteBlanche(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("ENROUTE")) && (isEnRoute(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("SOLO")) && (isSolo(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("SWITCH")) && (isswitch(cardNumber)))
            return true;
        if ((cardType.equalsIgnoreCase("VISAELECTRON")) && (isVisaElectron(cardNumber)))
            return true;
        return false;
    }

    /**
     * isNotPoBox returns true if address argument does not contain anything that
     * looks like a a PO Box.
     */
    public static boolean isNotPoBox(String s) {
        if (isEmpty(s))
            return defaultEmptyOK;

        // strings to check from Greg's program
        // "P.O. B"
        // "P.o.B"
        // "P.O B"
        // "PO. B"
        // "P O B"
        // "PO B"
        // "P.0. B"
        // "P0 B"

        String sl = s.toLowerCase();
        if (sl.indexOf("p.o. b") != -1)
            return false;
        if (sl.indexOf("p.o.b") != -1)
            return false;
        if (sl.indexOf("p.o b") != -1)
            return false;
        if (sl.indexOf("p o b") != -1)
            return false;
        if (sl.indexOf("po b") != -1)
            return false;
        if (sl.indexOf("pobox") != -1)
            return false;
        if (sl.indexOf("po#") != -1)
            return false;
        if (sl.indexOf("po #") != -1)
            return false;

        // now with 0's for them sneaky folks
        if (sl.indexOf("p.0. b") != -1)
            return false;
        if (sl.indexOf("p.0.b") != -1)
            return false;
        if (sl.indexOf("p.0 b") != -1)
            return false;
        if (sl.indexOf("p 0 b") != -1)
            return false;
        if (sl.indexOf("p0 b") != -1)
            return false;
        if (sl.indexOf("p0box") != -1)
            return false;
        if (sl.indexOf("p0#") != -1)
            return false;
        if (sl.indexOf("p0 #") != -1)
            return false;
        return true;
    }

    public static boolean isValidUpc(String upc) {
        if (upc == null || upc.length() != 12) {
            throw new IllegalArgumentException("Invalid UPC length; must be 12 characters");
        }

        char csum = upc.charAt(11);
        char calcSum = calcUpcChecksum(upc);
        return csum == calcSum;
    }

    public static char calcUpcChecksum(String upc) {
        return calcChecksum(upc, 12);
    }

    public static boolean isValidEan(String ean) {
        if (ean == null || ean.length() != 13) {
            throw new IllegalArgumentException("Invalid EAN length; must be 13 characters");
        }
        char csum = ean.charAt(13);
        char calcSum = calcChecksum(ean, 13);
        return csum == calcSum;
    }

    public static char calcChecksum(String value, int length) {
        if (value != null && value.length() == length + 1) {
            value = value.substring(0, length);
        }
        if (value == null || value.length() != length) {
            throw new IllegalArgumentException(
                    "Illegal size of value; must be either" + length + " or " + (length + 1) + " characters");
        }
        int oddsum = 0;
        int evensum = 0;
        for (int i = value.length() - 1; i >= 0; i--) {
            if ((value.length() - i) % 2 == 0) {
                evensum += Character.digit(value.charAt(i), 10);
            } else {
                oddsum += Character.digit(value.charAt(i), 10);
            }
        }
        int check = 10 - ((evensum + 3 * oddsum) % 10);
        if (check >= 10)
            check = 0;
        return Character.forDigit(check, 10);
    }

    public static String checkValidDatabaseId(String fieldStr) {
        if (fieldStr.indexOf(' ') >= 0) {
            return "[space found at position " + (fieldStr.indexOf(' ') + 1) + "]";
        }
        if (fieldStr.indexOf('"') >= 0) {
            return "[double-quote found at position " + (fieldStr.indexOf('"') + 1) + "]";
        }
        if (fieldStr.indexOf('\'') >= 0) {
            return "[single-quote found at position " + (fieldStr.indexOf('\'') + 1) + "]";
        }
        if (fieldStr.indexOf('&') >= 0) {
            return "[ampersand found at position " + (fieldStr.indexOf('&') + 1) + "]";
        }
        if (fieldStr.indexOf('?') >= 0) {
            return "[question mark found at position " + (fieldStr.indexOf('?') + 1) + "]";
        }
        if (fieldStr.indexOf('<') >= 0) {
            return "[less-than sign found at position " + (fieldStr.indexOf('<') + 1) + "]";
        }
        if (fieldStr.indexOf('>') >= 0) {
            return "[greater-than sign found at position " + (fieldStr.indexOf('>') + 1) + "]";
        }
        if (fieldStr.indexOf('\\') >= 0) {
            return "[back-slash found at position " + (fieldStr.indexOf('\\') + 1) + "]";
        }
        if (fieldStr.indexOf('/') >= 0) {
            return "[forward-slash found at position " + (fieldStr.indexOf('/') + 1) + "]";
        }
        return null;
    }

    public static boolean isValidDatabaseId(String fieldStr, StringBuffer errorDetails) {
        boolean isValid = true;
        String checkMessage = checkValidDatabaseId(fieldStr);
        if (checkMessage != null) {
            isValid = false;
            errorDetails.append(checkMessage);
        }
        return isValid;
    }

    public static boolean isValidDatabaseId(String fieldStr, StringBuilder errorDetails) {
        boolean isValid = true;
        String checkMessage = checkValidDatabaseId(fieldStr);
        if (checkMessage != null) {
            isValid = false;
            errorDetails.append(checkMessage);
        }
        return isValid;
    }
}