Fix bug in AsYouTypeFormatter where we hit a IndexOutOfBoundsException in its Java...
[platform/upstream/libphonenumber.git] / java / libphonenumber / src / com / google / i18n / phonenumbers / AsYouTypeFormatter.java
index 2a729ec..456c8ed 100644 (file)
@@ -172,7 +172,7 @@ public class AsYouTypeFormatter {
     return false;
   }
 
-  private void getAvailableFormats(String leadingThreeDigits) {
+  private void getAvailableFormats(String leadingDigits) {
     List<NumberFormat> formatList =
         (isCompleteNumber && currentMetadata.intlNumberFormatSize() > 0)
         ? currentMetadata.intlNumberFormats()
@@ -181,13 +181,14 @@ public class AsYouTypeFormatter {
     for (NumberFormat format : formatList) {
       if (!nationalPrefixIsUsedByCountry || isCompleteNumber ||
           format.isNationalPrefixOptionalWhenFormatting() ||
-          phoneUtil.formattingRuleHasFirstGroupOnly(format.getNationalPrefixFormattingRule())) {
+          PhoneNumberUtil.formattingRuleHasFirstGroupOnly(
+              format.getNationalPrefixFormattingRule())) {
         if (isFormatEligible(format.getFormat())) {
           possibleFormats.add(format);
         }
       }
     }
-    narrowDownPossibleFormats(leadingThreeDigits);
+    narrowDownPossibleFormats(leadingDigits);
   }
 
   private boolean isFormatEligible(String format) {
@@ -199,16 +200,18 @@ public class AsYouTypeFormatter {
     Iterator<NumberFormat> it = possibleFormats.iterator();
     while (it.hasNext()) {
       NumberFormat format = it.next();
-      if (format.leadingDigitsPatternSize() > indexOfLeadingDigitsPattern) {
-        Pattern leadingDigitsPattern =
-            regexCache.getPatternForRegex(
-                format.getLeadingDigitsPattern(indexOfLeadingDigitsPattern));
-        Matcher m = leadingDigitsPattern.matcher(leadingDigits);
-        if (!m.lookingAt()) {
-          it.remove();
-        }
-      } // else the particular format has no more specific leadingDigitsPattern, and it should be
-        // retained.
+      if (format.leadingDigitsPatternSize() == 0) {
+        // Keep everything that isn't restricted by leading digits.
+        continue;
+      }
+      int lastLeadingDigitsPattern =
+          Math.min(indexOfLeadingDigitsPattern, format.leadingDigitsPatternSize() - 1);
+      Pattern leadingDigitsPattern = regexCache.getPatternForRegex(
+          format.getLeadingDigitsPattern(lastLeadingDigitsPattern));
+      Matcher m = leadingDigitsPattern.matcher(leadingDigits);
+      if (!m.lookingAt()) {
+        it.remove();
+      }
     }
   }
 
@@ -362,7 +365,7 @@ public class AsYouTypeFormatter {
           }
           return prefixBeforeNationalNumber + nationalNumber.toString();
         }
-        if (possibleFormats.size() > 0) {  // The formatting pattern is already chosen.
+        if (possibleFormats.size() > 0) {  // The formatting patterns are already chosen.
           String tempNationalNumber = inputDigitHelper(nextChar);
           // See if the accrued digits can be formatted properly already. If not, use the results
           // from inputDigitHelper, which does formatting based on the formatting pattern chosen.
@@ -387,6 +390,9 @@ public class AsYouTypeFormatter {
     ableToFormat = true;
     isExpectingCountryCallingCode = false;
     possibleFormats.clear();
+    lastMatchPosition = 0;
+    formattingTemplate.setLength(0);
+    currentFormattingPattern = "";
     return attemptToChooseFormattingPattern();
   }
 
@@ -481,7 +487,8 @@ public class AsYouTypeFormatter {
     // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national
     // number (excluding national prefix) have been entered.
     if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) {
-      getAvailableFormats(nationalNumber.substring(0, MIN_LEADING_DIGITS_LENGTH));
+
+      getAvailableFormats(nationalNumber.toString());
       // See if the accrued digits can be formatted properly already.
       String formattedNumber = attemptToFormatAccruedDigits();
       if (formattedNumber.length() > 0) {
@@ -633,6 +640,8 @@ public class AsYouTypeFormatter {
   }
 
   private String inputDigitHelper(char nextChar) {
+    // Note that formattingTemplate is not guaranteed to have a value, it could be empty, e.g.
+    // when the next digit is entered after extracting an IDD or NDD.
     Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate);
     if (digitMatcher.find(lastMatchPosition)) {
       String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar));