diff options
Diffstat (limited to 'libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java')
-rw-r--r-- | libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java | 493 |
1 files changed, 246 insertions, 247 deletions
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index 5a41d761..705d657b 100644 --- a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -22,7 +22,6 @@ import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -52,14 +51,6 @@ import java.util.regex.Pattern; * @author Shaopeng Jia */ public class PhoneNumberUtil { - // @VisibleForTesting - static final MetadataLoader DEFAULT_METADATA_LOADER = new MetadataLoader() { - @Override - public InputStream loadMetadata(String metadataFileName) { - return PhoneNumberUtil.class.getResourceAsStream(metadataFileName); - } - }; - private static final Logger logger = Logger.getLogger(PhoneNumberUtil.class.getName()); /** Flags to use when compiling regular expressions for phone numbers. */ @@ -197,6 +188,7 @@ public class PhoneNumberUtil { diallableCharMap.putAll(asciiDigitMappings); diallableCharMap.put(PLUS_SIGN, PLUS_SIGN); diallableCharMap.put('*', '*'); + diallableCharMap.put('#', '#'); DIALLABLE_CHAR_MAPPINGS = Collections.unmodifiableMap(diallableCharMap); HashMap<Character, Character> allPlusNumberGroupings = new HashMap<Character, Character>(); @@ -241,14 +233,15 @@ public class PhoneNumberUtil { // square brackets, parentheses and tildes. It also includes the letter 'x' as that is found as a // placeholder for carrier information in some phone numbers. Full-width variants are also // present. - static final String VALID_PUNCTUATION = "-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F " + - "\u00A0\u00AD\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E"; + static final String VALID_PUNCTUATION = "-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F " + + "\u00A0\u00AD\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E"; private static final String DIGITS = "\\p{Nd}"; // We accept alpha characters in phone numbers, ASCII only, upper and lower case. private static final String VALID_ALPHA = - Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).replaceAll("[, \\[\\]]", "") + - Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).toLowerCase().replaceAll("[, \\[\\]]", ""); + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).replaceAll("[, \\[\\]]", "") + + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()) + .toLowerCase().replaceAll("[, \\[\\]]", ""); static final String PLUS_CHARS = "+\uFF0B"; static final Pattern PLUS_CHARS_PATTERN = Pattern.compile("[" + PLUS_CHARS + "]+"); private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[" + VALID_PUNCTUATION + "]+"); @@ -298,9 +291,9 @@ public class PhoneNumberUtil { // // Note VALID_PUNCTUATION starts with a -, so must be the first in the range. private static final String VALID_PHONE_NUMBER = - DIGITS + "{" + MIN_LENGTH_FOR_NSN + "}" + "|" + - "[" + PLUS_CHARS + "]*+(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" + - VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*"; + DIGITS + "{" + MIN_LENGTH_FOR_NSN + "}" + "|" + + "[" + PLUS_CHARS + "]*+(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" + + VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*"; // Default extension prefix to use when formatting. This will be put in front of any extension // component of the number, after the main national number is formatted. For example, if you wish @@ -343,11 +336,11 @@ public class PhoneNumberUtil { // Canonical-equivalence doesn't seem to be an option with Android java, so we allow two options // for representing the accented o - the character itself, and one in the unicode decomposed // form with the combining acute accent. - return (RFC3966_EXTN_PREFIX + CAPTURING_EXTN_DIGITS + "|" + "[ \u00A0\\t,]*" + - "(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|" + - "[" + singleExtnSymbols + "]|int|anexo|\uFF49\uFF4E\uFF54)" + - "[:\\.\uFF0E]?[ \u00A0\\t,-]*" + CAPTURING_EXTN_DIGITS + "#?|" + - "[- ]+(" + DIGITS + "{1,5})#"); + return (RFC3966_EXTN_PREFIX + CAPTURING_EXTN_DIGITS + "|" + "[ \u00A0\\t,]*" + + "(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|" + + "[" + singleExtnSymbols + "]|int|anexo|\uFF49\uFF4E\uFF54)" + + "[:\\.\uFF0E]?[ \u00A0\\t,-]*" + CAPTURING_EXTN_DIGITS + "#?|" + + "[- ]+(" + DIGITS + "{1,5})#"); } // Regexp of all known extension prefixes used by different regions followed by 1 or more valid @@ -477,8 +470,8 @@ public class PhoneNumberUtil { VALID { @Override boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { - if (!util.isValidNumber(number) || - !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util)) { + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util)) { return false; } return PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util); @@ -499,10 +492,10 @@ public class PhoneNumberUtil { STRICT_GROUPING { @Override boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { - if (!util.isValidNumber(number) || - !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) || - PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) || - !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.checkNumberGroupingIsValid( @@ -531,10 +524,10 @@ public class PhoneNumberUtil { EXACT_GROUPING { @Override boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { - if (!util.isValidNumber(number) || - !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) || - PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) || - !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.checkNumberGroupingIsValid( @@ -606,8 +599,8 @@ public class PhoneNumberUtil { // there are entries that list the non-geo entity alongside normal regions (which is wrong). // If we discover this, remove the non-geo entity from the set of supported regions and log. if (supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY)) { - logger.log(Level.WARNING, "invalid metadata " + - "(country calling code was mapped to the non-geo entity as well as specific region(s))"); + logger.log(Level.WARNING, "invalid metadata (country calling code was mapped to the non-geo " + + "entity as well as specific region(s))"); } nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE)); } @@ -623,9 +616,9 @@ public class PhoneNumberUtil { * number is parsed correctly. * * @param number the string that might contain a phone number - * @return the number, stripped of any non-phone-number prefix (such as "Tel:") or an empty - * string if no character used to start phone numbers (such as + or any digit) is - * found in the number + * @return the number, stripped of any non-phone-number prefix (such as "Tel:") or an empty + * string if no character used to start phone numbers (such as + or any digit) is found in the + * number */ static String extractPossibleNumber(String number) { Matcher m = VALID_START_CHAR_PATTERN.matcher(number); @@ -656,7 +649,7 @@ public class PhoneNumberUtil { * leading non-number symbols have been removed, such as by the method extractPossibleNumber. * * @param number string to be checked for viability as a phone number - * @return true if the number could be a phone number of some sort, otherwise false + * @return true if the number could be a phone number of some sort, otherwise false */ // @VisibleForTesting static boolean isViablePhoneNumber(String number) { @@ -681,7 +674,7 @@ public class PhoneNumberUtil { * Spurious alpha characters are stripped. * * @param number a string of characters representing a phone number - * @return the normalized string version of the phone number + * @return the normalized string version of the phone number */ static String normalize(String number) { Matcher m = VALID_ALPHA_PHONE_PATTERN.matcher(number); @@ -709,7 +702,7 @@ public class PhoneNumberUtil { * arabic-indic numerals to European numerals, and strips punctuation and alpha characters. * * @param number a string of characters representing a phone number - * @return the normalized string version of the phone number + * @return the normalized string version of the phone number */ public static String normalizeDigitsOnly(String number) { return normalizeDigits(number, false /* strip non-digits */).toString(); @@ -733,7 +726,7 @@ public class PhoneNumberUtil { * are not diallable on a mobile phone keypad (including all non-ASCII digits). * * @param number a string of characters representing a phone number - * @return the normalized string version of the phone number + * @return the normalized string version of the phone number */ static String normalizeDiallableCharsOnly(String number) { return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */); @@ -784,9 +777,9 @@ public class PhoneNumberUtil { * <li> some geographical numbers have no area codes. * </ul> * @param number the PhoneNumber object for which clients - * want to know the length of the area code. + * want to know the length of the area code * @return the length of area code of the PhoneNumber object - * passed in. + * passed in */ public int getLengthOfGeographicalAreaCode(PhoneNumber number) { PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number)); @@ -846,9 +839,9 @@ public class PhoneNumberUtil { * {@link #getLengthOfGeographicalAreaCode}. * * @param number the PhoneNumber object for which clients - * want to know the length of the NDC. + * want to know the length of the NDC * @return the length of NDC of the PhoneNumber object - * passed in. + * passed in */ public int getLengthOfNationalDestinationCode(PhoneNumber number) { PhoneNumber copiedProto; @@ -906,12 +899,11 @@ public class PhoneNumberUtil { * in the accompanying map with the values therein, and stripping all other characters if * removeNonMatches is true. * - * @param number a string of characters representing a phone number + * @param number a string of characters representing a phone number * @param normalizationReplacements a mapping of characters to what they should be replaced by in - * the normalized version of the phone number - * @param removeNonMatches indicates whether characters that are not able to be replaced - * should be stripped from the number. If this is false, they - * will be left unchanged in the number. + * the normalized version of the phone number + * @param removeNonMatches indicates whether characters that are not able to be replaced should + * be stripped from the number. If this is false, they will be left unchanged in the number. * @return the normalized string version of the phone number */ private static String normalizeHelper(String number, @@ -957,8 +949,7 @@ public class PhoneNumberUtil { /** * Gets a {@link PhoneNumberUtil} instance to carry out international phone number formatting, - * parsing, or validation. The instance is loaded with phone number metadata for a number of most - * commonly used regions. + * parsing, or validation. The instance is loaded with all phone number metadata. * * <p>The {@link PhoneNumberUtil} is implemented as a singleton. Therefore, calling getInstance * multiple times will only result in one instance being created. @@ -967,7 +958,7 @@ public class PhoneNumberUtil { */ public static synchronized PhoneNumberUtil getInstance() { if (instance == null) { - setInstance(createInstance(DEFAULT_METADATA_LOADER)); + setInstance(createInstance(MetadataManager.DEFAULT_METADATA_LOADER)); } return instance; } @@ -975,40 +966,40 @@ public class PhoneNumberUtil { /** * Create a new {@link PhoneNumberUtil} instance to carry out international phone number * formatting, parsing, or validation. The instance is loaded with all metadata by - * using the metadataSource specified. + * using the metadataLoader specified. * - * This method should only be used in the rare case in which you want to manage your own + * <p>This method should only be used in the rare case in which you want to manage your own * metadata loading. Calling this method multiple times is very expensive, as each time * a new instance is created from scratch. When in doubt, use {@link #getInstance}. * - * @param metadataSource Customized metadata source. This should not be null. - * @return a PhoneNumberUtil instance + * @param metadataLoader customized metadata loader. This should not be null + * @return a PhoneNumberUtil instance */ - public static PhoneNumberUtil createInstance(MetadataSource metadataSource) { - if (metadataSource == null) { - throw new IllegalArgumentException("metadataSource could not be null."); + public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) { + if (metadataLoader == null) { + throw new IllegalArgumentException("metadataLoader could not be null."); } - return new PhoneNumberUtil(metadataSource, - CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap()); + return createInstance(new MultiFileMetadataSourceImpl(metadataLoader)); } /** * Create a new {@link PhoneNumberUtil} instance to carry out international phone number * formatting, parsing, or validation. The instance is loaded with all metadata by - * using the metadataLoader specified. + * using the metadataSource specified. * - * This method should only be used in the rare case in which you want to manage your own + * <p>This method should only be used in the rare case in which you want to manage your own * metadata loading. Calling this method multiple times is very expensive, as each time * a new instance is created from scratch. When in doubt, use {@link #getInstance}. * - * @param metadataLoader Customized metadata loader. This should not be null. - * @return a PhoneNumberUtil instance + * @param metadataSource customized metadata source. This should not be null + * @return a PhoneNumberUtil instance */ - public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) { - if (metadataLoader == null) { - throw new IllegalArgumentException("metadataLoader could not be null."); + private static PhoneNumberUtil createInstance(MetadataSource metadataSource) { + if (metadataSource == null) { + throw new IllegalArgumentException("metadataSource could not be null."); } - return createInstance(new MultiFileMetadataSourceImpl(metadataLoader)); + return new PhoneNumberUtil(metadataSource, + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap()); } /** @@ -1016,8 +1007,8 @@ public class PhoneNumberUtil { * does not start with the national prefix. */ static boolean formattingRuleHasFirstGroupOnly(String nationalPrefixFormattingRule) { - return nationalPrefixFormattingRule.length() == 0 || - FIRST_GROUP_ONLY_PREFIX_PATTERN.matcher(nationalPrefixFormattingRule).matches(); + return nationalPrefixFormattingRule.length() == 0 + || FIRST_GROUP_ONLY_PREFIX_PATTERN.matcher(nationalPrefixFormattingRule).matches(); } /** @@ -1067,8 +1058,8 @@ public class PhoneNumberUtil { * which formatting rules to apply so we return the national significant number with no formatting * applied. * - * @param number the phone number to be formatted - * @param numberFormat the format the phone number should be formatted into + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into * @return the formatted phone number */ public String format(PhoneNumber number, PhoneNumberFormat numberFormat) { @@ -1077,7 +1068,7 @@ public class PhoneNumberUtil { // This is the only case where a number can be formatted as E164 without a // leading '+' symbol (but the original number wasn't parseable anyway). // TODO: Consider removing the 'if' above so that unparseable - // strings without raw input format to the empty string instead of "+00" + // strings without raw input format to the empty string instead of "+00". String rawInput = number.getRawInput(); if (rawInput.length() > 0) { return rawInput; @@ -1130,9 +1121,9 @@ public class PhoneNumberUtil { * code, we cannot work out things like whether there should be a national prefix applied, or how * to format extensions, so we return the national significant number with no formatting applied. * - * @param number the phone number to be formatted - * @param numberFormat the format the phone number should be formatted into - * @param userDefinedFormats formatting rules specified by clients + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into + * @param userDefinedFormats formatting rules specified by clients * @return the formatted phone number */ public String formatByPattern(PhoneNumber number, @@ -1147,7 +1138,7 @@ public class PhoneNumberUtil { // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. String regionCode = getRegionCodeForCountryCode(countryCallingCode); - // Metadata cannot be null because the country calling code is valid + // Metadata cannot be null because the country calling code is valid. PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); @@ -1159,7 +1150,7 @@ public class PhoneNumberUtil { // If no pattern above is matched, we format the number as a whole. formattedNumber.append(nationalSignificantNumber); } else { - NumberFormat numFormatCopy = new NumberFormat(); + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); // Before we do a replacement of the national prefix pattern $NP with the national prefix, we // need to copy the rule so that subsequent replacements for different numbers have the // appropriate national prefix. @@ -1196,7 +1187,7 @@ public class PhoneNumberUtil { * @param number the phone number to be formatted * @param carrierCode the carrier selection code to be used * @return the formatted phone number in national format for dialing using the carrier as - * specified in the {@code carrierCode} + * specified in the {@code carrierCode} */ public String formatNationalNumberWithCarrierCode(PhoneNumber number, String carrierCode) { int countryCallingCode = number.getCountryCode(); @@ -1247,9 +1238,13 @@ public class PhoneNumberUtil { */ public String formatNationalNumberWithPreferredCarrierCode(PhoneNumber number, String fallbackCarrierCode) { - return formatNationalNumberWithCarrierCode(number, number.hasPreferredDomesticCarrierCode() - ? number.getPreferredDomesticCarrierCode() - : fallbackCarrierCode); + return formatNationalNumberWithCarrierCode(number, + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + number.getPreferredDomesticCarrierCode().length() > 0 + ? number.getPreferredDomesticCarrierCode() + : fallbackCarrierCode); } /** @@ -1279,14 +1274,17 @@ public class PhoneNumberUtil { boolean isValidNumber = (numberType != PhoneNumberType.UNKNOWN); if (regionCallingFrom.equals(regionCode)) { boolean isFixedLineOrMobile = - (numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) || - (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE); + (numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) + || (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE); // Carrier codes may be needed in some countries. We handle this here. if (regionCode.equals("CO") && numberType == PhoneNumberType.FIXED_LINE) { formattedNumber = formatNationalNumberWithCarrierCode(numberNoExt, COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX); } else if (regionCode.equals("BR") && isFixedLineOrMobile) { - formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + formattedNumber = numberNoExt.getPreferredDomesticCarrierCode().length() > 0 ? formattedNumber = formatNationalNumberWithPreferredCarrierCode(numberNoExt, "") // Brazilian fixed line and mobile numbers need to be dialed with a carrier code when // called within Brazil. Without that, most of the carriers won't connect the call. @@ -1298,16 +1296,16 @@ public class PhoneNumberUtil { // dialing from a mobile phone, except for short numbers. As a result, we add it back here // if it is a valid regular length phone number. formattedNumber = - getNddPrefixForRegion(regionCode, true /* strip non-digits */) + - " " + format(numberNoExt, PhoneNumberFormat.NATIONAL); + getNddPrefixForRegion(regionCode, true /* strip non-digits */) + " " + + format(numberNoExt, PhoneNumberFormat.NATIONAL); } else if (countryCallingCode == NANPA_COUNTRY_CODE) { // For NANPA countries, we output international format for numbers that can be dialed // internationally, since that always works, except for numbers which might potentially be // short numbers, which are always dialled in national format. PhoneMetadata regionMetadata = getMetadataForRegion(regionCallingFrom); - if (canBeInternationallyDialled(numberNoExt) && - !isShorterThanPossibleNormalNumber(regionMetadata, - getNationalSignificantNumber(numberNoExt))) { + if (canBeInternationallyDialled(numberNoExt) + && testNumberLength(getNationalSignificantNumber(numberNoExt), + regionMetadata.getGeneralDesc()) != ValidationResult.TOO_SHORT) { formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); } else { formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); @@ -1316,18 +1314,18 @@ public class PhoneNumberUtil { // For non-geographical countries, and Mexican and Chilean fixed line and mobile numbers, we // output international format for numbers that can be dialed internationally as that always // works. - if ((regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITY) || - // MX fixed line and mobile numbers should always be formatted in international format, - // even when dialed within MX. For national format to work, a carrier code needs to be - // used, and the correct carrier code depends on if the caller and callee are from the - // same local area. It is trickier to get that to work correctly than using - // international format, which is tested to work fine on all carriers. - // CL fixed line numbers need the national prefix when dialing in the national format, - // but don't have it when used for display. The reverse is true for mobile numbers. - // As a result, we output them in the international format to make it work. - ((regionCode.equals("MX") || regionCode.equals("CL")) && - isFixedLineOrMobile)) && - canBeInternationallyDialled(numberNoExt)) { + if ((regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITY) + // MX fixed line and mobile numbers should always be formatted in international format, + // even when dialed within MX. For national format to work, a carrier code needs to be + // used, and the correct carrier code depends on if the caller and callee are from the + // same local area. It is trickier to get that to work correctly than using + // international format, which is tested to work fine on all carriers. + // CL fixed line numbers need the national prefix when dialing in the national format, + // but don't have it when used for display. The reverse is true for mobile numbers. As + // a result, we output them in the international format to make it work. + || ((regionCode.equals("MX") || regionCode.equals("CL")) + && isFixedLineOrMobile)) + && canBeInternationallyDialled(numberNoExt)) { formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); } else { formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); @@ -1357,8 +1355,8 @@ public class PhoneNumberUtil { * is used. For regions which have multiple international prefixes, the number in its * INTERNATIONAL format will be returned instead. * - * @param number the phone number to be formatted - * @param regionCallingFrom the region where the call is being placed + * @param number the phone number to be formatted + * @param regionCallingFrom the region where the call is being placed * @return the formatted phone number */ public String formatOutOfCountryCallingNumber(PhoneNumber number, @@ -1441,8 +1439,8 @@ public class PhoneNumberUtil { * @return the formatted phone number in its original number format */ public String formatInOriginalFormat(PhoneNumber number, String regionCallingFrom) { - if (number.hasRawInput() && - (hasUnexpectedItalianLeadingZero(number) || !hasFormattingPatternForNumber(number))) { + if (number.hasRawInput() + && (hasUnexpectedItalianLeadingZero(number) || !hasFormattingPatternForNumber(number))) { // We check if we have the formatting pattern because without that, we might format the number // as a group without national prefix. return number.getRawInput(); @@ -1515,7 +1513,7 @@ public class PhoneNumberUtil { break; } // Otherwise, we need to remove the national prefix from our output. - NumberFormat numFormatCopy = new NumberFormat(); + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); numFormatCopy.mergeFrom(formatRule); numFormatCopy.clearNationalPrefixFormattingRule(); List<NumberFormat> numberFormats = new ArrayList<NumberFormat>(1); @@ -1635,8 +1633,8 @@ public class PhoneNumberUtil { if (isNANPACountry(regionCallingFrom)) { return countryCode + " " + rawInput; } - } else if (metadataForRegionCallingFrom != null && - countryCode == getCountryCodeForValidRegion(regionCallingFrom)) { + } else if (metadataForRegionCallingFrom != null + && countryCode == getCountryCodeForValidRegion(regionCallingFrom)) { NumberFormat formattingPattern = chooseFormattingPatternForNumber(metadataForRegionCallingFrom.numberFormats(), nationalNumber); @@ -1644,7 +1642,7 @@ public class PhoneNumberUtil { // If no pattern above is matched, we format the original input. return rawInput; } - NumberFormat newFormat = new NumberFormat(); + NumberFormat.Builder newFormat = NumberFormat.newBuilder(); newFormat.mergeFrom(formattingPattern); // The first group is the first group of digits that the user wrote together. newFormat.setPattern("(\\d+)(.*)"); @@ -1794,9 +1792,9 @@ public class PhoneNumberUtil { Matcher m = regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber); String formattedNationalNumber = ""; - if (numberFormat == PhoneNumberFormat.NATIONAL && - carrierCode != null && carrierCode.length() > 0 && - formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) { + if (numberFormat == PhoneNumberFormat.NATIONAL + && carrierCode != null && carrierCode.length() > 0 + && formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) { // Replace the $CC in the formatting rule with the desired carrier code. String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule(); carrierCodeFormattingRule = @@ -1809,9 +1807,9 @@ public class PhoneNumberUtil { } else { // Use the national prefix formatting rule instead. String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule(); - if (numberFormat == PhoneNumberFormat.NATIONAL && - nationalPrefixFormattingRule != null && - nationalPrefixFormattingRule.length() > 0) { + if (numberFormat == PhoneNumberFormat.NATIONAL + && nationalPrefixFormattingRule != null + && nationalPrefixFormattingRule.length() > 0) { Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule); formattedNationalNumber = m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule)); @@ -1968,13 +1966,20 @@ public class PhoneNumberUtil { public PhoneNumber getExampleNumberForNonGeoEntity(int countryCallingCode) { PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); if (metadata != null) { - PhoneNumberDesc desc = metadata.getGeneralDesc(); - try { - if (desc.hasExampleNumber()) { - return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + // For geographical entities, fixed-line data is always present. However, for non-geographical + // entities, this is not the case, so we have to go through different types to find the + // example number. We don't check fixed-line or personal number since they aren't used by + // non-geographical entities (if this changes, a unit-test will catch this.) + for (PhoneNumberDesc desc : Arrays.asList(metadata.getMobile(), metadata.getTollFree(), + metadata.getSharedCost(), metadata.getVoip(), metadata.getVoicemail(), + metadata.getUan(), metadata.getPremiumRate())) { + try { + if (desc != null && desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); } - } catch (NumberParseException e) { - logger.log(Level.SEVERE, e.toString()); } } else { logger.log(Level.WARNING, @@ -2088,8 +2093,8 @@ public class PhoneNumberUtil { } // Otherwise, test to see if the number is mobile. Only do this if certain that the patterns for // mobile and fixed line aren't the same. - if (!metadata.isSameMobileAndFixedLinePattern() && - isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { + if (!metadata.isSameMobileAndFixedLinePattern() + && isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { return PhoneNumberType.MOBILE; } return PhoneNumberType.UNKNOWN; @@ -2113,26 +2118,26 @@ public class PhoneNumberUtil { return metadataSource.getMetadataForNonGeographicalRegion(countryCallingCode); } - boolean isNumberPossibleForDesc(String nationalNumber, PhoneNumberDesc numberDesc) { - Matcher possibleNumberPatternMatcher = - regexCache.getPatternForRegex(numberDesc.getPossibleNumberPattern()) - .matcher(nationalNumber); - return possibleNumberPatternMatcher.matches(); - } - boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) { + // Check if any possible number lengths are present; if so, we use them to avoid checking the + // validation pattern if they don't match. If they are absent, this means they match the general + // description, which we have already checked before checking a specific number type. + int actualLength = nationalNumber.length(); + List<Integer> possibleLengths = numberDesc.getPossibleLengthList(); + if (possibleLengths.size() > 0 && !possibleLengths.contains(actualLength)) { + return false; + } Matcher nationalNumberPatternMatcher = regexCache.getPatternForRegex(numberDesc.getNationalNumberPattern()) .matcher(nationalNumber); - return isNumberPossibleForDesc(nationalNumber, numberDesc) && - nationalNumberPatternMatcher.matches(); + return nationalNumberPatternMatcher.matches(); } /** * Tests whether a phone number matches a valid pattern. Note this doesn't verify the number * is actually in use, which is impossible to tell by just looking at a number itself. * - * @param number the phone number that we want to validate + * @param number the phone number that we want to validate * @return a boolean that indicates whether the number is of a valid pattern */ public boolean isValidNumber(PhoneNumber number) { @@ -2152,16 +2157,16 @@ public class PhoneNumberUtil { * the region "GB" (United Kingdom), since it has its own region code, "IM", which may be * undesirable. * - * @param number the phone number that we want to validate - * @param regionCode the region that we want to validate the phone number for + * @param number the phone number that we want to validate + * @param regionCode the region that we want to validate the phone number for * @return a boolean that indicates whether the number is of a valid pattern */ public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) { int countryCode = number.getCountryCode(); PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); - if ((metadata == null) || - (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) && - countryCode != getCountryCodeForValidRegion(regionCode))) { + if ((metadata == null) + || (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + && countryCode != getCountryCodeForValidRegion(regionCode))) { // Either the region code was invalid, or the country calling code for this number does not // match that of the region code. return false; @@ -2362,32 +2367,35 @@ public class PhoneNumberUtil { } /** - * Helper method to check a number against a particular pattern and determine whether it matches, - * or is too short or too long. Currently, if a number pattern suggests that numbers of length 7 - * and 10 are possible, and a number in between these possible lengths is entered, such as of - * length 8, this will return TOO_LONG. + * Helper method to check a number against possible lengths for this number, and determine whether + * it matches, or is too short or too long. Currently, if a number pattern suggests that numbers + * of length 7 and 10 are possible, and a number in between these possible lengths is entered, + * such as of length 8, this will return TOO_LONG. */ - private ValidationResult testNumberLengthAgainstPattern(Pattern numberPattern, String number) { - Matcher numberMatcher = numberPattern.matcher(number); - if (numberMatcher.matches()) { + private ValidationResult testNumberLength(String number, PhoneNumberDesc phoneNumberDesc) { + List<Integer> possibleLengths = phoneNumberDesc.getPossibleLengthList(); + List<Integer> localLengths = phoneNumberDesc.getPossibleLengthLocalOnlyList(); + int actualLength = number.length(); + if (localLengths.contains(actualLength)) { return ValidationResult.IS_POSSIBLE; } - if (numberMatcher.lookingAt()) { - return ValidationResult.TOO_LONG; - } else { + // There should always be "possibleLengths" set for every element. This will be a build-time + // check once ShortNumberMetadata.xml is migrated to contain this information as well. + int minimumLength = possibleLengths.get(0); + if (minimumLength == actualLength) { + return ValidationResult.IS_POSSIBLE; + } else if (minimumLength > actualLength) { return ValidationResult.TOO_SHORT; + } else if (possibleLengths.get(possibleLengths.size() - 1) < actualLength) { + return ValidationResult.TOO_LONG; } - } - - /** - * Helper method to check whether a number is too short to be a regular length phone number in a - * region. - */ - private boolean isShorterThanPossibleNormalNumber(PhoneMetadata regionMetadata, String number) { - Pattern possibleNumberPattern = regexCache.getPatternForRegex( - regionMetadata.getGeneralDesc().getPossibleNumberPattern()); - return testNumberLengthAgainstPattern(possibleNumberPattern, number) == - ValidationResult.TOO_SHORT; + // Note that actually the number is not too long if possibleLengths does not contain the length: + // we know it is less than the highest possible number length, and higher than the lowest + // possible number length. However, we don't currently have an enum to express this, so we + // return TOO_LONG in the short-term. + // We skip the first element; we've already checked it. + return possibleLengths.subList(1, possibleLengths.size()).contains(actualLength) + ? ValidationResult.IS_POSSIBLE : ValidationResult.TOO_LONG; } /** @@ -2424,9 +2432,7 @@ public class PhoneNumberUtil { String regionCode = getRegionCodeForCountryCode(countryCode); // Metadata cannot be null because the country calling code is valid. PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); - Pattern possibleNumberPattern = - regexCache.getPatternForRegex(metadata.getGeneralDesc().getPossibleNumberPattern()); - return testNumberLengthAgainstPattern(possibleNumberPattern, nationalNumber); + return testNumberLength(nationalNumber, metadata.getGeneralDesc()); } /** @@ -2460,8 +2466,8 @@ public class PhoneNumberUtil { * Attempts to extract a valid number from a phone number that is too long to be valid, and resets * the PhoneNumber object passed in to that valid version. If no valid number could be extracted, * the PhoneNumber object passed in will not be modified. - * @param number a PhoneNumber object which contains a number that is too long to be valid. - * @return true if a valid phone number can be successfully extracted. + * @param number a PhoneNumber object which contains a number that is too long to be valid + * @return true if a valid phone number can be successfully extracted */ public boolean truncateTooLongNumber(PhoneNumber number) { if (isValidNumber(number)) { @@ -2473,8 +2479,8 @@ public class PhoneNumberUtil { do { nationalNumber /= 10; numberCopy.setNationalNumber(nationalNumber); - if (isPossibleNumberWithReason(numberCopy) == ValidationResult.TOO_SHORT || - nationalNumber == 0) { + if (isPossibleNumberWithReason(numberCopy) == ValidationResult.TOO_SHORT + || nationalNumber == 0) { return false; } } while (!isValidNumber(numberCopy)); @@ -2596,15 +2602,12 @@ public class PhoneNumberUtil { regexCache.getPatternForRegex(generalDesc.getNationalNumberPattern()); maybeStripNationalPrefixAndCarrierCode( potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */); - Pattern possibleNumberPattern = - regexCache.getPatternForRegex(generalDesc.getPossibleNumberPattern()); // If the number was not valid before but is valid now, or if it was too long before, we // consider the number with the country calling code stripped to be a better result and // keep that instead. - if ((!validNumberPattern.matcher(fullNumber).matches() && - validNumberPattern.matcher(potentialNationalNumber).matches()) || - testNumberLengthAgainstPattern(possibleNumberPattern, fullNumber.toString()) - == ValidationResult.TOO_LONG) { + if ((!validNumberPattern.matcher(fullNumber).matches() + && validNumberPattern.matcher(potentialNationalNumber).matches()) + || testNumberLength(fullNumber.toString(), generalDesc) == ValidationResult.TOO_LONG) { nationalNumber.append(potentialNationalNumber); if (keepRawInput) { phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); @@ -2647,12 +2650,12 @@ public class PhoneNumberUtil { * the resulting number, and indicates if an international prefix was present. * * @param number the non-normalized telephone number that we wish to strip any international - * dialing prefix from. + * dialing prefix from * @param possibleIddPrefix the international direct dialing prefix from the region we * think this number may be dialed in * @return the corresponding CountryCodeSource if an international dialing prefix could be * removed from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if the number did - * not seem to be in international format. + * not seem to be in international format */ // @VisibleForTesting CountryCodeSource maybeStripInternationalPrefixAndNormalize( @@ -2684,7 +2687,7 @@ public class PhoneNumberUtil { * dialing prefix from * @param metadata the metadata for the region that we think this number is from * @param carrierCode a place to insert the carrier code if one is extracted - * @return true if a national prefix or carrier code (or both) could be extracted. + * @return true if a national prefix or carrier code (or both) could be extracted */ // @VisibleForTesting boolean maybeStripNationalPrefixAndCarrierCode( @@ -2707,11 +2710,11 @@ public class PhoneNumberUtil { // remove the national prefix. int numOfGroups = prefixMatcher.groupCount(); String transformRule = metadata.getNationalPrefixTransformRule(); - if (transformRule == null || transformRule.length() == 0 || - prefixMatcher.group(numOfGroups) == null) { + if (transformRule == null || transformRule.length() == 0 + || prefixMatcher.group(numOfGroups) == null) { // If the original number was viable, and the resultant number is not, we return. - if (isViableOriginalNumber && - !nationalNumberRule.matcher(number.substring(prefixMatcher.end())).matches()) { + if (isViableOriginalNumber + && !nationalNumberRule.matcher(number.substring(prefixMatcher.end())).matches()) { return false; } if (carrierCode != null && numOfGroups > 0 && prefixMatcher.group(numOfGroups) != null) { @@ -2724,8 +2727,8 @@ public class PhoneNumberUtil { // the string buffer and making the transformation on the copy first. StringBuilder transformedNumber = new StringBuilder(number); transformedNumber.replace(0, numberLength, prefixMatcher.replaceFirst(transformRule)); - if (isViableOriginalNumber && - !nationalNumberRule.matcher(transformedNumber.toString()).matches()) { + if (isViableOriginalNumber + && !nationalNumberRule.matcher(transformedNumber.toString()).matches()) { return false; } if (carrierCode != null && numOfGroups > 1) { @@ -2743,7 +2746,7 @@ public class PhoneNumberUtil { * usually indicated with extn, ext, x or similar) from the end of the number, and returns it. * * @param number the non-normalized telephone number that we wish to strip the extension from - * @return the phone extension + * @return the phone extension */ // @VisibleForTesting String maybeStripExtension(StringBuilder number) { @@ -2773,8 +2776,8 @@ public class PhoneNumberUtil { private boolean checkRegionForParsing(String numberToParse, String defaultRegion) { if (!isValidRegionCode(defaultRegion)) { // If the number is null or empty, we can't infer the region. - if ((numberToParse == null) || (numberToParse.length() == 0) || - !PLUS_CHARS_PATTERN.matcher(numberToParse).lookingAt()) { + if ((numberToParse == null) || (numberToParse.length() == 0) + || !PLUS_CHARS_PATTERN.matcher(numberToParse).lookingAt()) { return false; } } @@ -2795,20 +2798,18 @@ public class PhoneNumberUtil { * is actually a valid number for a particular region is not performed. This can be done * separately with {@link #isValidNumber}. * - * @param numberToParse number that we are attempting to parse. This can contain formatting - * such as +, ( and -, as well as a phone number extension. It can also - * be provided in RFC3966 format. - * @param defaultRegion region that we are expecting the number to be from. This is only used - * if the number being parsed is not written in international format. - * The country_code for the number in this case would be stored as that - * of the default region supplied. If the number is guaranteed to - * start with a '+' followed by the country calling code, then - * "ZZ" or null can be supplied. - * @return a phone number proto buffer filled with the parsed number + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. It can also be provided in RFC3966 + * format. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. If the number + * is guaranteed to start with a '+' followed by the country calling code, then RegionCode.ZZ + * or null can be supplied. + * @return a phone number proto buffer filled with the parsed number * @throws NumberParseException if the string is not considered to be a viable phone number (e.g. - * too few or too many digits) or if no default region was supplied - * and the number is not in international format (does not start - * with +) + * too few or too many digits) or if no default region was supplied and the number is not in + * international format (does not start with +) */ public PhoneNumber parse(String numberToParse, String defaultRegion) throws NumberParseException { @@ -2831,15 +2832,14 @@ public class PhoneNumberUtil { * in that it always populates the raw_input field of the protocol buffer with numberToParse as * well as the country_code_source field. * - * @param numberToParse number that we are attempting to parse. This can contain formatting - * such as +, ( and -, as well as a phone number extension. - * @param defaultRegion region that we are expecting the number to be from. This is only used - * if the number being parsed is not written in international format. - * The country calling code for the number in this case would be stored - * as that of the default region supplied. - * @return a phone number proto buffer filled with the parsed number + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country calling code + * for the number in this case would be stored as that of the default region supplied. + * @return a phone number proto buffer filled with the parsed number * @throws NumberParseException if the string is not considered to be a viable phone number or if - * no default region was supplied + * no default region was supplied */ public PhoneNumber parseAndKeepRawInput(String numberToParse, String defaultRegion) throws NumberParseException { @@ -2863,12 +2863,11 @@ public class PhoneNumberUtil { * is a shortcut for {@link #findNumbers(CharSequence, String, Leniency, long) * getMatcher(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE)}. * - * @param text the text to search for phone numbers, null for no text - * @param defaultRegion region that we are expecting the number to be from. This is only used - * if the number being parsed is not written in international format. The - * country_code for the number in this case would be stored as that of - * the default region supplied. May be null if only international - * numbers are expected. + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. */ public Iterable<PhoneNumberMatch> findNumbers(CharSequence text, String defaultRegion) { return findNumbers(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE); @@ -2877,16 +2876,15 @@ public class PhoneNumberUtil { /** * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. * - * @param text the text to search for phone numbers, null for no text - * @param defaultRegion region that we are expecting the number to be from. This is only used - * if the number being parsed is not written in international format. The - * country_code for the number in this case would be stored as that of - * the default region supplied. May be null if only international - * numbers are expected. - * @param leniency the leniency to use when evaluating candidate phone numbers - * @param maxTries the maximum number of invalid numbers to try before giving up on the - * text. This is to cover degenerate cases where the text has a lot of - * false positives in it. Must be {@code >= 0}. + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. + * @param leniency the leniency to use when evaluating candidate phone numbers + * @param maxTries the maximum number of invalid numbers to try before giving up on the text. + * This is to cover degenerate cases where the text has a lot of false positives in it. Must + * be {@code >= 0}. */ public Iterable<PhoneNumberMatch> findNumbers( final CharSequence text, final String defaultRegion, final Leniency leniency, @@ -2910,8 +2908,8 @@ public class PhoneNumberUtil { int numberOfLeadingZeros = 1; // Note that if the national number is all "0"s, the last "0" is not counted as a leading // zero. - while (numberOfLeadingZeros < nationalNumber.length() - 1 && - nationalNumber.charAt(numberOfLeadingZeros) == '0') { + while (numberOfLeadingZeros < nationalNumber.length() - 1 + && nationalNumber.charAt(numberOfLeadingZeros) == '0') { numberOfLeadingZeros++; } if (numberOfLeadingZeros != 1) { @@ -2975,8 +2973,8 @@ public class PhoneNumberUtil { normalizedNationalNumber, keepRawInput, phoneNumber); } catch (NumberParseException e) { Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber.toString()); - if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE && - matcher.lookingAt()) { + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE + && matcher.lookingAt()) { // Strip the plus-char, and try again. countryCode = maybeExtractCountryCode(nationalNumber.substring(matcher.end()), regionMetadata, normalizedNationalNumber, @@ -3016,11 +3014,12 @@ public class PhoneNumberUtil { StringBuilder potentialNationalNumber = new StringBuilder(normalizedNationalNumber); maybeStripNationalPrefixAndCarrierCode(potentialNationalNumber, regionMetadata, carrierCode); // We require that the NSN remaining after stripping the national prefix and carrier code be - // of a possible length for the region. Otherwise, we don't do the stripping, since the - // original number could be a valid short number. - if (!isShorterThanPossibleNormalNumber(regionMetadata, potentialNationalNumber.toString())) { + // long enough to be a possible length for the region. Otherwise, we don't do the stripping, + // since the original number could be a valid short number. + if (testNumberLength(potentialNationalNumber.toString(), regionMetadata.getGeneralDesc()) + != ValidationResult.TOO_SHORT) { normalizedNationalNumber = potentialNationalNumber; - if (keepRawInput) { + if (keepRawInput && carrierCode.length() > 0) { phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString()); } } @@ -3065,8 +3064,8 @@ public class PhoneNumberUtil { // handle the case when "tel:" is missing, as we have seen in some of the phone number inputs. // In that case, we append everything from the beginning. int indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX); - int indexOfNationalNumber = (indexOfRfc3966Prefix >= 0) ? - indexOfRfc3966Prefix + RFC3966_PREFIX.length() : 0; + int indexOfNationalNumber = (indexOfRfc3966Prefix >= 0) + ? indexOfRfc3966Prefix + RFC3966_PREFIX.length() : 0; nationalNumber.append(numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext)); } else { // Extract a possible number from the string passed in (this strips leading characters that @@ -3120,17 +3119,17 @@ public class PhoneNumberUtil { secondNumber.clearRawInput(); secondNumber.clearCountryCodeSource(); secondNumber.clearPreferredDomesticCarrierCode(); - if (firstNumber.hasExtension() && - firstNumber.getExtension().length() == 0) { - firstNumber.clearExtension(); + if (firstNumber.hasExtension() + && firstNumber.getExtension().length() == 0) { + firstNumber.clearExtension(); } - if (secondNumber.hasExtension() && - secondNumber.getExtension().length() == 0) { - secondNumber.clearExtension(); + if (secondNumber.hasExtension() + && secondNumber.getExtension().length() == 0) { + secondNumber.clearExtension(); } // Early exit if both had extensions and these are different. - if (firstNumber.hasExtension() && secondNumber.hasExtension() && - !firstNumber.getExtension().equals(secondNumber.getExtension())) { + if (firstNumber.hasExtension() && secondNumber.hasExtension() + && !firstNumber.getExtension().equals(secondNumber.getExtension())) { return MatchType.NO_MATCH; } int firstNumberCountryCode = firstNumber.getCountryCode(); @@ -3139,8 +3138,8 @@ public class PhoneNumberUtil { if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) { if (firstNumber.exactlySameAs(secondNumber)) { return MatchType.EXACT_MATCH; - } else if (firstNumberCountryCode == secondNumberCountryCode && - isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { + } else if (firstNumberCountryCode == secondNumberCountryCode + && isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { // A SHORT_NSN_MATCH occurs if there is a difference because of the presence or absence of // an 'Italian leading zero', the presence or absence of an extension, or one NSN being a // shorter variant of the other. @@ -3168,8 +3167,8 @@ public class PhoneNumberUtil { String firstNumberNationalNumber = String.valueOf(firstNumber.getNationalNumber()); String secondNumberNationalNumber = String.valueOf(secondNumber.getNationalNumber()); // Note that endsWith returns true if the numbers are equal. - return firstNumberNationalNumber.endsWith(secondNumberNationalNumber) || - secondNumberNationalNumber.endsWith(firstNumberNationalNumber); + return firstNumberNationalNumber.endsWith(secondNumberNationalNumber) + || secondNumberNationalNumber.endsWith(firstNumberNationalNumber); } /** @@ -3215,7 +3214,7 @@ public class PhoneNumberUtil { * Takes two phone numbers and compares them for equality. This is a convenience wrapper for * {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known. * - * @param firstNumber first number to compare in proto buffer format. + * @param firstNumber first number to compare in proto buffer format * @param secondNumber second number to compare. Can contain formatting, and can have country * calling code specified with + at the start. * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See @@ -3283,7 +3282,7 @@ public class PhoneNumberUtil { * invalid, unknown or regions that don't support mobile number portability. * * @param regionCode the region for which we want to know whether it supports mobile number - * portability or not. + * portability or not */ public boolean isMobileNumberPortableRegion(String regionCode) { PhoneMetadata metadata = getMetadataForRegion(regionCode); |