AsYouTypeFormatter.java revision 0b3c1fb05c01bc853ad927356eee743b62a8121b
11524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia/* 21524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Copyright (C) 2009 Google Inc. 31524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 41524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Licensed under the Apache License, Version 2.0 (the "License"); 51524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * you may not use this file except in compliance with the License. 61524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * You may obtain a copy of the License at 71524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 81524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * http://www.apache.org/licenses/LICENSE-2.0 91524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Unless required by applicable law or agreed to in writing, software 111524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * distributed under the License is distributed on an "AS IS" BASIS, 121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * See the License for the specific language governing permissions and 141524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * limitations under the License. 151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiapackage com.google.i18n.phonenumbers; 181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; 207900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jiaimport com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; 211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.ArrayList; 231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.List; 241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.regex.Matcher; 251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.regex.Pattern; 261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia/** 281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * A formatter which formats phone numbers as they are entered. 291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 301524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * An AsYouTypeFormatter could be created by invoking the getAsYouTypeFormatter method of the 311524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * PhoneNumberUtil. After that digits could be added by invoking the inputDigit method on the 321524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * formatter instance, and the partially formatted phone number will be returned each time a digit 331524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * is added. The clear method could be invoked before a new number needs to be formatted. 341524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 351524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * See testAsYouTypeFormatterUS(), testAsYouTestFormatterGB() and testAsYouTypeFormatterDE() in 361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * PhoneNumberUtilTest.java for more details on how the formatter is to be used. 371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 381524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * @author Shaopeng Jia 391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiapublic class AsYouTypeFormatter { 411524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private StringBuffer currentOutput; 421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String formattingTemplate; 431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private StringBuffer accruedInput; 441524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private StringBuffer accruedInputWithoutFormatting; 457900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia private boolean ableToFormat = true; 467900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia private boolean isInternationalFormatting = false; 471524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); 481524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String defaultCountry; 497900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia private Phonemetadata.PhoneMetadata defaultMetaData; 501524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private PhoneMetadata currentMetaData; 511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // The digits that have not been entered yet will be represented by a \u2008, the punctuation 531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // space. 541524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String digitPlaceholder = "\u2008"; 551524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private Pattern digitPattern = Pattern.compile(digitPlaceholder); 561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private int lastMatchPosition = 0; 570b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia private boolean rememberPosition = false; 580b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia private int positionRemembered = 0; 590b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia private int originalPosition = 0; 601524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private Pattern nationalPrefixForParsing; 611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private Pattern internationalPrefix; 621524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private StringBuffer prefixBeforeNationalNumber; 631524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private StringBuffer nationalNumber; 640b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // No formatting will be applied when any of the character in the following character class is 650b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // entered by users. 660b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia private final Pattern UNSUPPORTED_SYNTAX = Pattern.compile("[- *#;,.()/a-zA-Z]"); 670199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia private final Pattern CHARACTER_CLASS_PATTERN = Pattern.compile("\\[([^\\[\\]])*\\]"); 680199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia private final Pattern STANDALONE_DIGIT_PATTERN = Pattern.compile("\\d(?=[^,}][^,}])"); 691524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 701524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia /** 711524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Constructs a light-weight formatter which does no formatting, but outputs exactly what is 721524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * fed into the inputDigit method. 731524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 741524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * @param regionCode the country/region where the phone number is being entered 751524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 761524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia AsYouTypeFormatter(String regionCode) { 771524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInput = new StringBuffer(); 781524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInputWithoutFormatting = new StringBuffer(); 791524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia currentOutput = new StringBuffer(); 801524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia prefixBeforeNationalNumber = new StringBuffer(); 811524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nationalNumber = new StringBuffer(); 821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia defaultCountry = regionCode; 831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia initializeCountrySpecificInfo(defaultCountry); 841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia defaultMetaData = currentMetaData; 851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 861524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 871524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private void initializeCountrySpecificInfo(String regionCode) { 881524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia currentMetaData = phoneUtil.getMetadataForRegion(regionCode); 891524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nationalPrefixForParsing = 901524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Pattern.compile(currentMetaData.getNationalPrefixForParsing()); 911524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia internationalPrefix = 921524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Pattern.compile("\\+|" + currentMetaData.getInternationalPrefix()); 931524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 941524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 951524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private void chooseFormatAndCreateTemplate(String leadingFourDigitsOfNationalNumber) { 961524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia List<NumberFormat> formatList = getAvailableFormats(leadingFourDigitsOfNationalNumber); 971524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (formatList.size() < 1) { 981524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = false; 991524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 1001524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // When there are multiple available formats, the formatter uses the first format. 1011524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia NumberFormat format = formatList.get(0); 1021524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!createFormattingTemplate(format)) { 1031524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = false; 1041524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 1051524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia currentOutput = new StringBuffer(formattingTemplate); 1061524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1071524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private List<NumberFormat> getAvailableFormats(String leadingFourDigits) { 1111524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia List<NumberFormat> matchedList = new ArrayList<NumberFormat>(); 1127900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia List<NumberFormat> formatList = 1137900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia (isInternationalFormatting && currentMetaData.getIntlNumberFormatCount() > 0) 1147900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia ? currentMetaData.getIntlNumberFormatList() 1157900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia : currentMetaData.getNumberFormatList(); 1161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia for (NumberFormat format : formatList) { 1171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (format.hasLeadingDigits()) { 1181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Pattern leadingDigitsPattern = Pattern.compile(format.getLeadingDigits()); 1191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Matcher m = leadingDigitsPattern.matcher(leadingFourDigits); 1201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (m.lookingAt()) { 1211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia matchedList.add(format); 1221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 1241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia matchedList.add(format); 1251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return matchedList; 1281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1301524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private boolean createFormattingTemplate(NumberFormat format) { 1311524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String numberFormat = format.getFormat(); 1321524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String numberPattern = format.getPattern(); 1331524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1340199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia // The formatter doesn't format numbers when numberPattern contains "|", e.g. 1350199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia // (20|3)\d{4}. In those cases we quickly return. 1360199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia if (numberPattern.indexOf('|') != -1) { 1371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return false; 1381524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Replace anything in the form of [..] with \d 1410199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia numberPattern = CHARACTER_CLASS_PATTERN.matcher(numberPattern).replaceAll("\\\\d"); 1421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Replace any standalone digit (not the one in d{}) with \d 1440199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia numberPattern = STANDALONE_DIGIT_PATTERN.matcher(numberPattern).replaceAll("\\\\d"); 1451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia formattingTemplate = getFormattingTemplate(numberPattern, numberFormat); 1471524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return true; 1481524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1501524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Gets a formatting template which could be used to efficiently format a partial number where 1511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // digits are added one by one. 1521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String getFormattingTemplate(String numberPattern, String numberFormat) { 1531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Creates a phone number consisting only of the digit 9 that matches the 1541524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // numberPattern by applying the pattern to the longestPhoneNumber string. 1551524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String longestPhoneNumber = "999999999999999"; 1561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Matcher m = Pattern.compile(numberPattern).matcher(longestPhoneNumber); 1571524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia m.find(); // this will always succeed 1581524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String aPhoneNumber = m.group(); 1591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Formats the number according to numberFormat 1601524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String template = aPhoneNumber.replaceAll(numberPattern, numberFormat); 1611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Replaces each digit with character digitPlaceholder 1621524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia template = template.replaceAll("9", digitPlaceholder); 1631524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return template; 1641524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1651524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1661524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia /** 1671524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Clears the internal state of the formatter, so it could be reused. 1681524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 1691524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia public void clear() { 1700199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia accruedInput.setLength(0); 1710199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia accruedInputWithoutFormatting.setLength(0); 1720199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia currentOutput.setLength(0); 1731524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia lastMatchPosition = 0; 1740199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia prefixBeforeNationalNumber.setLength(0); 1750199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia nationalNumber.setLength(0); 1761524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = true; 1770b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = 0; 1780b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia originalPosition = 0; 1797900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia isInternationalFormatting = false; 1801524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!currentMetaData.equals(defaultMetaData)) { 1811524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia initializeCountrySpecificInfo(defaultCountry); 1821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 1851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia /** 1861524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Formats a phone number on-the-fly as each digit is entered. 1871524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 1881524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * @param nextChar the most recently entered digit of a phone number. Formatting characters are 1891524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * allowed, but they are removed from the result. Full width digits and Arabic-indic digits 1901524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * are allowed, and will be shown as they are. 1910199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia * @return the partially formatted phone number. 1921524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 1931524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia public String inputDigit(char nextChar) { 1941524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInput.append(nextChar); 1950b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia rememberPosition(); 1960199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia if (UNSUPPORTED_SYNTAX.matcher(Character.toString(nextChar)).matches()) { 1971524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = false; 1981524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 1991524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!ableToFormat) { 2000b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (positionRemembered > 0 && currentOutput.length() > 0) { 2010b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = originalPosition; 2020b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia currentOutput.setLength(0); 2030b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2041524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return accruedInput.toString(); 2051524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2061524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 2071524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar); 2081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 2091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // We start to attempt to format only when at least 6 digits (the plus sign is counted as a 2101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // digit as well for this purpose) have been entered. 2111524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia switch (accruedInputWithoutFormatting.length()) { 2121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 0: // this is the case where the first few inputs are neither digits nor the plus sign. 2131524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 1: 2141524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 2: 2151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 3: 2161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 4: 2171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 5: 2181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return accruedInput.toString(); 2191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia case 6: 2201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!extractIddAndValidCountryCode()) { 2211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = false; 2221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return accruedInput.toString(); 2231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia removeNationalPrefixFromNationalNumber(); 2251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return attemptToChooseFormattingPattern(); 2261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia default: 2271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (nationalNumber.length() > 4) { // The formatting pattern is already chosen. 2280b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia String temp = inputDigitHelper(nextChar); 2290b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia return ableToFormat 2300b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia ? prefixBeforeNationalNumber + temp 2310b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia : temp; 2321524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 2331524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return attemptToChooseFormattingPattern(); 2341524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2351524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 2380b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia private void rememberPosition() { 2390b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (rememberPosition) { 2400b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = accruedInput.length(); 2410b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia originalPosition = positionRemembered; 2420b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2430b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2440b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia 2450b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia /** 2460b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia * Same as inputDigit, but remembers the position where nextChar is inserted, so that it could be 2470b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia * retrieved later by using getRememberedPosition(). The remembered position will be automatically 2480b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia * adjusted if additional formatting characters are later inserted/removed in front of nextChar. 2490b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia */ 2500b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia public String inputDigitAndRememberPosition(char nextChar) { 2510b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia rememberPosition = true; 2520b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia String result = inputDigit(nextChar); 2530b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia rememberPosition = false; 2540b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia return result; 2550b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2560b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia 2570b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia /** 2580b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia * Returns the current position in the partially formatted phone number of the character which was 2590b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia * previously passed in as the parameter of inputDigitAndRememberPosition(). 2600b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia */ 2610b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia public int getRememberedPosition() { 2620b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia return positionRemembered; 2630b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2640b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia 2651524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Attempts to set the formatting template and returns a string which contains the formatted 2661524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // version of the digits entered so far. 2671524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String attemptToChooseFormattingPattern() { 2681524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // We start to attempt to format only when as least 4 digits of national number (excluding 2691524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // national prefix) have been entered. 2701524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (nationalNumber.length() >= 4) { 2711524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia chooseFormatAndCreateTemplate(nationalNumber.substring(0, 4)); 2721524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return inputAccruedNationalNumber(); 2731524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 2740b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (rememberPosition) { 2750b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = prefixBeforeNationalNumber.length() + nationalNumber.length(); 2760b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2771524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return prefixBeforeNationalNumber + nationalNumber.toString(); 2781524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2791524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2801524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 2811524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted 2821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // string in the end. 2831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String inputAccruedNationalNumber() { 2841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia int lengthOfNationalNumber = nationalNumber.length(); 2851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (lengthOfNationalNumber > 0) { 2860b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // The positionRemembered should be only adjusted once in the loop that follows. 2870b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia Boolean positionAlreadyAdjusted = false; 2881524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia for (int i = 0; i < lengthOfNationalNumber - 1; i++) { 2890b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia String temp = inputDigitHelper(nationalNumber.charAt(i)); 2900b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (!positionAlreadyAdjusted && 2910b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered - prefixBeforeNationalNumber.length() == i + 1) { 2920b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = prefixBeforeNationalNumber.length() + temp.length(); 2930b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionAlreadyAdjusted = true; 2940b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 2951524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 2960b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia String temp = inputDigitHelper(nationalNumber.charAt(lengthOfNationalNumber - 1)); 2970b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia return ableToFormat 2980b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia ? prefixBeforeNationalNumber + temp 2990b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia : temp; 3001524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 3010b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (rememberPosition) { 3020b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = prefixBeforeNationalNumber.length(); 3030b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 3041524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return prefixBeforeNationalNumber.toString(); 3051524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3061524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3071524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 3081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private void removeNationalPrefixFromNationalNumber() { 3091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia int startOfNationalNumber = 0; 31094c2440dc41689b7d9c169edf5089eeebf7527d7Shaopeng Jia if (currentMetaData.getCountryCode() == 1 && nationalNumber.charAt(0) == '1') { 31194c2440dc41689b7d9c169edf5089eeebf7527d7Shaopeng Jia startOfNationalNumber = 1; 3120b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia prefixBeforeNationalNumber.append("1"); 3130b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // Since a space will be inserted after the national prefix in this case, we increase the 3140b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // remembered position by 1 for anything that is after the national prefix. 3150b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (positionRemembered > prefixBeforeNationalNumber.length()) { 3160b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered++; 3170b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 3180b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia prefixBeforeNationalNumber.append(" "); 31994c2440dc41689b7d9c169edf5089eeebf7527d7Shaopeng Jia } else if (currentMetaData.hasNationalPrefix()) { 3201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Matcher m = nationalPrefixForParsing.matcher(nationalNumber); 3211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (m.lookingAt()) { 3221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia startOfNationalNumber = m.end(); 3231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber)); 3241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nationalNumber.delete(0, startOfNationalNumber); 3271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 3291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia /** 3301524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * Extracts IDD, plus sign and country code to prefixBeforeNationalNumber when they are available, 3311524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * and places the remaining input into nationalNumber. 3321524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * 3331524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * @return false when accruedInputWithoutFormatting begins with the plus sign or valid IDD for 3341524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * defaultCountry, but the sequence of digits after that does not form a valid country code. 3351524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * It returns true for all other cases. 3361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */ 3371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private boolean extractIddAndValidCountryCode() { 3380199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia nationalNumber.setLength(0); 3391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting); 3401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (iddMatcher.lookingAt()) { 3417900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia isInternationalFormatting = true; 3421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia int startOfCountryCode = iddMatcher.end(); 3431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia StringBuffer numberIncludeCountryCode = 3441524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia new StringBuffer(accruedInputWithoutFormatting.substring(startOfCountryCode)); 3451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia int countryCode = phoneUtil.extractCountryCode(numberIncludeCountryCode, nationalNumber); 3461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (countryCode == 0) { 3471524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return false; 3481524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 3491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode); 3501524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!newRegionCode.equals(defaultCountry)) { 3511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia initializeCountrySpecificInfo(newRegionCode); 3521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia prefixBeforeNationalNumber.append( 3541524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInputWithoutFormatting.substring(0, startOfCountryCode)); 3551524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN ) { 3560b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (positionRemembered > prefixBeforeNationalNumber.length()) { 3570b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // Since a space will be inserted in front of the country code in this case, we increase 3580b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // the remembered position by 1. 3590b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered++; 3600b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 3611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia prefixBeforeNationalNumber.append(" "); 3621524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3630b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia String countryCodeString = Integer.toString(countryCode); 3640b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (positionRemembered > prefixBeforeNationalNumber.length() + countryCodeString.length()) { 3650b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // Since a space will be inserted after the country code in this case, we increase the 3660b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia // remembered position by 1. 3670b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered++; 3680b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 3690b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia prefixBeforeNationalNumber.append(countryCodeString).append(" "); 3701524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3711524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { 3720199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia nationalNumber.setLength(0); 3730199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia nationalNumber.append(accruedInputWithoutFormatting); 3741524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3751524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return true; 3761524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3771524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 3781524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar 3791524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first 3801524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // normalized to the ASCII version. The return value is nextChar itself, or its normalized 3811524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia // version, if nextChar is a digit in non-ASCII format. 3821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private char normalizeAndAccrueDigitsAndPlusSign(char nextChar) { 3831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (nextChar == PhoneNumberUtil.PLUS_SIGN) { 3841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInputWithoutFormatting.append(nextChar); 3851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3861524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 3871524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (PhoneNumberUtil.DIGIT_MAPPINGS.containsKey(nextChar)) { 3881524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nextChar = PhoneNumberUtil.DIGIT_MAPPINGS.get(nextChar); 3891524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia accruedInputWithoutFormatting.append(nextChar); 3901524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia nationalNumber.append(nextChar); 3911524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3921524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return nextChar; 3931524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3941524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 3951524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia private String inputDigitHelper(char nextChar) { 3961524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (!PhoneNumberUtil.DIGIT_MAPPINGS.containsKey(nextChar)) { 3971524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia return currentOutput.toString(); 3981524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 3991524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia 4001524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia Matcher digitMatcher = digitPattern.matcher(currentOutput); 4011524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia if (digitMatcher.find(lastMatchPosition)) { 4021524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia currentOutput = new StringBuffer(digitMatcher.replaceFirst(Character.toString(nextChar))); 4031524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia lastMatchPosition = digitMatcher.start(); 4040b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (rememberPosition) { 4050b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = prefixBeforeNationalNumber.length() + lastMatchPosition + 1; 4060b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 4075803259dcdfb1a04cc353e9ef02c1a3aef6a6176Shaopeng Jia return currentOutput.substring(0, lastMatchPosition + 1); 4081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } else { // More digits are entered than we could handle. 4091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia currentOutput.append(nextChar); 4101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia ableToFormat = false; 4110b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia if (positionRemembered > 0) { 4120b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia positionRemembered = originalPosition; 4130b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia currentOutput.setLength(0); 4140b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia } 4150b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia return accruedInput.toString(); 4161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 4171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia } 4181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia} 419