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
17a77faddfc3b3e4cca8f585c82d669054aec221f4Narayan Kamathpackage com.google.i18n.phonenumbers;
181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
1993399cc7a32833de9cb538ef7940eed61a23edcaNeil Fullerimport com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
2093399cc7a32833de9cb538ef7940eed61a23edcaNeil Fullerimport com.google.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 = ' ';
6493399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller  private static final PhoneMetadata EMPTY_METADATA =
6593399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller      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
11893399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    // 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();
15493399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller      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(
16293399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller                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
1759ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia  private void getAvailableFormats(String leadingDigits) {
17693399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    List<NumberFormat> formatList =
17793399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller        (isCompleteNumber && currentMetadata.intlNumberFormatSize() > 0)
17893399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller        ? currentMetadata.intlNumberFormats()
17993399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller        : currentMetadata.numberFormats();
18093399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    boolean nationalPrefixIsUsedByCountry = currentMetadata.hasNationalPrefix();
18193399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    for (NumberFormat format : formatList) {
182203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      if (!nationalPrefixIsUsedByCountry || isCompleteNumber ||
18393399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller          format.isNationalPrefixOptionalWhenFormatting() ||
1847a81979b0076f18b31b47b7df2beac29735f3a37Cecilia Roes          PhoneNumberUtil.formattingRuleHasFirstGroupOnly(
18593399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller              format.getNationalPrefixFormattingRule())) {
18693399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller        if (isFormatEligible(format.getFormat())) {
187203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          possibleFormats.add(format);
188203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        }
189372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      }
190372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    }
1919ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia    narrowDownPossibleFormats(leadingDigits);
192df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  }
193df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
194372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private boolean isFormatEligible(String format) {
195372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    return ELIGIBLE_FORMAT_PATTERN.matcher(format).matches();
196372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  }
197372bff8dd464574d36737d47e495cad14346653cShaopeng Jia
198df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private void narrowDownPossibleFormats(String leadingDigits) {
199372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    int indexOfLeadingDigitsPattern = leadingDigits.length() - MIN_LEADING_DIGITS_LENGTH;
200df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    Iterator<NumberFormat> it = possibleFormats.iterator();
201df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    while (it.hasNext()) {
202df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      NumberFormat format = it.next();
20393399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller      if (format.leadingDigitsPatternSize() == 0) {
2049ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia        // Keep everything that isn't restricted by leading digits.
2059ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia        continue;
2069ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      }
2079ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      int lastLeadingDigitsPattern =
20893399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller          Math.min(indexOfLeadingDigitsPattern, format.leadingDigitsPatternSize() - 1);
2099ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      Pattern leadingDigitsPattern = regexCache.getPatternForRegex(
21093399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller          format.getLeadingDigitsPattern(lastLeadingDigitsPattern));
2119ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      Matcher m = leadingDigitsPattern.matcher(leadingDigits);
2129ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      if (!m.lookingAt()) {
2139ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia        it.remove();
2149ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      }
2151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private boolean createFormattingTemplate(NumberFormat format) {
21993399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    String numberPattern = format.getPattern();
2201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2210199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    // The formatter doesn't format numbers when numberPattern contains "|", e.g.
2220199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    // (20|3)\d{4}. In those cases we quickly return.
2230199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    if (numberPattern.indexOf('|') != -1) {
2241524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return false;
2251524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Replace anything in the form of [..] with \d
2280199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    numberPattern = CHARACTER_CLASS_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
2291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2301524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Replace any standalone digit (not the one in d{}) with \d
2310199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    numberPattern = STANDALONE_DIGIT_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
232df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    formattingTemplate.setLength(0);
23393399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    String tempTemplate = getFormattingTemplate(numberPattern, format.getFormat());
234d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    if (tempTemplate.length() > 0) {
23552699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      formattingTemplate.append(tempTemplate);
23652699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      return true;
23752699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    }
23852699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    return false;
2391524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
241372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // Gets a formatting template which can be used to efficiently format a partial number where
2421524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // digits are added one by one.
2431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  private String getFormattingTemplate(String numberPattern, String numberFormat) {
2441524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Creates a phone number consisting only of the digit 9 that matches the
2451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // numberPattern by applying the pattern to the longestPhoneNumber string.
2461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String longestPhoneNumber = "999999999999999";
247df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    Matcher m = regexCache.getPatternForRegex(numberPattern).matcher(longestPhoneNumber);
2481524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    m.find();  // this will always succeed
2491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String aPhoneNumber = m.group();
250d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    // No formatting template can be created if the number of digits entered so far is longer than
251d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    // the maximum the current formatting rule can accommodate.
252d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    if (aPhoneNumber.length() < nationalNumber.length()) {
253d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      return "";
254d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    }
2551524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    // Formats the number according to numberFormat
2561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    String template = aPhoneNumber.replaceAll(numberPattern, numberFormat);
257203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // Replaces each digit with character DIGIT_PLACEHOLDER
258203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    template = template.replaceAll("9", DIGIT_PLACEHOLDER);
2591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    return template;
2601524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
2621524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
263372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Clears the internal state of the formatter, so it can be reused.
2641524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
2651524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  public void clear() {
266df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = "";
2670199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    accruedInput.setLength(0);
2680199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    accruedInputWithoutFormatting.setLength(0);
269df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    formattingTemplate.setLength(0);
2701524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    lastMatchPosition = 0;
271df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentFormattingPattern = "";
2720199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    prefixBeforeNationalNumber.setLength(0);
273b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    extractedNationalPrefix = "";
2740199c997f87434f2c5a7d1df4bb4b5f904312b9fShaopeng Jia    nationalNumber.setLength(0);
2751524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    ableToFormat = true;
276ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    inputHasFormatting = false;
277df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    positionToRemember = 0;
2780b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia    originalPosition = 0;
279203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    isCompleteNumber = false;
280372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    isExpectingCountryCallingCode = false;
281df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    possibleFormats.clear();
282203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    shouldAddSpaceAfterNationalPrefix = false;
283bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    if (!currentMetadata.equals(defaultMetadata)) {
284bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = getMetadataForRegion(defaultCountry);
2851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
2861524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
2871524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
288df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  /**
289df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * Formats a phone number on-the-fly as each digit is entered.
290df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *
291df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @param nextChar  the most recently entered digit of a phone number. Formatting characters are
292372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     allowed, but as soon as they are encountered this method formats the number as entered and
293372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will
294372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   *     be shown as they are.
295df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @return  the partially formatted phone number.
296df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   */
2974b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  public String inputDigit(char nextChar) {
298df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = inputDigitWithOptionToRememberPosition(nextChar, false);
299df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutput;
3004b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  }
3014b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia
3021524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
303372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Same as {@link #inputDigit}, but remembers the position where {@code nextChar} is inserted, so
304372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * that it can be retrieved later by using {@link #getRememberedPosition}. The remembered
305372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * position will be automatically adjusted if additional formatting characters are later
306372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * inserted/removed in front of {@code nextChar}.
3071524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
3084b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  public String inputDigitAndRememberPosition(char nextChar) {
309df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    currentOutput = inputDigitWithOptionToRememberPosition(nextChar, true);
310df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutput;
3114b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  }
3124b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia
31352699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia  @SuppressWarnings("fallthrough")
3144b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia  private String inputDigitWithOptionToRememberPosition(char nextChar, boolean rememberPosition) {
3151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    accruedInput.append(nextChar);
3164b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia    if (rememberPosition) {
317df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      originalPosition = accruedInput.length();
3184b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia    }
319f7e0224b862054893f28d2736b3f6804d9935886Shaopeng Jia    // We do formatting on-the-fly only when each character entered is either a digit, or a plus
32016b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    // sign (accepted at the start of the number only).
32116b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    if (!isDigitOrLeadingPlusSign(nextChar)) {
3221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      ableToFormat = false;
323ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      inputHasFormatting = true;
324ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    } else {
325ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar, rememberPosition);
3261524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (!ableToFormat) {
328ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // When we are unable to format because of reasons other than that formatting chars have been
329ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able
330ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // to do formatting again after extracting them.
331ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      if (inputHasFormatting) {
332ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        return accruedInput.toString();
333ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      } else if (attemptToExtractIdd()) {
334ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        if (attemptToExtractCountryCallingCode()) {
335ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia          return attemptToChoosePatternWithPrefixExtracted();
336ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        }
337ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      } else if (ableToExtractLongerNdd()) {
338ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        // Add an additional space to separate long NDD and national significant number for
339203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        // readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want
340203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        // this to change later when we choose formatting templates.
341203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
342ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        return attemptToChoosePatternWithPrefixExtracted();
343ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      }
3441524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return accruedInput.toString();
3451524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
347df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus
348df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // sign is counted as a digit as well for this purpose) have been entered.
3491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    switch (accruedInputWithoutFormatting.length()) {
350372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      case 0:
3511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 1:
3521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 2:
353df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        return accruedInput.toString();
3541524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      case 3:
355df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        if (attemptToExtractIdd()) {
356372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          isExpectingCountryCallingCode = true;
357ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia        } else {  // No IDD or plus sign is found, might be entering in national format.
358b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia          extractedNationalPrefix = removeNationalPrefixFromNationalNumber();
359df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return attemptToChooseFormattingPattern();
360df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        }
361ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      default:
362372bff8dd464574d36737d47e495cad14346653cShaopeng Jia        if (isExpectingCountryCallingCode) {
363372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          if (attemptToExtractCountryCallingCode()) {
364372bff8dd464574d36737d47e495cad14346653cShaopeng Jia            isExpectingCountryCallingCode = false;
365df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
366df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return prefixBeforeNationalNumber + nationalNumber.toString();
367df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        }
3689ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia        if (possibleFormats.size() > 0) {  // The formatting patterns are already chosen.
369df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          String tempNationalNumber = inputDigitHelper(nextChar);
370df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          // See if the accrued digits can be formatted properly already. If not, use the results
371df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          // from inputDigitHelper, which does formatting based on the formatting pattern chosen.
372df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          String formattedNumber = attemptToFormatAccruedDigits();
373df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          if (formattedNumber.length() > 0) {
374df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia            return formattedNumber;
375df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
376df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          narrowDownPossibleFormats(nationalNumber.toString());
377df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          if (maybeCreateNewTemplate()) {
378df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia            return inputAccruedNationalNumber();
379df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          }
3800b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia          return ableToFormat
381203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia             ? appendNationalNumber(tempNationalNumber)
382f3c6df010e7bc8ead25ba577ae09474b70d08adcShaopeng Jia             : accruedInput.toString();
3831524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        } else {
384df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          return attemptToChooseFormattingPattern();
3851524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        }
3861524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
3871524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
3881524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
389ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private String attemptToChoosePatternWithPrefixExtracted() {
390ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    ableToFormat = true;
391ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    isExpectingCountryCallingCode = false;
392ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    possibleFormats.clear();
3937491c3442ffdba4a604c18a7a853590a3b32fcfcNarayan Kamath    lastMatchPosition = 0;
3947491c3442ffdba4a604c18a7a853590a3b32fcfcNarayan Kamath    formattingTemplate.setLength(0);
3957491c3442ffdba4a604c18a7a853590a3b32fcfcNarayan Kamath    currentFormattingPattern = "";
396ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    return attemptToChooseFormattingPattern();
397ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  }
398ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia
399b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  // @VisibleForTesting
400b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  String getExtractedNationalPrefix() {
401b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    return extractedNationalPrefix;
402b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia  }
403b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia
404ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result
405ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // in a number we can format, we try to see if we can extract a longer version here.
406ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private boolean ableToExtractLongerNdd() {
407b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    if (extractedNationalPrefix.length() > 0) {
408ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // Put the extracted NDD back to the national number before attempting to extract a new NDD.
409b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia      nationalNumber.insert(0, extractedNationalPrefix);
410ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set
41177aadd284847681bd66af639636c2fa43e418c2bShaopeng Jia      // it to empty string because people sometimes incorrectly enter national prefix after the
41277aadd284847681bd66af639636c2fa43e418c2bShaopeng Jia      // country code, e.g. +44 (0)20-1234-5678.
413b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia      int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(extractedNationalPrefix);
414ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      prefixBeforeNationalNumber.setLength(indexOfPreviousNdd);
415ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    }
416b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    return !extractedNationalPrefix.equals(removeNationalPrefixFromNationalNumber());
417ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  }
418ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia
41916b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia  private boolean isDigitOrLeadingPlusSign(char nextChar) {
42016b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia    return Character.isDigit(nextChar) ||
42116b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia        (accruedInput.length() == 1 &&
42216b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia         PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches());
42316b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia  }
42416b56da4e787a614d16bedcd02b5086d40efbbdbShaopeng Jia
425203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
426203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Check to see if there is an exact pattern match for these digits. If so, we should use this
427203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * instead of any other formatting template whose leadingDigitsPattern also matches the input.
428203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
429df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  String attemptToFormatAccruedDigits() {
430203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    for (NumberFormat numberFormat : possibleFormats) {
43193399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller      Matcher m = regexCache.getPatternForRegex(numberFormat.getPattern()).matcher(nationalNumber);
432df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (m.matches()) {
433203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        shouldAddSpaceAfterNationalPrefix =
434203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia            NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher(
43593399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller                numberFormat.getNationalPrefixFormattingRule()).find();
43693399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller        String formattedNumber = m.replaceAll(numberFormat.getFormat());
437203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        return appendNationalNumber(formattedNumber);
438df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
4390b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia    }
440df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return "";
4410b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  }
4420b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia
4430b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  /**
4440b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia   * Returns the current position in the partially formatted phone number of the character which was
445372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * previously passed in as the parameter of {@link #inputDigitAndRememberPosition}.
4460b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia   */
4470b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  public int getRememberedPosition() {
448df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (!ableToFormat) {
449df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return originalPosition;
450df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
45152699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    int accruedInputIndex = 0, currentOutputIndex = 0;
452372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    while (accruedInputIndex < positionToRemember && currentOutputIndex < currentOutput.length()) {
453df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (accruedInputWithoutFormatting.charAt(accruedInputIndex) ==
454df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia          currentOutput.charAt(currentOutputIndex)) {
455df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        accruedInputIndex++;
456df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
457372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      currentOutputIndex++;
458df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
459df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return currentOutputIndex;
4600b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia  }
4610b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia
462203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
463203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Combines the national number with any prefix (IDD/+ and country code or national prefix) that
464203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * was collected. A space will be inserted between them if the current formatting template
465203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * indicates this to be suitable.
466203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
467203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private String appendNationalNumber(String nationalNumber) {
468203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    int prefixBeforeNationalNumberLength = prefixBeforeNationalNumber.length();
469203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    if (shouldAddSpaceAfterNationalPrefix && prefixBeforeNationalNumberLength > 0 &&
470203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.charAt(prefixBeforeNationalNumberLength - 1)
471203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia            != SEPARATOR_BEFORE_NATIONAL_NUMBER) {
472203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // We want to add a space after the national prefix if the national prefix formatting rule
473203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // indicates that this would normally be done, with the exception of the case where we already
474203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      // appended a space because the NDD was surprisingly long.
475203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return new String(prefixBeforeNationalNumber) + SEPARATOR_BEFORE_NATIONAL_NUMBER
476203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia          + nationalNumber;
477203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    } else {
478203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return prefixBeforeNationalNumber + nationalNumber;
479203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    }
480203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  }
481203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia
482203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
483203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Attempts to set the formatting template and returns a string which contains the formatted
484203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * version of the digits entered so far.
485203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
486df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String attemptToChooseFormattingPattern() {
487bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national
488df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    // number (excluding national prefix) have been entered.
489df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) {
4909ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia
4919ecee8b74bf330f20a902e4b974eddb7abedd627Shaopeng Jia      getAvailableFormats(nationalNumber.toString());
492bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // See if the accrued digits can be formatted properly already.
493bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      String formattedNumber = attemptToFormatAccruedDigits();
494bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      if (formattedNumber.length() > 0) {
495bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        return formattedNumber;
496bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      }
49796a7214cdabf08f53f5b1a560304601c9f65e0b9Shaopeng Jia      return maybeCreateNewTemplate() ? inputAccruedNationalNumber() : accruedInput.toString();
4981524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    } else {
499203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return appendNationalNumber(nationalNumber.toString());
5001524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
5011524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
5021524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
503203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
504203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted
505203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * string in the end.
506203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
507df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String inputAccruedNationalNumber() {
5081524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    int lengthOfNationalNumber = nationalNumber.length();
5091524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (lengthOfNationalNumber > 0) {
5104b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia      String tempNationalNumber = "";
5114b7846722d1a5acb0577b07e98324f744f5e7942Shaopeng Jia      for (int i = 0; i < lengthOfNationalNumber; i++) {
512df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia        tempNationalNumber = inputDigitHelper(nationalNumber.charAt(i));
5131524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      }
514203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      return ableToFormat ? appendNationalNumber(tempNationalNumber) : accruedInput.toString();
5151524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    } else {
5161524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      return prefixBeforeNationalNumber.toString();
5171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
5181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
5191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
520203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  /**
521203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * Returns true if the current country is a NANPA country and the national number begins with
522203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   * the national prefix.
523203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia   */
524203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  private boolean isNanpaNumberWithNationalPrefix() {
525203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is
526203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // that national significant numbers in NANPA always start with [2-9] after the national prefix.
527203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the
528203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    // national prefix.
52993399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    return (currentMetadata.getCountryCode() == 1) && (nationalNumber.charAt(0) == '1') &&
530203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia           (nationalNumber.charAt(1) != '0') && (nationalNumber.charAt(1) != '1');
531203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia  }
532203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia
533ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  // Returns the national prefix extracted, or an empty string if it is not present.
534ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia  private String removeNationalPrefixFromNationalNumber() {
5351524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    int startOfNationalNumber = 0;
536203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    if (isNanpaNumberWithNationalPrefix()) {
53794c2440dc41689b7d9c169edf5089eeebf7527d7Shaopeng Jia      startOfNationalNumber = 1;
538203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      prefixBeforeNationalNumber.append('1').append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
539203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      isCompleteNumber = true;
54093399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller    } else if (currentMetadata.hasNationalPrefixForParsing()) {
541372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      Pattern nationalPrefixForParsing =
54293399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller          regexCache.getPatternForRegex(currentMetadata.getNationalPrefixForParsing());
5431524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      Matcher m = nationalPrefixForParsing.matcher(nationalNumber);
544bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // Since some national prefix patterns are entirely optional, check that a national prefix
545bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      // could actually be extracted.
546bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      if (m.lookingAt() && m.end() > 0) {
547f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // When the national prefix is detected, we use international formatting rules instead of
548f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // national ones, because national formatting rules could contain local formatting rules
549f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia        // for numbers entered without area code.
550203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        isCompleteNumber = true;
5511524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        startOfNationalNumber = m.end();
5521524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia        prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber));
5531524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      }
5541524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
555ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    String nationalPrefix = nationalNumber.substring(0, startOfNationalNumber);
5561524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    nationalNumber.delete(0, startOfNationalNumber);
557ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia    return nationalPrefix;
5581524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
5591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
5601524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  /**
561df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * Extracts IDD and plus sign to prefixBeforeNationalNumber when they are available, and places
562df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * the remaining input into nationalNumber.
5631524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   *
564df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   * @return  true when accruedInputWithoutFormatting begins with the plus sign or valid IDD for
565df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *     defaultCountry.
5661524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia   */
567df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private boolean attemptToExtractIdd() {
568372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    Pattern internationalPrefix =
569372bff8dd464574d36737d47e495cad14346653cShaopeng Jia        regexCache.getPatternForRegex("\\" + PhoneNumberUtil.PLUS_SIGN + "|" +
57093399cc7a32833de9cb538ef7940eed61a23edcaNeil Fuller            currentMetadata.getInternationalPrefix());
5711524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting);
5721524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (iddMatcher.lookingAt()) {
573203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia      isCompleteNumber = true;
574372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      int startOfCountryCallingCode = iddMatcher.end();
575df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      nationalNumber.setLength(0);
576372bff8dd464574d36737d47e495cad14346653cShaopeng Jia      nationalNumber.append(accruedInputWithoutFormatting.substring(startOfCountryCallingCode));
577ca1e43d6e1fac07c7fc29c66c7da1fa9d7cf50f2Shaopeng Jia      prefixBeforeNationalNumber.setLength(0);
578df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      prefixBeforeNationalNumber.append(
579372bff8dd464574d36737d47e495cad14346653cShaopeng Jia          accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode));
580df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN) {
581203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia        prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
582df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      }
583df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return true;
584df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
585df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    return false;
586df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  }
587df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia
588df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  /**
589372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * Extracts the country calling code from the beginning of nationalNumber to
590372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * prefixBeforeNationalNumber when they are available, and places the remaining input into
591372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * nationalNumber.
592df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   *
593372bff8dd464574d36737d47e495cad14346653cShaopeng Jia   * @return  true when a valid country calling code can be found.
594df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia   */
595372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  private boolean attemptToExtractCountryCallingCode() {
596f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    if (nationalNumber.length() == 0) {
597f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia      return false;
598f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    }
599372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    StringBuilder numberWithoutCountryCallingCode = new StringBuilder();
600372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode);
601f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    if (countryCode == 0) {
602f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia      return false;
603f59ccfca9dd02c4e3cf3e06b5cf184a8d0e67626Shaopeng Jia    }
604372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    nationalNumber.setLength(0);
605372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    nationalNumber.append(numberWithoutCountryCallingCode);
606372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode);
607528b0d12a556ff0c2d16f99d56fcdd62657f433cShaopeng Jia    if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(newRegionCode)) {
608bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = phoneUtil.getMetadataForNonGeographicalRegion(countryCode);
609528b0d12a556ff0c2d16f99d56fcdd62657f433cShaopeng Jia    } else if (!newRegionCode.equals(defaultCountry)) {
610bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      currentMetadata = getMetadataForRegion(newRegionCode);
611372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    }
612372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    String countryCodeString = Integer.toString(countryCode);
613203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    prefixBeforeNationalNumber.append(countryCodeString).append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
614b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    // When we have successfully extracted the IDD, the previously extracted NDD should be cleared
615b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    // because it is no longer valid.
616b03a14984ad9b0d8b88337ca714cb831233b99c3Shaopeng Jia    extractedNationalPrefix = "";
6171524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    return true;
6181524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6191524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
6201524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar
6211524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first
6221524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  // normalized to the ASCII version. The return value is nextChar itself, or its normalized
623372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // version, if nextChar is a digit in non-ASCII format. This method assumes its input is either a
624372bff8dd464574d36737d47e495cad14346653cShaopeng Jia  // digit or the plus sign.
625df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private char normalizeAndAccrueDigitsAndPlusSign(char nextChar, boolean rememberPosition) {
626d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    char normalizedChar;
6271524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (nextChar == PhoneNumberUtil.PLUS_SIGN) {
628d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      normalizedChar = nextChar;
6291524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      accruedInputWithoutFormatting.append(nextChar);
630372bff8dd464574d36737d47e495cad14346653cShaopeng Jia    } else {
631d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      int radix = 10;
632d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      normalizedChar = Character.forDigit(Character.digit(nextChar, radix), radix);
633d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      accruedInputWithoutFormatting.append(normalizedChar);
634d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia      nationalNumber.append(normalizedChar);
6351524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
636df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    if (rememberPosition) {
637df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      positionToRemember = accruedInputWithoutFormatting.length();
638df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia    }
639d1db4c508088ac27cb0815a222cf2600f16ad5b9Shaopeng Jia    return normalizedChar;
6401524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6411524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia
642df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia  private String inputDigitHelper(char nextChar) {
6437491c3442ffdba4a604c18a7a853590a3b32fcfcNarayan Kamath    // Note that formattingTemplate is not guaranteed to have a value, it could be empty, e.g.
6447491c3442ffdba4a604c18a7a853590a3b32fcfcNarayan Kamath    // when the next digit is entered after extracting an IDD or NDD.
645203cf688f8d56e2c1f9828801b113110465f39a7Shaopeng Jia    Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate);
6461524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    if (digitMatcher.find(lastMatchPosition)) {
647df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar));
648df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      formattingTemplate.replace(0, tempTemplate.length(), tempTemplate);
6491524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia      lastMatchPosition = digitMatcher.start();
650df19cbfb8a1e8720bae76bb763ab29622e057c42Shaopeng Jia      return formattingTemplate.substring(0, lastMatchPosition + 1);
65152699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia    } else {
65252699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      if (possibleFormats.size() == 1) {
65352699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        // More digits are entered than we could handle, and there are no other valid patterns to
65452699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        // try.
65552699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia        ableToFormat = false;
65652699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      }  // else, we just reset the formatting pattern.
65752699e08e855fb0957944b4e73358ad9e0007c0cShaopeng Jia      currentFormattingPattern = "";
6580b3c1fb05c01bc853ad927356eee743b62a8121bShaopeng Jia      return accruedInput.toString();
6591524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia    }
6601524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia  }
6611524ca8c53cd2c3adee0bb2e2b95a93fee976862Shaopeng Jia}
662