AsYouTypeFormatter.java revision b03a14984ad9b0d8b88337ca714cb831233b99c3
11524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia/*
2ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia * Copyright (C) 2009 The Libphonenumber Authors
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
1793f6965c2c041ac707bf1b3bcf5a3f60e452f421Shaopeng Jiapackage com.android.i18n.phonenumbers;
181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
1993f6965c2c041ac707bf1b3bcf5a3f60e452f421Shaopeng Jiaimport com.android.i18n.phonenumbers.Phonemetadata.NumberFormat;
2093f6965c2c041ac707bf1b3bcf5a3f60e452f421Shaopeng Jiaimport com.android.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.ArrayList;
23df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jiaimport java.util.Iterator;
241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.List;
251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.regex.Matcher;
261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiaimport java.util.regex.Pattern;
271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia/**
291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * A formatter which formats phone numbers as they are entered.
301524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia *
31372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * <p>An AsYouTypeFormatter can be created by invoking
32372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * {@link PhoneNumberUtil#getAsYouTypeFormatter}. After that, digits can be added by invoking
33372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * {@link #inputDigit} on the formatter instance, and the partially formatted phone number will be
34372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * returned each time a digit is added. {@link #clear} can be invoked before formatting a new
35372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * number.
361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia *
37372bff8dd464574d36737d47e495cad14346653cShaopeng Jia * <p>See the unittests for more details on how the formatter is to be used.
381524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia *
391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia * @author Shaopeng Jia
401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia */
411524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jiapublic class AsYouTypeFormatter {
42df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String currentOutput = "";
43372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private StringBuilder formattingTemplate = new StringBuilder();
44df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // The pattern from numberFormat that is currently used to create formattingTemplate.
45df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String currentFormattingPattern = "";
46372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private StringBuilder accruedInput = new StringBuilder();
47372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private StringBuilder accruedInputWithoutFormatting = new StringBuilder();
48ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // This indicates whether AsYouTypeFormatter is currently doing the formatting.
497900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia  private boolean ableToFormat = true;
50ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // Set to true when users enter their own formatting. AsYouTypeFormatter will do no formatting at
51ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // all when this is set to true.
52ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private boolean inputHasFormatting = false;
53203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // This is set to true when we know the user is entering a full national significant number, since
54203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // we have either detected a national prefix or an international dialing prefix. When this is
55203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // true, we will no longer use local number formatting patterns.
56203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private boolean isCompleteNumber = false;
57372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private boolean isExpectingCountryCallingCode = false;
581524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private String defaultCountry;
60372bff8dd464574d36737d47e495cad14346653cShaopeng Jia
61203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // Character used when appropriate to separate a prefix, such as a long NDD or a country calling
62203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // code, from the national number.
63203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private static final char SEPARATOR_BEFORE_NATIONAL_NUMBER = ' ';
64372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private static final PhoneMetadata EMPTY_METADATA =
65372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      new PhoneMetadata().setInternationalPrefix("NA");
66bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private PhoneMetadata defaultMetadata;
67bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private PhoneMetadata currentMetadata;
681524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
694b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // A pattern that is used to match character classes in regular expressions. An example of a
704b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // character class is [1-4].
7152699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia  private static final Pattern CHARACTER_CLASS_PATTERN = Pattern.compile("\\[([^\\[\\]])*\\]");
724b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // Any digit in a regular expression that actually denotes a digit. For example, in the regular
734b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // expression 80[0-2]\d{6,10}, the first 2 digits (8 and 0) are standalone digits, but the rest
744b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // are not.
754b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // Two look-aheads are needed because the number following \\d could be a two-digit number, since
764b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // the phone number can be as long as 15 digits.
774b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  private static final Pattern STANDALONE_DIGIT_PATTERN = Pattern.compile("\\d(?=[^,}][^,}])");
784b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia
79372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // A pattern that is used to determine if a numberFormat under availableFormats is eligible to be
80372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // used by the AYTF. It is eligible when the format element under numberFormat contains groups of
81372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // the dollar sign followed by a single digit, separated by valid phone number punctuation. This
82372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // prevents invalid punctuation (such as the star sign in Israeli star numbers) getting into the
83372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // output of the AYTF.
84372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private static final Pattern ELIGIBLE_FORMAT_PATTERN =
85372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      Pattern.compile("[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*" +
86372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          "(\\$\\d" + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*)+");
87203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // A set of characters that, if found in a national prefix formatting rules, are an indicator to
88203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  // us that we should separate the national prefix from the number when formatting.
89203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private static final Pattern NATIONAL_PREFIX_SEPARATORS_PATTERN = Pattern.compile("[- ]");
90372bff8dd464574d36737d47e495cad14346653cShaopeng Jia
91df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // This is the minimum length of national number accrued that is required to trigger the
92df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // formatter. The first element of the leadingDigitsPattern of each numberFormat contains a
93df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // regular expression that matches up to this number of digits.
94df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private static final int MIN_LEADING_DIGITS_LENGTH = 3;
95df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
961524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // The digits that have not been entered yet will be represented by a \u2008, the punctuation
971524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // space.
98203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private static final String DIGIT_PLACEHOLDER = "\u2008";
99203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private static final Pattern DIGIT_PATTERN = Pattern.compile(DIGIT_PLACEHOLDER);
1001524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private int lastMatchPosition = 0;
1014b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as
1024b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  // found in the original sequence of characters the user entered.
1030b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  private int originalPosition = 0;
104df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as
105df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // found in accruedInputWithoutFormatting.
106df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private int positionToRemember = 0;
107ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // This contains anything that has been entered so far preceding the national significant number,
108ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // and it is formatted (e.g. with space inserted). For example, this can contain IDD, country
109ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // code, and/or NDD, etc.
110372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private StringBuilder prefixBeforeNationalNumber = new StringBuilder();
111203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private boolean shouldAddSpaceAfterNationalPrefix = false;
112ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // This contains the national prefix that has been extracted. It contains only digits without
113ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // formatting.
114b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  private String extractedNationalPrefix = "";
115372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private StringBuilder nationalNumber = new StringBuilder();
116df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private List<NumberFormat> possibleFormats = new ArrayList<NumberFormat>();
117df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
118df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // A cache for frequently used country-specific regular expressions.
119df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private RegexCache regexCache = new RegexCache(64);
1201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
1211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
12252699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia   * Constructs an as-you-type formatter. Should be obtained from {@link
12352699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia   * PhoneNumberUtil#getAsYouTypeFormatter}.
1241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   *
1251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   * @param regionCode  the country/region where the phone number is being entered
1261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
1271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  AsYouTypeFormatter(String regionCode) {
1281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    defaultCountry = regionCode;
129bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    currentMetadata = getMetadataForRegion(defaultCountry);
130bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    defaultMetadata = currentMetadata;
1311524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
1321524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
133249f28fc9d984e6a7d5ff05ca78d8e7ce280eb54Shaopeng Jia  // The metadata needed by this class is the same for all regions sharing the same country calling
134249f28fc9d984e6a7d5ff05ca78d8e7ce280eb54Shaopeng Jia  // code. Therefore, we return the metadata for "main" region for this country calling code.
135372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private PhoneMetadata getMetadataForRegion(String regionCode) {
136249f28fc9d984e6a7d5ff05ca78d8e7ce280eb54Shaopeng Jia    int countryCallingCode = phoneUtil.getCountryCodeForRegion(regionCode);
137249f28fc9d984e6a7d5ff05ca78d8e7ce280eb54Shaopeng Jia    String mainCountry = phoneUtil.getRegionCodeForCountryCode(countryCallingCode);
138249f28fc9d984e6a7d5ff05ca78d8e7ce280eb54Shaopeng Jia    PhoneMetadata metadata = phoneUtil.getMetadataForRegion(mainCountry);
139372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    if (metadata != null) {
140372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      return metadata;
14152699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    }
142372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    // Set to a default instance of the metadata. This allows us to function with an incorrect
143372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    // region code, even if formatting only works for numbers specified with "+".
144372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    return EMPTY_METADATA;
1451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
1461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
147df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  // Returns true if a new template is created as opposed to reusing the existing template.
148df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private boolean maybeCreateNewTemplate() {
149df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // When there are multiple available formats, the formatter uses the first format where a
150df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // formatting template could be created.
151d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    Iterator<NumberFormat> it = possibleFormats.iterator();
152d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    while (it.hasNext()) {
153d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      NumberFormat numberFormat = it.next();
154df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      String pattern = numberFormat.getPattern();
155df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (currentFormattingPattern.equals(pattern)) {
156df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        return false;
157df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
158df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (createFormattingTemplate(numberFormat)) {
159df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        currentFormattingPattern = pattern;
160203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        shouldAddSpaceAfterNationalPrefix =
161203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia            NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher(
162203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia                numberFormat.getNationalPrefixFormattingRule()).find();
163ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        // With a new formatting template, the matched position using the old template needs to be
164ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        // reset.
165ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        lastMatchPosition = 0;
166df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        return true;
167d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      } else {  // Remove the current number format from possibleFormats.
168d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia        it.remove();
1691524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      }
1701524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
171df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    ableToFormat = false;
172df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return false;
1731524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
1741524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
175df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private void getAvailableFormats(String leadingThreeDigits) {
1767900ea273b8c33b3c6f70d7dd559127938d0fc3dShaopeng Jia    List<NumberFormat> formatList =
177bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        (isCompleteNumber && currentMetadata.intlNumberFormatSize() > 0)
178bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        ? currentMetadata.intlNumberFormats()
179bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        : currentMetadata.numberFormats();
180bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    boolean nationalPrefixIsUsedByCountry = currentMetadata.hasNationalPrefix();
181372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    for (NumberFormat format : formatList) {
182203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      if (!nationalPrefixIsUsedByCountry || isCompleteNumber ||
183203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          format.isNationalPrefixOptionalWhenFormatting() ||
184203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          phoneUtil.formattingRuleHasFirstGroupOnly(format.getNationalPrefixFormattingRule())) {
185203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        if (isFormatEligible(format.getFormat())) {
186203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          possibleFormats.add(format);
187203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        }
188372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      }
189372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    }
190df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    narrowDownPossibleFormats(leadingThreeDigits);
191df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  }
192df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
193372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private boolean isFormatEligible(String format) {
194372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    return ELIGIBLE_FORMAT_PATTERN.matcher(format).matches();
195372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  }
196372bff8dd464574d36737d47e495cad14346653cShaopeng Jia
197df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private void narrowDownPossibleFormats(String leadingDigits) {
198372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    int indexOfLeadingDigitsPattern = leadingDigits.length() - MIN_LEADING_DIGITS_LENGTH;
199df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    Iterator<NumberFormat> it = possibleFormats.iterator();
200df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    while (it.hasNext()) {
201df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      NumberFormat format = it.next();
202372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      if (format.leadingDigitsPatternSize() > indexOfLeadingDigitsPattern) {
203df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        Pattern leadingDigitsPattern =
204df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia            regexCache.getPatternForRegex(
205df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia                format.getLeadingDigitsPattern(indexOfLeadingDigitsPattern));
206df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        Matcher m = leadingDigitsPattern.matcher(leadingDigits);
207df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        if (!m.lookingAt()) {
208df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          it.remove();
2091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        }
210df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      } // else the particular format has no more specific leadingDigitsPattern, and it should be
211df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        // retained.
2121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2131524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2141524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private boolean createFormattingTemplate(NumberFormat format) {
2161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String numberPattern = format.getPattern();
2171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2180199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    // The formatter doesn't format numbers when numberPattern contains "|", e.g.
2190199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    // (20|3)\d{4}. In those cases we quickly return.
2200199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    if (numberPattern.indexOf('|') != -1) {
2211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return false;
2221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Replace anything in the form of [..] with \d
2250199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    numberPattern = CHARACTER_CLASS_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
2261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Replace any standalone digit (not the one in d{}) with \d
2280199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    numberPattern = STANDALONE_DIGIT_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
229df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    formattingTemplate.setLength(0);
230372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    String tempTemplate = getFormattingTemplate(numberPattern, format.getFormat());
231d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    if (tempTemplate.length() > 0) {
23252699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      formattingTemplate.append(tempTemplate);
23352699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      return true;
23452699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    }
23552699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    return false;
2361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
238372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // Gets a formatting template which can be used to efficiently format a partial number where
2391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // digits are added one by one.
2401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private String getFormattingTemplate(String numberPattern, String numberFormat) {
2411524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Creates a phone number consisting only of the digit 9 that matches the
2421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // numberPattern by applying the pattern to the longestPhoneNumber string.
2431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String longestPhoneNumber = "999999999999999";
244df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    Matcher m = regexCache.getPatternForRegex(numberPattern).matcher(longestPhoneNumber);
2451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    m.find();  // this will always succeed
2461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String aPhoneNumber = m.group();
247d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    // No formatting template can be created if the number of digits entered so far is longer than
248d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    // the maximum the current formatting rule can accommodate.
249d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    if (aPhoneNumber.length() < nationalNumber.length()) {
250d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      return "";
251d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    }
2521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Formats the number according to numberFormat
2531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String template = aPhoneNumber.replaceAll(numberPattern, numberFormat);
254203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // Replaces each digit with character DIGIT_PLACEHOLDER
255203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    template = template.replaceAll("9", DIGIT_PLACEHOLDER);
2561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    return template;
2571524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2581524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
260372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Clears the internal state of the formatter, so it can be reused.
2611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
2621524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  public void clear() {
263df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = "";
2640199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    accruedInput.setLength(0);
2650199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    accruedInputWithoutFormatting.setLength(0);
266df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    formattingTemplate.setLength(0);
2671524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    lastMatchPosition = 0;
268df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentFormattingPattern = "";
2690199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    prefixBeforeNationalNumber.setLength(0);
270b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    extractedNationalPrefix = "";
2710199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    nationalNumber.setLength(0);
2721524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    ableToFormat = true;
273ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    inputHasFormatting = false;
274df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    positionToRemember = 0;
2750b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia    originalPosition = 0;
276203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    isCompleteNumber = false;
277372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    isExpectingCountryCallingCode = false;
278df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    possibleFormats.clear();
279203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    shouldAddSpaceAfterNationalPrefix = false;
280bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    if (!currentMetadata.equals(defaultMetadata)) {
281bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = getMetadataForRegion(defaultCountry);
2821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
285df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  /**
286df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * Formats a phone number on-the-fly as each digit is entered.
287df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *
288df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @param nextChar  the most recently entered digit of a phone number. Formatting characters are
289372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     allowed, but as soon as they are encountered this method formats the number as entered and
290372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will
291372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     be shown as they are.
292df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @return  the partially formatted phone number.
293df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   */
2944b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  public String inputDigit(char nextChar) {
295df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = inputDigitWithOptionToRememberPosition(nextChar, false);
296df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutput;
2974b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  }
2984b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia
2991524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
300372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Same as {@link #inputDigit}, but remembers the position where {@code nextChar} is inserted, so
301372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * that it can be retrieved later by using {@link #getRememberedPosition}. The remembered
302372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * position will be automatically adjusted if additional formatting characters are later
303372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * inserted/removed in front of {@code nextChar}.
3041524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
3054b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  public String inputDigitAndRememberPosition(char nextChar) {
306df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = inputDigitWithOptionToRememberPosition(nextChar, true);
307df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutput;
3084b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  }
3094b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia
31052699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia  @SuppressWarnings("fallthrough")
3114b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  private String inputDigitWithOptionToRememberPosition(char nextChar, boolean rememberPosition) {
3121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    accruedInput.append(nextChar);
3134b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia    if (rememberPosition) {
314df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      originalPosition = accruedInput.length();
3154b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia    }
316f7e0224b862054893f28d2736b3f6804d9935886Shaopeng Jia    // We do formatting on-the-fly only when each character entered is either a digit, or a plus
31716b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    // sign (accepted at the start of the number only).
31816b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    if (!isDigitOrLeadingPlusSign(nextChar)) {
3191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      ableToFormat = false;
320ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      inputHasFormatting = true;
321ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    } else {
322ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar, rememberPosition);
3231524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (!ableToFormat) {
325ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // When we are unable to format because of reasons other than that formatting chars have been
326ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able
327ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // to do formatting again after extracting them.
328ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      if (inputHasFormatting) {
329ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        return accruedInput.toString();
330ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      } else if (attemptToExtractIdd()) {
331ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        if (attemptToExtractCountryCallingCode()) {
332ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia          return attemptToChoosePatternWithPrefixExtracted();
333ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        }
334ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      } else if (ableToExtractLongerNdd()) {
335ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        // Add an additional space to separate long NDD and national significant number for
336203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        // readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want
337203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        // this to change later when we choose formatting templates.
338203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
339ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        return attemptToChoosePatternWithPrefixExtracted();
340ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      }
3411524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return accruedInput.toString();
3421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
344df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus
345df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // sign is counted as a digit as well for this purpose) have been entered.
3461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    switch (accruedInputWithoutFormatting.length()) {
347372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      case 0:
3481524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 1:
3491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 2:
350df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        return accruedInput.toString();
3511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 3:
352df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        if (attemptToExtractIdd()) {
353372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          isExpectingCountryCallingCode = true;
354ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        } else {  // No IDD or plus sign is found, might be entering in national format.
355b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia          extractedNationalPrefix = removeNationalPrefixFromNationalNumber();
356df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return attemptToChooseFormattingPattern();
357df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        }
358ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      default:
359372bff8dd464574d36737d47e495cad14346653cShaopeng Jia        if (isExpectingCountryCallingCode) {
360372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          if (attemptToExtractCountryCallingCode()) {
361372bff8dd464574d36737d47e495cad14346653cShaopeng Jia            isExpectingCountryCallingCode = false;
362df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
363df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return prefixBeforeNationalNumber + nationalNumber.toString();
364df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        }
365df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        if (possibleFormats.size() > 0) {  // The formatting pattern is already chosen.
366df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          String tempNationalNumber = inputDigitHelper(nextChar);
367df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          // See if the accrued digits can be formatted properly already. If not, use the results
368df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          // from inputDigitHelper, which does formatting based on the formatting pattern chosen.
369df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          String formattedNumber = attemptToFormatAccruedDigits();
370df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          if (formattedNumber.length() > 0) {
371df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia            return formattedNumber;
372df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
373df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          narrowDownPossibleFormats(nationalNumber.toString());
374df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          if (maybeCreateNewTemplate()) {
375df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia            return inputAccruedNationalNumber();
376df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
3770b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia          return ableToFormat
378203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia             ? appendNationalNumber(tempNationalNumber)
379f3c6df010e7bc8ead25ba577ae09474b70d08adcShaopeng Jia             : accruedInput.toString();
3801524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        } else {
381df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return attemptToChooseFormattingPattern();
3821524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        }
3831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3841524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
3851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
386ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private String attemptToChoosePatternWithPrefixExtracted() {
387ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    ableToFormat = true;
388ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    isExpectingCountryCallingCode = false;
389ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    possibleFormats.clear();
390ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    return attemptToChooseFormattingPattern();
391ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  }
392ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia
393b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  // @VisibleForTesting
394b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  String getExtractedNationalPrefix() {
395b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    return extractedNationalPrefix;
396b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  }
397b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia
398ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result
399ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // in a number we can format, we try to see if we can extract a longer version here.
400ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private boolean ableToExtractLongerNdd() {
401b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    if (extractedNationalPrefix.length() > 0) {
402ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // Put the extracted NDD back to the national number before attempting to extract a new NDD.
403b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia      nationalNumber.insert(0, extractedNationalPrefix);
404ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set
40577aadd284847681bd66af639636c2fa43e418c2bShaopeng Jia      // it to empty string because people sometimes incorrectly enter national prefix after the
40677aadd284847681bd66af639636c2fa43e418c2bShaopeng Jia      // country code, e.g. +44 (0)20-1234-5678.
407b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia      int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(extractedNationalPrefix);
408ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      prefixBeforeNationalNumber.setLength(indexOfPreviousNdd);
409ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    }
410b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    return !extractedNationalPrefix.equals(removeNationalPrefixFromNationalNumber());
411ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  }
412ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia
41316b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia  private boolean isDigitOrLeadingPlusSign(char nextChar) {
41416b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    return Character.isDigit(nextChar) ||
41516b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia        (accruedInput.length() == 1 &&
41616b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia         PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches());
41716b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia  }
41816b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia
419203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
420203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Check to see if there is an exact pattern match for these digits. If so, we should use this
421203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * instead of any other formatting template whose leadingDigitsPattern also matches the input.
422203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
423df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  String attemptToFormatAccruedDigits() {
424203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    for (NumberFormat numberFormat : possibleFormats) {
425203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      Matcher m = regexCache.getPatternForRegex(numberFormat.getPattern()).matcher(nationalNumber);
426df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (m.matches()) {
427203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        shouldAddSpaceAfterNationalPrefix =
428203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia            NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher(
429203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia                numberFormat.getNationalPrefixFormattingRule()).find();
430203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        String formattedNumber = m.replaceAll(numberFormat.getFormat());
431203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        return appendNationalNumber(formattedNumber);
432df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
4330b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia    }
434df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return "";
4350b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  }
4360b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia
4370b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  /**
4380b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia   * Returns the current position in the partially formatted phone number of the character which was
439372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * previously passed in as the parameter of {@link #inputDigitAndRememberPosition}.
4400b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia   */
4410b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  public int getRememberedPosition() {
442df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (!ableToFormat) {
443df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return originalPosition;
444df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
44552699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    int accruedInputIndex = 0, currentOutputIndex = 0;
446372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    while (accruedInputIndex < positionToRemember && currentOutputIndex < currentOutput.length()) {
447df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (accruedInputWithoutFormatting.charAt(accruedInputIndex) ==
448df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          currentOutput.charAt(currentOutputIndex)) {
449df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        accruedInputIndex++;
450df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
451372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      currentOutputIndex++;
452df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
453df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutputIndex;
4540b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  }
4550b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia
456203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
457203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Combines the national number with any prefix (IDD/+ and country code or national prefix) that
458203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * was collected. A space will be inserted between them if the current formatting template
459203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * indicates this to be suitable.
460203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
461203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private String appendNationalNumber(String nationalNumber) {
462203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    int prefixBeforeNationalNumberLength = prefixBeforeNationalNumber.length();
463203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    if (shouldAddSpaceAfterNationalPrefix && prefixBeforeNationalNumberLength > 0 &&
464203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.charAt(prefixBeforeNationalNumberLength - 1)
465203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia            != SEPARATOR_BEFORE_NATIONAL_NUMBER) {
466203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // We want to add a space after the national prefix if the national prefix formatting rule
467203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // indicates that this would normally be done, with the exception of the case where we already
468203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // appended a space because the NDD was surprisingly long.
469203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return new String(prefixBeforeNationalNumber) + SEPARATOR_BEFORE_NATIONAL_NUMBER
470203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          + nationalNumber;
471203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    } else {
472203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return prefixBeforeNationalNumber + nationalNumber;
473203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    }
474203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  }
475203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia
476203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
477203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Attempts to set the formatting template and returns a string which contains the formatted
478203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * version of the digits entered so far.
479203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
480df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String attemptToChooseFormattingPattern() {
481bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national
482df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // number (excluding national prefix) have been entered.
483df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) {
484df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      getAvailableFormats(nationalNumber.substring(0, MIN_LEADING_DIGITS_LENGTH));
485bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // See if the accrued digits can be formatted properly already.
486bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      String formattedNumber = attemptToFormatAccruedDigits();
487bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      if (formattedNumber.length() > 0) {
488bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        return formattedNumber;
489bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      }
49096a7214cdabf08f53f5b1a560304601c9f65e0b9Shaopeng Jia      return maybeCreateNewTemplate() ? inputAccruedNationalNumber() : accruedInput.toString();
4911524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    } else {
492203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return appendNationalNumber(nationalNumber.toString());
4931524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
4941524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
4951524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
496203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
497203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted
498203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * string in the end.
499203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
500df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String inputAccruedNationalNumber() {
5011524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    int lengthOfNationalNumber = nationalNumber.length();
5021524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (lengthOfNationalNumber > 0) {
5034b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia      String tempNationalNumber = "";
5044b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia      for (int i = 0; i < lengthOfNationalNumber; i++) {
505df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        tempNationalNumber = inputDigitHelper(nationalNumber.charAt(i));
5061524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      }
507203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return ableToFormat ? appendNationalNumber(tempNationalNumber) : accruedInput.toString();
5081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    } else {
5091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return prefixBeforeNationalNumber.toString();
5101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
5111524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
5121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
513203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
514203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Returns true if the current country is a NANPA country and the national number begins with
515203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * the national prefix.
516203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
517203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private boolean isNanpaNumberWithNationalPrefix() {
518203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is
519203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // that national significant numbers in NANPA always start with [2-9] after the national prefix.
520203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the
521203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // national prefix.
522bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    return (currentMetadata.getCountryCode() == 1) && (nationalNumber.charAt(0) == '1') &&
523203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia           (nationalNumber.charAt(1) != '0') && (nationalNumber.charAt(1) != '1');
524203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  }
525203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia
526ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // Returns the national prefix extracted, or an empty string if it is not present.
527ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private String removeNationalPrefixFromNationalNumber() {
5281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    int startOfNationalNumber = 0;
529203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    if (isNanpaNumberWithNationalPrefix()) {
53094c2440dc41689b7d9c169edf5089eeebf7527d7Shaopeng Jia      startOfNationalNumber = 1;
531203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      prefixBeforeNationalNumber.append('1').append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
532203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      isCompleteNumber = true;
533bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    } else if (currentMetadata.hasNationalPrefixForParsing()) {
534372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      Pattern nationalPrefixForParsing =
535bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia          regexCache.getPatternForRegex(currentMetadata.getNationalPrefixForParsing());
5361524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      Matcher m = nationalPrefixForParsing.matcher(nationalNumber);
537bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // Since some national prefix patterns are entirely optional, check that a national prefix
538bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // could actually be extracted.
539bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      if (m.lookingAt() && m.end() > 0) {
540f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // When the national prefix is detected, we use international formatting rules instead of
541f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // national ones, because national formatting rules could contain local formatting rules
542f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // for numbers entered without area code.
543203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        isCompleteNumber = true;
5441524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        startOfNationalNumber = m.end();
5451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber));
5461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      }
5471524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
548ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    String nationalPrefix = nationalNumber.substring(0, startOfNationalNumber);
5491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    nationalNumber.delete(0, startOfNationalNumber);
550ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    return nationalPrefix;
5511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
5521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
5531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
554df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * Extracts IDD and plus sign to prefixBeforeNationalNumber when they are available, and places
555df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * the remaining input into nationalNumber.
5561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   *
557df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @return  true when accruedInputWithoutFormatting begins with the plus sign or valid IDD for
558df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *     defaultCountry.
5591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
560df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private boolean attemptToExtractIdd() {
561372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    Pattern internationalPrefix =
562372bff8dd464574d36737d47e495cad14346653cShaopeng Jia        regexCache.getPatternForRegex("\\" + PhoneNumberUtil.PLUS_SIGN + "|" +
563bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia            currentMetadata.getInternationalPrefix());
5641524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting);
5651524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (iddMatcher.lookingAt()) {
566203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      isCompleteNumber = true;
567372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      int startOfCountryCallingCode = iddMatcher.end();
568df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      nationalNumber.setLength(0);
569372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      nationalNumber.append(accruedInputWithoutFormatting.substring(startOfCountryCallingCode));
570ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      prefixBeforeNationalNumber.setLength(0);
571df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      prefixBeforeNationalNumber.append(
572372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode));
573df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN) {
574203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
575df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
576df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return true;
577df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
578df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return false;
579df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  }
580df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
581df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  /**
582372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Extracts the country calling code from the beginning of nationalNumber to
583372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * prefixBeforeNationalNumber when they are available, and places the remaining input into
584372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * nationalNumber.
585df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *
586372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * @return  true when a valid country calling code can be found.
587df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   */
588372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private boolean attemptToExtractCountryCallingCode() {
589f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    if (nationalNumber.length() == 0) {
590f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia      return false;
591f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    }
592372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    StringBuilder numberWithoutCountryCallingCode = new StringBuilder();
593372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode);
594f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    if (countryCode == 0) {
595f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia      return false;
596f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    }
597372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    nationalNumber.setLength(0);
598372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    nationalNumber.append(numberWithoutCountryCallingCode);
599372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode);
600528b0d12a556ff0c2d16f99d56fcdd62657f433cShaopeng Jia    if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(newRegionCode)) {
601bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = phoneUtil.getMetadataForNonGeographicalRegion(countryCode);
602528b0d12a556ff0c2d16f99d56fcdd62657f433cShaopeng Jia    } else if (!newRegionCode.equals(defaultCountry)) {
603bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = getMetadataForRegion(newRegionCode);
604372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    }
605372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    String countryCodeString = Integer.toString(countryCode);
606203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    prefixBeforeNationalNumber.append(countryCodeString).append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
607b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    // When we have successfully extracted the IDD, the previously extracted NDD should be cleared
608b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    // because it is no longer valid.
609b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    extractedNationalPrefix = "";
6101524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    return true;
6111524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6121524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
6131524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar
6141524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first
6151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // normalized to the ASCII version. The return value is nextChar itself, or its normalized
616372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // version, if nextChar is a digit in non-ASCII format. This method assumes its input is either a
617372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // digit or the plus sign.
618df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private char normalizeAndAccrueDigitsAndPlusSign(char nextChar, boolean rememberPosition) {
619d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    char normalizedChar;
6201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (nextChar == PhoneNumberUtil.PLUS_SIGN) {
621d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      normalizedChar = nextChar;
6221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      accruedInputWithoutFormatting.append(nextChar);
623372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    } else {
624d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      int radix = 10;
625d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      normalizedChar = Character.forDigit(Character.digit(nextChar, radix), radix);
626d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      accruedInputWithoutFormatting.append(normalizedChar);
627d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      nationalNumber.append(normalizedChar);
6281524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
629df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (rememberPosition) {
630df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      positionToRemember = accruedInputWithoutFormatting.length();
631df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
632d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    return normalizedChar;
6331524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6341524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
635df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String inputDigitHelper(char nextChar) {
636203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate);
6371524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (digitMatcher.find(lastMatchPosition)) {
638df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar));
639df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      formattingTemplate.replace(0, tempTemplate.length(), tempTemplate);
6401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      lastMatchPosition = digitMatcher.start();
641df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return formattingTemplate.substring(0, lastMatchPosition + 1);
64252699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    } else {
64352699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      if (possibleFormats.size() == 1) {
64452699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        // More digits are entered than we could handle, and there are no other valid patterns to
64552699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        // try.
64652699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        ableToFormat = false;
64752699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      }  // else, we just reset the formatting pattern.
64852699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      currentFormattingPattern = "";
6490b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia      return accruedInput.toString();
6501524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
6511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia}
653