You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/07/10 15:57:11 UTC

svn commit: r420525 - in /incubator/harmony/enhanced/classlib/trunk/modules/luni/src: main/java/java/util/Scanner.java main/java/org/apache/harmony/luni/util/ExternalMessages.properties test/java/tests/api/java/util/ScannerTest.java

Author: tellison
Date: Mon Jul 10 06:57:10 2006
New Revision: 420525

URL: http://svn.apache.org/viewvc?rev=420525&view=rev
Log:
Apply patch HARMONY-817 (Implementation of new methods hasNextInt(),nextInt(),hasNextInt(int),nextInt(int), in java.util.Scanner)

Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Scanner.java
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
    incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/ScannerTest.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Scanner.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Scanner.java?rev=420525&r1=420524&r2=420525&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Scanner.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/util/Scanner.java Mon Jul 10 06:57:10 2006
@@ -65,7 +65,7 @@
             "true|false", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
     
     // The pattern matching anything
-    private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*");
+    private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*"); //$NON-NLS-1$
 
     private static final int DIPLOID = 2;
 
@@ -102,6 +102,8 @@
     private IOException lastIOException;
     
     private boolean matchSuccessful = false;
+    
+    private DecimalFormat decimalFormat;
 
     /**
      * Constructs a scanner that uses File as its input. The default charset is
@@ -132,12 +134,12 @@
     public Scanner(File src, String charsetName) throws FileNotFoundException {
         if (null == src) {
             throw new NullPointerException(org.apache.harmony.luni.util.Msg
-                    .getString("KA00a"));
+                    .getString("KA00a")); //$NON-NLS-1$
         }
         FileInputStream fis = new FileInputStream(src);
         if (null == charsetName) {
             throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
-                    .getString("KA009"));
+                    .getString("KA009")); //$NON-NLS-1$
         }
         try {
             input = new InputStreamReader(fis, charsetName);
@@ -188,7 +190,7 @@
     public Scanner(InputStream src, String charsetName) {
         if (null == src) {
             throw new NullPointerException(org.apache.harmony.luni.util.Msg
-                    .getString("KA00b"));
+                    .getString("KA00b")); //$NON-NLS-1$
         }
         try {
             input = new InputStreamReader(src, charsetName);
@@ -237,11 +239,11 @@
     public Scanner(ReadableByteChannel src, String charsetName) {
         if (null == src) {
             throw new NullPointerException(org.apache.harmony.luni.util.Msg
-                    .getString("KA00d"));
+                    .getString("KA00d")); //$NON-NLS-1$
         }
         if (null == charsetName) {
             throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
-                    .getString("KA009"));
+                    .getString("KA009")); //$NON-NLS-1$
         }
         try {
             input = new InputStreamReader(Channels.newInputStream(src),
@@ -483,16 +485,48 @@
         throw new NotYetImplementedException();
     }
 
-    //TODO: To implement this feature
+    /**
+     * Returns true if this scanner's next token can be translated into a valid
+     * int value in the default radix. The scanner does not advance past the
+     * input.
+     * 
+     * @return true iff the next token in this scanner's input can be translated
+     *         into a valid int value
+     * @throws IllegalStateException
+     *             if the scanner has been closed
+     */
     public boolean hasNextInt() {
-        throw new NotYetImplementedException();
+        return hasNextInt(radix);
     }
 
-    //TODO: To implement this feature
+    /**
+     * Returns true if this scanner's next token can be translated into a valid
+     * int value in the specified radix. The scanner does not advance past the
+     * input.
+     * 
+     * @param radix
+     *            the radix used to translate the token into an int value
+     * @return true iff the next token in this scanner's input can be translated
+     *         into a valid int value
+     * @throws IllegalStateException
+     *             if the scanner has been closed
+     */
     public boolean hasNextInt(int radix) {
-        throw new NotYetImplementedException();
+        Pattern integerPattern = getIntegerPattern(radix);
+        boolean isIntValue = false;
+        String intString;
+        if (hasNext(integerPattern)) {
+            intString = removeLocaleInfo(matcher.group());
+            try {
+                Integer.parseInt(intString, radix);
+                isIntValue = true;
+            } catch (NumberFormatException e) {
+                matchSuccessful = false;
+            }
+        }
+        return isIntValue;
     }
-
+    
     //TODO: To implement this feature
     public boolean hasNextLine() {
         throw new NotYetImplementedException();
@@ -700,14 +734,67 @@
         throw new NotYetImplementedException();
     }
 
-    //TODO: To implement this feature
+    /**
+     * Translates the next token in this scanner's input into an int value and
+     * returns this value. This method may be blocked when it is waiting for
+     * input to scan, even if a previous invocation of hasNextInt() returned
+     * true. If this match succeeds, the scanner advances past the input that
+     * matched.
+     * 
+     * The invocation of this method in the form nextInt() behaves in the same
+     * way as the invocaiton of nextInt(radix), the radix is the default radix
+     * of this scanner.
+     * 
+     * @return the int value scanned from the input
+     * @throws IllegalStateException
+     *             if this scanner has been closed
+     * @throws NoSuchElementException
+     *             if input has been exhausted
+     * @throws InputMismatchException
+     *             if the next token can not be translated into a valid int
+     *             value
+     */
     public int nextInt() {
-        throw new NotYetImplementedException();
+        return nextInt(radix);
     }
 
-    //TODO: To implement this feature
+    /**
+     * Translates the next token in this scanner's input into an int value and
+     * returns this value. This method may be blocked when it is waiting for
+     * input to scan, even if a previous invocation of hasNextInt(radix)
+     * returned true. If this match succeeds, the scanner advances past the
+     * input that matched.
+     * 
+     * If the next token matches the Integer regular expression successfully,
+     * the token is translated into an int value as following steps. At first
+     * all locale specific prefixes ,group separators, and locale specific
+     * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
+     * via Character.digit, a negative sign (-) is added if the locale specific
+     * negative prefixes and suffixes were present. At last the resulting String
+     * is passed to Integer.parseInt with the specified radix.
+     * 
+     * @param radix
+     *            the radix used to translate the token into an int value
+     * @return the int value scanned from the input
+     * @throws IllegalStateException
+     *             if this scanner has been closed
+     * @throws NoSuchElementException
+     *             if input has been exhausted
+     * @throws InputMismatchException
+     *             if the next token can not be translated into a valid int
+     *             value
+     */
     public int nextInt(int radix) {
-        throw new NotYetImplementedException();
+        String intString = nextIntegerToken(radix);
+        int intValue = 0;
+        try {
+            intValue = Integer.parseInt(intString, radix);
+        } catch (NumberFormatException e) {
+            matchSuccessful = false;
+            recoverPreviousStatus();
+            throw new InputMismatchException();
+        }
+        return intValue;
     }
 
     //TODO: To implement this feature
@@ -812,7 +899,7 @@
     public Scanner useRadix(int radix) {
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
             throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
-                    .getString("KA008", radix));
+                    .getString("KA008", radix)); //$NON-NLS-1$
         }
         this.radix = radix;
         return this;
@@ -888,6 +975,178 @@
      */
     private void recoverPreviousStatus() {
         findStartIndex = preStartIndex;
+    }
+    
+    /*
+     * Get next token if it matches integer regular expression after removing
+     * locale related information
+     */
+    private String nextIntegerToken(int radix) {
+        Pattern integerPattern = getIntegerPattern(radix);
+        String tokenString = next(integerPattern);
+        String intString = removeLocaleInfo(tokenString);
+        return intString;
+    }
+
+    /*
+     * Get integer's pattern
+     */
+    private Pattern getIntegerPattern(int radix) {
+        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+            throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
+                    .getString("KA00e", radix)); //$NON-NLS-1$
+        }
+        decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+        
+        String allAvailableDigits="0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ 
+        String ASCIIDigit=allAvailableDigits.substring(0, radix);
+        String nonZeroASCIIDigit=allAvailableDigits.substring(1, radix);
+
+        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ 
+                .append("]|\\p{javaDigit})"); //$NON-NLS-1$
+        StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append( //$NON-NLS-1$
+                nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))"); //$NON-NLS-1$
+        StringBuilder numeral = getNumeral(digit, nonZeroDigit);
+
+        StringBuilder integer = new StringBuilder("(([-+]?(").append(numeral) //$NON-NLS-1$
+                .append(")))|(").append(addPositiveSign(numeral)).append(")|(") //$NON-NLS-1$ //$NON-NLS-2$
+                .append(addNegativeSign(numeral)).append(")"); //$NON-NLS-1$
+
+        Pattern integerPattern = Pattern.compile(integer.toString());
+        return integerPattern;
+    }
+
+
+    private StringBuilder getNumeral(StringBuilder digit,
+            StringBuilder nonZeroDigit) {
+        char groupSeparator = decimalFormat.getDecimalFormatSymbols()
+                .getGroupingSeparator();
+        StringBuilder groupedNumeral = new StringBuilder("(").append( //$NON-NLS-1$
+                nonZeroDigit).append(digit).append("?").append(digit).append( //$NON-NLS-1$
+                "?(\\").append(groupSeparator).append(digit).append(digit) //$NON-NLS-1$
+                .append(digit).append(")+)"); //$NON-NLS-1$
+        StringBuilder numeral = new StringBuilder("((").append(digit).append( //$NON-NLS-1$
+                "++)|").append(groupedNumeral).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
+        return numeral;
+    }
+
+    /*
+     * Add the locale specific positive prefixes and suffixes to the pattern
+     */
+    private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
+        String positivePrefix = ""; //$NON-NLS-1$
+        String positiveSuffix = ""; //$NON-NLS-1$
+        if (!decimalFormat.getPositivePrefix().equals("")) { //$NON-NLS-1$
+            positivePrefix = "\\" + decimalFormat.getPositivePrefix(); //$NON-NLS-1$
+        }
+        if (!decimalFormat.getPositiveSuffix().equals("")) { //$NON-NLS-1$
+            positiveSuffix = "\\" + decimalFormat.getPositiveSuffix(); //$NON-NLS-1$
+        }
+        StringBuilder signedNumeral = new StringBuilder()
+                .append(positivePrefix).append(unSignNumeral).append(
+                        positiveSuffix);
+        return signedNumeral;
+    }
+
+    /*
+     * Add the locale specific negative prefixes and suffixes to the pattern
+     */
+    private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
+        String negativePrefix = ""; //$NON-NLS-1$
+        String negativeSuffix = ""; //$NON-NLS-1$
+        if (!decimalFormat.getNegativePrefix().equals("")) { //$NON-NLS-1$
+            negativePrefix = "\\" + decimalFormat.getNegativePrefix(); //$NON-NLS-1$
+        }
+        if (!decimalFormat.getNegativeSuffix().equals("")) { //$NON-NLS-1$
+            negativeSuffix = "\\" + decimalFormat.getNegativeSuffix(); //$NON-NLS-1$
+        }
+        StringBuilder signedNumeral = new StringBuilder()
+                .append(negativePrefix).append(unSignNumeral).append(
+                        negativeSuffix);
+        return signedNumeral;
+    }
+
+    /*
+     * Remove the locale specific prefixes, group separators, and locale
+     * specific suffixes from input string
+     */
+    private String removeLocaleInfo(String token) {
+        StringBuilder tokenBuilder = new StringBuilder(token);
+        boolean negative = removeLocaleSign(tokenBuilder);
+        // Remove group separator
+        String groupSeparator = String.valueOf(decimalFormat
+                .getDecimalFormatSymbols().getGroupingSeparator());
+        int separatorIndex = -1;
+        while (-1 != (separatorIndex = tokenBuilder.indexOf(groupSeparator))) {
+            tokenBuilder.delete(separatorIndex, separatorIndex + 1);
+        }
+        // Remove decimal separator
+        String decimalSeparator = String.valueOf(decimalFormat
+                .getDecimalFormatSymbols().getDecimalSeparator());
+        separatorIndex = tokenBuilder.indexOf(decimalSeparator);
+        StringBuilder result = new StringBuilder(""); //$NON-NLS-1$
+        
+        for (int i = 0; i < tokenBuilder.length(); i++) {
+            if (-1 != Character.digit(tokenBuilder.charAt(i),
+                    Character.MAX_RADIX)) {
+                result.append(tokenBuilder.charAt(i));
+            }
+        }
+        // Token is NaN or Infinity
+        if (0 == result.length()) {
+            result = tokenBuilder;
+        }
+        if (-1 != separatorIndex) {
+            result.insert(separatorIndex, "."); //$NON-NLS-1$
+        }
+        // If input is negative
+        if (negative) {
+            result.insert(0, '-');
+        }
+        return result.toString();
+    }
+
+    /*
+     * remove positive and negative sign from the parameter stringBuilder, and
+     * return whether the input string is negative
+     */
+    private boolean removeLocaleSign(StringBuilder tokenBuilder) {
+        String positivePrefix = decimalFormat.getPositivePrefix();
+        String positiveSuffix = decimalFormat.getPositiveSuffix();
+        String negativePrefix = decimalFormat.getNegativePrefix();
+        String negativeSuffix = decimalFormat.getNegativeSuffix();
+
+        if (0 == tokenBuilder.indexOf("+")) { //$NON-NLS-1$
+            tokenBuilder.delete(0, 1);
+        }
+        if (!positivePrefix.equals("") //$NON-NLS-1$
+                && 0 == tokenBuilder.indexOf(positivePrefix)) {
+            tokenBuilder.delete(0, positivePrefix.length());
+        }
+        if (!positiveSuffix.equals("") //$NON-NLS-1$
+                && -1 != tokenBuilder.indexOf(positiveSuffix)) {
+            tokenBuilder.delete(
+                    tokenBuilder.length() - positiveSuffix.length(),
+                    tokenBuilder.length());
+        }
+        boolean negative = false;
+        if (0 == tokenBuilder.indexOf("-")) { //$NON-NLS-1$
+            tokenBuilder.delete(0, 1);
+            negative = true;
+        }
+        if (!negativePrefix.equals("") //$NON-NLS-1$
+                && 0 == tokenBuilder.indexOf(negativePrefix)) {
+            tokenBuilder.delete(0, negativePrefix.length());
+            negative = true;
+        }
+        if (!negativeSuffix.equals("") //$NON-NLS-1$
+                && -1 != tokenBuilder.indexOf(negativeSuffix)) {
+            tokenBuilder.delete(
+                    tokenBuilder.length() - negativeSuffix.length(),
+                    tokenBuilder.length());
+            negative = true;
+        }
+        return negative;
     }
 
     /*

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties?rev=420525&r1=420524&r2=420525&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties Mon Jul 10 06:57:10 2006
@@ -299,4 +299,5 @@
 KA00b=InputStream is null
 KA00c=Readable is null
 KA00d=ReadableByteChannel is null
+KA00e=Radix {0} is less than Character.MIN_RADIX or greater than Character.MAX_RADIX
 

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/ScannerTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/ScannerTest.java?rev=420525&r1=420524&r2=420525&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/ScannerTest.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/util/ScannerTest.java Mon Jul 10 06:57:10 2006
@@ -928,6 +928,385 @@
     
     /**
      * @throws IOException
+     * @tests java.util.Scanner#nextInt(int)
+     */
+    public void test_nextIntI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt(10));
+        assertEquals(456, s.nextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertEquals(38, s.nextInt(5));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextInt(10));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(162, s.nextInt(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("E3456");
+        assertEquals(930902, s.nextInt(16));
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(930902, s.nextInt(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextInt(10));
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123- (123)");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextInt(10));
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt(10));
+
+        // If the parameter radix is illegal, the following test cases fail on
+        // RI
+        try {
+            s.nextInt(Character.MIN_RADIX - 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            s.nextInt(Character.MAX_RADIX + 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextInt()
+     */
+    public void test_nextInt() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt());
+        assertEquals(456, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertEquals(38, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextInt());
+        s.useRadix(5);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(162, s.nextInt());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("E3456");
+        s.useRadix(16);
+        assertEquals(930902, s.nextInt());
+
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        s.useRadix(16);
+        assertEquals(930902, s.nextInt());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextInt());
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123- (123)");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt());
+    }
+    
+    /**
+     * @throws IOException
      * @tests java.util.Scanner#hasNext()
      */
     public void test_hasNext() throws IOException {
@@ -1196,6 +1575,353 @@
         assertFalse(s.nextBoolean());
         assertFalse(s.hasNextBoolean());
 
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextInt(int)
+     */
+    public void test_hasNextIntI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt(10));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(456, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextInt(5));
+        assertEquals(38, s.nextInt(5));
+        assertFalse(s.hasNextInt(5));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextInt(10));
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt(10));
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextInt(10));
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt(10));
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextInt(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06662");
+        assertTrue(s.hasNextInt(10));
+        assertFalse(s.hasNextInt(5));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextInt(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextInt(10));
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("E3456");
+        assertTrue(s.hasNextInt(16));
+        assertEquals(930902, s.nextInt(16));
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt(16));
+        assertEquals(930902, s.nextInt(16));
+
+        // If parameter radix is illegal, the following test case fails on RI
+        try {
+            s.hasNextInt(Character.MIN_RADIX - 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123- (123)");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextInt()
+     */
+    public void test_hasNextInt() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextInt());
+        assertEquals(123, s.nextInt());
+        assertEquals(456, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertTrue(s.hasNextInt());
+        assertEquals(38, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextInt());
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt());
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt());
+        s.useLocale(new Locale("it", "CH"));
+        assertTrue(s.hasNextInt());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06662");
+        s.useRadix(5);
+        assertFalse(s.hasNextInt());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextInt());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextInt());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextInt());
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("E3456");
+        s.useRadix(16);
+        assertTrue(s.hasNextInt());
+        assertEquals(930902, s.nextInt());
+
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        s.useRadix(16);
+        assertTrue(s.hasNextInt());
+        assertEquals(930902, s.nextInt());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123- (123)");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
     }
 
     private static class MockStringReader extends StringReader {