Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
/*
 * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
 *
 * Licensed under the Aduna BSD-style license.
 */

import java.util.StringTokenizer;

public class Main {
    /**
     * Normalizes a double to its canonical representation.
     * 
     * @param value
     *            The value to normalize.
     * @return The canonical representation of <tt>value</tt>.
     * @throws IllegalArgumentException
     *             If the supplied value is not a legal double.
     */
    public static String normalizeDouble(String value) {
        return normalizeFPNumber(value, "-9007199254740991.0", "9007199254740991.0", "-1075", "970");
    }

    /**
     * Normalizes a floating point number to its canonical representation.
     * 
     * @param value
     *            The value to normalize.
     * @return The canonical representation of <tt>value</tt>.
     * @throws IllegalArgumentException
     *             If the supplied value is not a legal floating point number.
     */
    public static String normalizeFPNumber(String value) {
        return normalizeFPNumber(value, null, null, null, null);
    }

    /**
     * Normalizes a floating point number to its canonical representation.
     * 
     * @param value
     *            The value to normalize.
     * @param minMantissa
     *            A normalized decimal indicating the lowest value that the
     *            mantissa may have.
     * @param maxMantissa
     *            A normalized decimal indicating the highest value that the
     *            mantissa may have.
     * @param minExponent
     *            A normalized integer indicating the lowest value that the
     *            exponent may have.
     * @param maxExponent
     *            A normalized integer indicating the highest value that the
     *            exponent may have.
     * @return The canonical representation of <tt>value</tt>.
     * @throws IllegalArgumentException
     *             If the supplied value is not a legal floating point number.
     */
    private static String normalizeFPNumber(String value, String minMantissa, String maxMantissa,
            String minExponent, String maxExponent) {
        value = collapseWhiteSpace(value);

        // handle special values
        if (value.equals("INF") || value.equals("-INF") || value.equals("NaN")) {
            return value;
        }

        // Search for the exponent character E or e
        int eIdx = value.indexOf('E');
        if (eIdx == -1) {
            // try lower case
            eIdx = value.indexOf('e');
        }

        // Extract mantissa and exponent
        String mantissa, exponent;
        if (eIdx == -1) {
            mantissa = normalizeDecimal(value);
            exponent = "0";
        } else {
            mantissa = normalizeDecimal(value.substring(0, eIdx));
            exponent = normalizeInteger(value.substring(eIdx + 1));
        }

        // Check lower and upper bounds, if applicable
        if (minMantissa != null) {
            if (compareCanonicalDecimals(mantissa, minMantissa) < 0) {
                throwIAE("Mantissa smaller than minimum value (" + minMantissa + ")");
            }
        }
        if (maxMantissa != null) {
            if (compareCanonicalDecimals(mantissa, maxMantissa) > 0) {
                throwIAE("Mantissa larger than maximum value (" + maxMantissa + ")");
            }
        }
        if (minExponent != null) {
            if (compareCanonicalIntegers(exponent, minExponent) < 0) {
                throwIAE("Exponent smaller than minimum value (" + minExponent + ")");
            }
        }
        if (maxExponent != null) {
            if (compareCanonicalIntegers(exponent, maxExponent) > 0) {
                throwIAE("Exponent larger than maximum value (" + maxExponent + ")");
            }
        }

        // Normalize mantissa to one non-zero digit before the dot
        int shift = 0;

        int dotIdx = mantissa.indexOf('.');
        int digitCount = dotIdx;
        if (mantissa.charAt(0) == '-') {
            digitCount--;
        }

        if (digitCount > 1) {
            // more than one digit before the dot, e.g 123.45, -10.0 or 100.0
            StringBuilder sb = new StringBuilder(mantissa.length());
            int firstDigitIdx = 0;
            if (mantissa.charAt(0) == '-') {
                sb.append('-');
                firstDigitIdx = 1;
            }
            sb.append(mantissa.charAt(firstDigitIdx));
            sb.append('.');
            sb.append(mantissa.substring(firstDigitIdx + 1, dotIdx));
            sb.append(mantissa.substring(dotIdx + 1));

            mantissa = sb.toString();

            // Check if the mantissa has excessive trailing zeros.
            // For example, 100.0 will be normalize to 1.000 and
            // -10.0 to -1.00.
            int nonZeroIdx = mantissa.length() - 1;
            while (nonZeroIdx >= 3 && mantissa.charAt(nonZeroIdx) == '0') {
                nonZeroIdx--;
            }

            if (nonZeroIdx < 3 && mantissa.charAt(0) == '-') {
                nonZeroIdx++;
            }

            if (nonZeroIdx < mantissa.length() - 1) {
                mantissa = mantissa.substring(0, nonZeroIdx + 1);
            }

            shift = 1 - digitCount;
        } else if (mantissa.startsWith("0.") || mantissa.startsWith("-0.")) {
            // Example mantissas: 0.0, -0.1, 0.00345 and 0.09
            // search first non-zero digit
            int nonZeroIdx = 2;
            while (nonZeroIdx < mantissa.length() && mantissa.charAt(nonZeroIdx) == '0') {
                nonZeroIdx++;
            }

            // 0.0 does not need any normalization:
            if (nonZeroIdx < mantissa.length()) {
                StringBuilder sb = new StringBuilder(mantissa.length());
                sb.append(mantissa.charAt(nonZeroIdx));
                sb.append('.');
                if (nonZeroIdx == mantissa.length() - 1) {
                    // There was only one non-zero digit, e.g. as in 0.09
                    sb.append('0');
                } else {
                    sb.append(mantissa.substring(nonZeroIdx + 1));
                }

                mantissa = sb.toString();
                shift = nonZeroIdx - 1;
            }
        }

        if (shift != 0) {
            try {
                int exp = Integer.parseInt(exponent);
                exponent = String.valueOf(exp - shift);
            } catch (NumberFormatException e) {
                throw new RuntimeException("NumberFormatException: " + e.getMessage());
            }
        }

        return mantissa + "E" + exponent;
    }

    /**
     * Replaces all contiguous sequences of #x9 (tab), #xA (line feed) and #xD
     * (carriage return) with a single #x20 (space) character, and removes any
     * leading and trailing whitespace characters, as specified for whiteSpace
     * facet <tt>collapse</tt>.
     */
    public static String collapseWhiteSpace(String s) {
        StringBuilder sb = new StringBuilder(s.length());

        StringTokenizer st = new StringTokenizer(s, "\t\r\n ");

        if (st.hasMoreTokens()) {
            sb.append(st.nextToken());
        }

        while (st.hasMoreTokens()) {
            sb.append(' ').append(st.nextToken());
        }

        return sb.toString();
    }

    /**
     * Normalizes a decimal to its canonical representation. For example:
     * <tt>120</tt> becomes <tt>120.0</tt>, <tt>+.3</tt> becomes <tt>0.3</tt>,
     * <tt>00012.45000</tt> becomes <tt>12.45</tt> and <tt>-.0</tt> becomes
     * <tt>0.0</tt>.
     * 
     * @param decimal
     *            The decimal to normalize.
     * @return The canonical representation of <tt>decimal</tt>.
     * @throws IllegalArgumentException
     *             If one of the supplied strings is not a legal decimal.
     */
    public static String normalizeDecimal(String decimal) {
        decimal = collapseWhiteSpace(decimal);

        int decLength = decimal.length();
        StringBuilder result = new StringBuilder(decLength + 2);

        if (decLength == 0) {
            throwIAE("Not a legal decimal: " + decimal);
        }

        boolean isZeroPointZero = true;

        // process any sign info
        int idx = 0;
        if (decimal.charAt(idx) == '-') {
            result.append('-');
            idx++;
        } else if (decimal.charAt(idx) == '+') {
            idx++;
        }

        if (idx == decLength) {
            throwIAE("Not a legal decimal: " + decimal);
        }

        // skip any leading zeros
        while (idx < decLength && decimal.charAt(idx) == '0') {
            idx++;
        }

        // Process digits before the dot
        if (idx == decLength) {
            // decimal consists of zeros only
            result.append('0');
        } else if (idx < decLength && decimal.charAt(idx) == '.') {
            // no non-zero digit before the dot
            result.append('0');
        } else {
            isZeroPointZero = false;

            // Copy any digits before the dot
            while (idx < decLength) {
                char c = decimal.charAt(idx);
                if (c == '.') {
                    break;
                }
                if (!isDigit(c)) {
                    throwIAE("Not a legal decimal: " + decimal);
                }
                result.append(c);
                idx++;
            }
        }

        result.append('.');

        // Process digits after the dot
        if (idx == decLength) {
            // No dot was found in the decimal
            result.append('0');
        } else {
            idx++;

            // search last non-zero digit
            int lastIdx = decLength - 1;
            while (lastIdx >= 0 && decimal.charAt(lastIdx) == '0') {
                lastIdx--;
            }

            if (idx > lastIdx) {
                // No non-zero digits found
                result.append('0');
            } else {
                isZeroPointZero = false;

                while (idx <= lastIdx) {
                    char c = decimal.charAt(idx);
                    if (!isDigit(c)) {
                        throwIAE("Not a legal decimal: " + decimal);
                    }
                    result.append(c);
                    idx++;
                }
            }
        }

        if (isZeroPointZero) {
            // Make sure we don't return "-0.0"
            return "0.0";
        } else {
            return result.toString();
        }
    }

    /**
     * Normalizes an integer to its canonical representation. For example:
     * <tt>+120</tt> becomes <tt>120</tt> and <tt>00012</tt> becomes <tt>12</tt>
     * .
     * 
     * @param value
     *            The value to normalize.
     * @return The canonical representation of <tt>value</tt>.
     * @throws IllegalArgumentException
     *             If the supplied value is not a legal integer.
     */
    public static String normalizeInteger(String value) {
        return normalizeIntegerValue(value, null, null);
    }

    /**
     * Compares two canonical decimals to eachother.
     * 
     * @return A negative number if <tt>dec1</tt> is smaller than <tt>dec2</tt>,
     *         <tt>0</tt> if they are equal, or positive (&gt;0) if
     *         <tt>dec1</tt> is larger than <tt>dec2</tt>. The result is
     *         undefined when one or both of the arguments is not a canonical
     *         decimal.
     * @throws IllegalArgumentException
     *             If one of the supplied strings is not a legal decimal.
     */
    public static int compareCanonicalDecimals(String dec1, String dec2) {
        if (dec1.equals(dec2)) {
            return 0;
        }

        // Check signs
        if (dec1.charAt(0) == '-' && dec2.charAt(0) != '-') {
            // dec1 is negative, dec2 is not
            return -1;
        }
        if (dec2.charAt(0) == '-' && dec1.charAt(0) != '-') {
            // dec2 is negative, dec1 is not
            return 1;
        }

        int dotIdx1 = dec1.indexOf('.');
        int dotIdx2 = dec2.indexOf('.');

        // The decimal with the most digits before the dot is the largest
        int result = dotIdx1 - dotIdx2;

        if (result == 0) {
            // equal number of digits before the dot, compare them
            for (int i = 0; result == 0 && i < dotIdx1; i++) {
                result = dec1.charAt(i) - dec2.charAt(i);
            }

            // Continue comparing digits after the dot if necessary
            int dec1Length = dec1.length();
            int dec2Length = dec2.length();
            int lastIdx = dec1Length <= dec2Length ? dec1Length : dec2Length;

            for (int i = dotIdx1 + 1; result == 0 && i < lastIdx; i++) {
                result = dec1.charAt(i) - dec2.charAt(i);
            }

            // Still equal? The decimal with the most digits is the largest
            if (result == 0) {
                result = dec1Length - dec2Length;
            }
        }

        if (dec1.charAt(0) == '-') {
            // reverse result for negative values
            result = -result;
        }

        return result;
    }

    /**
     * Throws an IllegalArgumentException that contains the supplied message.
     */
    private static final void throwIAE(String msg) {
        throw new IllegalArgumentException(msg);
    }

    /**
     * Compares two canonical integers to eachother.
     * 
     * @return A negative number if <tt>int1</tt> is smaller than <tt>int2</tt>,
     *         <tt>0</tt> if they are equal, or positive (&gt;0) if
     *         <tt>int1</tt> is larger than <tt>int2</tt>. The result is
     *         undefined when one or both of the arguments is not a canonical
     *         integer.
     * @throws IllegalArgumentException
     *             If one of the supplied strings is not a legal integer.
     */
    public static int compareCanonicalIntegers(String int1, String int2) {
        if (int1.equals(int2)) {
            return 0;
        }

        // Check signs
        if (int1.charAt(0) == '-' && int2.charAt(0) != '-') {
            // int1 is negative, int2 is not
            return -1;
        }
        if (int2.charAt(0) == '-' && int1.charAt(0) != '-') {
            // int2 is negative, int1 is not
            return 1;
        }

        // The integer with the most digits is the largest
        int result = int1.length() - int2.length();

        if (result == 0) {
            // equal number of digits, compare them
            for (int i = 0; result == 0 && i < int1.length(); i++) {
                result = int1.charAt(i) - int2.charAt(i);
            }
        }

        if (int1.charAt(0) == '-') {
            // reverse result for negative values
            result = -result;
        }

        return result;
    }

    /**
     * Parses the supplied xsd:int strings and returns its value.
     * 
     * @param s
     *            A string representation of an xsd:int value.
     * @return The <tt>int</tt> value represented by the supplied string
     *         argument.
     * @throws NumberFormatException
     *             If the supplied string is not a valid xsd:int value.
     */
    public static int parseInt(String s) {
        s = trimPlusSign(s);
        return Integer.parseInt(s);
    }

    /**
     * Checks whether the supplied character is a digit.
     */
    private static final boolean isDigit(char c) {
        return c >= '0' && c <= '9';
    }

    /**
     * Normalizes an integer to its canonical representation and checks that the
     * value is in the range [minValue, maxValue].
     */
    private static String normalizeIntegerValue(String integer, String minValue, String maxValue) {
        integer = collapseWhiteSpace(integer);

        int intLength = integer.length();

        if (intLength == 0) {
            throwIAE("Not a legal integer: " + integer);
        }

        int idx = 0;

        // process any sign info
        boolean isNegative = false;
        if (integer.charAt(idx) == '-') {
            isNegative = true;
            idx++;
        } else if (integer.charAt(idx) == '+') {
            idx++;
        }

        if (idx == intLength) {
            throwIAE("Not a legal integer: " + integer);
        }

        if (integer.charAt(idx) == '0' && idx < intLength - 1) {
            // integer starts with a zero followed by more characters,
            // skip any leading zeros
            idx++;
            while (idx < intLength - 1 && integer.charAt(idx) == '0') {
                idx++;
            }
        }

        String norm = integer.substring(idx);

        // Check that all characters in 'norm' are digits
        for (int i = 0; i < norm.length(); i++) {
            if (!isDigit(norm.charAt(i))) {
                throwIAE("Not a legal integer: " + integer);
            }
        }

        if (isNegative && norm.charAt(0) != '0') {
            norm = "-" + norm;
        }

        // Check lower and upper bounds, if applicable
        if (minValue != null) {
            if (compareCanonicalIntegers(norm, minValue) < 0) {
                throwIAE("Value smaller than minimum value");
            }
        }
        if (maxValue != null) {
            if (compareCanonicalIntegers(norm, maxValue) > 0) {
                throwIAE("Value larger than maximum value");
            }
        }

        return norm;
    }

    /**
     * Removes the first character from the supplied string if this is a plus
     * sign ('+'). Number strings with leading plus signs cannot be parsed by
     * methods such as {@link Integer#parseInt(String)}.
     */
    private static String trimPlusSign(String s) {
        if (s.length() > 0 && s.charAt(0) == '+') {
            return s.substring(1);
        } else {
            return s;
        }
    }
}