From 7e6feaeeea64a9fdde5496eca09c1aad9421226b Mon Sep 17 00:00:00 2001 From: lararennie Date: Thu, 13 Jul 2017 12:20:31 +0200 Subject: [PATCH] Replacing some public APIs that take phone numbers as strings with CharSequence. Removed two private methods that were unused (leftover from a previous commit). (#1847) --- .../i18n/phonenumbers/PhoneNumberMatcher.java | 20 +- .../i18n/phonenumbers/PhoneNumberUtil.java | 194 ++++++++---------- .../i18n/phonenumbers/ShortNumberInfo.java | 13 +- .../phonenumbers/PhoneNumberUtilTest.java | 20 +- pending_code_changes.txt | 10 + 5 files changed, 115 insertions(+), 142 deletions(-) diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java index 21dbdf86a..8310fe3c1 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java @@ -326,15 +326,14 @@ final class PhoneNumberMatcher implements Iterator { } // Try to come up with a valid match given the entire candidate. - String rawString = candidate.toString(); - PhoneNumberMatch match = parseAndVerify(rawString, offset); + PhoneNumberMatch match = parseAndVerify(candidate, offset); if (match != null) { return match; } // If that failed, try to find an "inner match" - there might be a phone number within this // candidate. - return extractInnerMatch(rawString, offset); + return extractInnerMatch(candidate, offset); } /** @@ -345,7 +344,7 @@ final class PhoneNumberMatcher implements Iterator { * @param offset the current offset of {@code candidate} within {@link #text} * @return the match found, null if none can be found */ - private PhoneNumberMatch extractInnerMatch(String candidate, int offset) { + private PhoneNumberMatch extractInnerMatch(CharSequence candidate, int offset) { for (Pattern possibleInnerMatch : INNER_MATCHES) { Matcher groupMatcher = possibleInnerMatch.matcher(candidate); boolean isFirstMatch = true; @@ -354,8 +353,8 @@ final class PhoneNumberMatcher implements Iterator { // We should handle any group before this one too. CharSequence group = trimAfterFirstMatch( PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, - candidate.substring(0, groupMatcher.start())); - PhoneNumberMatch match = parseAndVerify(group.toString(), offset); + candidate.subSequence(0, groupMatcher.start())); + PhoneNumberMatch match = parseAndVerify(group, offset); if (match != null) { return match; } @@ -364,7 +363,7 @@ final class PhoneNumberMatcher implements Iterator { } CharSequence group = trimAfterFirstMatch( PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, groupMatcher.group(1)); - PhoneNumberMatch match = parseAndVerify(group.toString(), offset + groupMatcher.start(1)); + PhoneNumberMatch match = parseAndVerify(group, offset + groupMatcher.start(1)); if (match != null) { return match; } @@ -383,7 +382,7 @@ final class PhoneNumberMatcher implements Iterator { * @param offset the offset of {@code candidate} within {@link #text} * @return the parsed and validated phone number match, or null */ - private PhoneNumberMatch parseAndVerify(String candidate, int offset) { + private PhoneNumberMatch parseAndVerify(CharSequence candidate, int offset) { try { // Check the candidate doesn't contain any formatting which would indicate that it really // isn't a phone number. @@ -440,7 +439,7 @@ final class PhoneNumberMatcher implements Iterator { number.clearCountryCodeSource(); number.clearRawInput(); number.clearPreferredDomesticCarrierCode(); - return new PhoneNumberMatch(offset, candidate, number); + return new PhoneNumberMatch(offset, candidate.toString(), number); } } catch (NumberParseException e) { // ignore and continue @@ -572,7 +571,8 @@ final class PhoneNumberMatcher implements Iterator { } static boolean checkNumberGroupingIsValid( - PhoneNumber number, String candidate, PhoneNumberUtil util, NumberGroupingChecker checker) { + PhoneNumber number, CharSequence candidate, PhoneNumberUtil util, + NumberGroupingChecker checker) { // TODO: Evaluate how this works for other locales (testing has been limited to NANPA regions) // and optimise if necessary. StringBuilder normalizedCandidate = diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index 68bbbaee0..4f608673c 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -363,9 +363,11 @@ public class PhoneNumberUtil { // correctly. Therefore, we use \d, so that the first group actually used in the pattern will be // matched. private static final Pattern FIRST_GROUP_PATTERN = Pattern.compile("(\\$\\d)"); - private static final Pattern NP_PATTERN = Pattern.compile("\\$NP"); - private static final Pattern FG_PATTERN = Pattern.compile("\\$FG"); - private static final Pattern CC_PATTERN = Pattern.compile("\\$CC"); + // Constants used in the formatting rules to represent the national prefix, first group and + // carrier code respectively. + private static final String NP_STRING = "$NP"; + private static final String FG_STRING = "$FG"; + private static final String CC_STRING = "$CC"; // A pattern that is used to determine if the national prefix formatting rule has the first group // only, i.e., does not start with the national prefix. Note that the pattern explicitly allows @@ -478,7 +480,7 @@ public class PhoneNumberUtil { */ POSSIBLE { @Override - boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { + boolean verify(PhoneNumber number, CharSequence candidate, PhoneNumberUtil util) { return util.isPossibleNumber(number); } }, @@ -490,9 +492,9 @@ public class PhoneNumberUtil { */ VALID { @Override - boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { + boolean verify(PhoneNumber number, CharSequence candidate, PhoneNumberUtil util) { if (!util.isValidNumber(number) - || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util)) { + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate.toString(), util)) { return false; } return PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util); @@ -512,10 +514,11 @@ public class PhoneNumberUtil { */ STRICT_GROUPING { @Override - boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { + boolean verify(PhoneNumber number, CharSequence candidate, PhoneNumberUtil util) { + String candidateString = candidate.toString(); if (!util.isValidNumber(number) - || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) - || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { return false; } @@ -544,10 +547,11 @@ public class PhoneNumberUtil { */ EXACT_GROUPING { @Override - boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { + boolean verify(PhoneNumber number, CharSequence candidate, PhoneNumberUtil util) { + String candidateString = candidate.toString(); if (!util.isValidNumber(number) - || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) - || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { return false; } @@ -565,7 +569,7 @@ public class PhoneNumberUtil { }; /** Returns true if {@code number} is a verified number according to this leniency. */ - abstract boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util); + abstract boolean verify(PhoneNumber number, CharSequence candidate, PhoneNumberUtil util); } // A source of metadata for different regions. @@ -644,20 +648,20 @@ public class PhoneNumberUtil { * string if no character used to start phone numbers (such as + or any digit) is found in the * number */ - static String extractPossibleNumber(String number) { + static CharSequence extractPossibleNumber(CharSequence number) { Matcher m = VALID_START_CHAR_PATTERN.matcher(number); if (m.find()) { - number = number.substring(m.start()); + number = number.subSequence(m.start(), number.length()); // Remove trailing non-alpha non-numerical characters. Matcher trailingCharsMatcher = UNWANTED_END_CHAR_PATTERN.matcher(number); if (trailingCharsMatcher.find()) { - number = number.substring(0, trailingCharsMatcher.start()); + number = number.subSequence(0, trailingCharsMatcher.start()); logger.log(Level.FINER, "Stripped trailing characters: " + number); } // Check for extra numbers at the end. Matcher secondNumber = SECOND_NUMBER_START_PATTERN.matcher(number); if (secondNumber.find()) { - number = number.substring(0, secondNumber.start()); + number = number.subSequence(0, secondNumber.start()); } return number; } else { @@ -676,7 +680,7 @@ public class PhoneNumberUtil { * @return true if the number could be a phone number of some sort, otherwise false */ // @VisibleForTesting - static boolean isViablePhoneNumber(String number) { + static boolean isViablePhoneNumber(CharSequence number) { if (number.length() < MIN_LENGTH_FOR_NSN) { return false; } @@ -687,38 +691,27 @@ public class PhoneNumberUtil { /** * Normalizes a string of characters representing a phone number. This performs the following * conversions: - * Punctuation is stripped. + * - Punctuation is stripped. * For ALPHA/VANITY numbers: - * Letters are converted to their numeric representation on a telephone keypad. The keypad - * used here is the one defined in ITU Recommendation E.161. This is only done if there are - * 3 or more letters in the number, to lessen the risk that such letters are typos. + * - Letters are converted to their numeric representation on a telephone keypad. The keypad + * used here is the one defined in ITU Recommendation E.161. This is only done if there are 3 + * or more letters in the number, to lessen the risk that such letters are typos. * For other numbers: - * Wide-ascii digits are converted to normal ASCII (European) digits. - * Arabic-Indic numerals are converted to European numerals. - * Spurious alpha characters are stripped. + * - Wide-ascii digits are converted to normal ASCII (European) digits. + * - Arabic-Indic numerals are converted to European numerals. + * - Spurious alpha characters are stripped. * - * @param number a string of characters representing a phone number - * @return the normalized string version of the phone number + * @param number a StringBuilder of characters representing a phone number that will be + * normalized in place */ - static String normalize(String number) { + static StringBuilder normalize(StringBuilder number) { Matcher m = VALID_ALPHA_PHONE_PATTERN.matcher(number); if (m.matches()) { - return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, true); + number.replace(0, number.length(), normalizeHelper(number, ALPHA_PHONE_MAPPINGS, true)); } else { - return normalizeDigitsOnly(number); + number.replace(0, number.length(), normalizeDigitsOnly(number)); } - } - - /** - * Normalizes a string of characters representing a phone number. This is a wrapper for - * normalize(String number) but does in-place normalization of the StringBuilder provided. - * - * @param number a StringBuilder of characters representing a phone number that will be - * normalized in place - */ - static void normalize(StringBuilder number) { - String normalizedNumber = normalize(number.toString()); - number.replace(0, number.length(), normalizedNumber); + return number; } /** @@ -728,13 +721,14 @@ public class PhoneNumberUtil { * @param number a string of characters representing a phone number * @return the normalized string version of the phone number */ - public static String normalizeDigitsOnly(String number) { + public static String normalizeDigitsOnly(CharSequence number) { return normalizeDigits(number, false /* strip non-digits */).toString(); } - static StringBuilder normalizeDigits(String number, boolean keepNonDigits) { + static StringBuilder normalizeDigits(CharSequence number, boolean keepNonDigits) { StringBuilder normalizedDigits = new StringBuilder(number.length()); - for (char c : number.toCharArray()) { + for (int i = 0; i < number.length(); i++) { + char c = number.charAt(i); int digit = Character.digit(c, 10); if (digit != -1) { normalizedDigits.append(digit); @@ -752,7 +746,7 @@ public class PhoneNumberUtil { * @param number a string of characters representing a phone number * @return the normalized string version of the phone number */ - public static String normalizeDiallableCharsOnly(String number) { + public static String normalizeDiallableCharsOnly(CharSequence number) { return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */); } @@ -760,7 +754,7 @@ public class PhoneNumberUtil { * Converts all alpha characters in a number to their respective digits on a keypad, but retains * existing formatting. */ - public static String convertAlphaCharactersInNumber(String number) { + public static String convertAlphaCharactersInNumber(CharSequence number) { return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, false); } @@ -930,7 +924,7 @@ public class PhoneNumberUtil { * 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, + private static String normalizeHelper(CharSequence number, Map normalizationReplacements, boolean removeNonMatches) { StringBuilder normalizedNumber = new StringBuilder(number.length()); @@ -1267,9 +1261,8 @@ public class PhoneNumberUtil { if (nationalPrefix.length() > 0) { // Replace $NP with national prefix and $FG with the first group ($1). nationalPrefixFormattingRule = - NP_PATTERN.matcher(nationalPrefixFormattingRule).replaceFirst(nationalPrefix); - nationalPrefixFormattingRule = - FG_PATTERN.matcher(nationalPrefixFormattingRule).replaceFirst("\\$1"); + nationalPrefixFormattingRule.replace(NP_STRING, nationalPrefix); + nationalPrefixFormattingRule = nationalPrefixFormattingRule.replace(FG_STRING, "$1"); numFormatCopy.setNationalPrefixFormattingRule(nationalPrefixFormattingRule); } else { // We don't want to have a rule for how to format the national prefix if there isn't one. @@ -1295,7 +1288,7 @@ public class PhoneNumberUtil { * @return the formatted phone number in national format for dialing using the carrier as * specified in the {@code carrierCode} */ - public String formatNationalNumberWithCarrierCode(PhoneNumber number, String carrierCode) { + public String formatNationalNumberWithCarrierCode(PhoneNumber number, CharSequence carrierCode) { int countryCallingCode = number.getCountryCode(); String nationalSignificantNumber = getNationalSignificantNumber(number); if (!hasValidCountryCallingCode(countryCallingCode)) { @@ -1343,7 +1336,7 @@ public class PhoneNumberUtil { * none is found */ public String formatNationalNumberWithPreferredCarrierCode(PhoneNumber number, - String fallbackCarrierCode) { + CharSequence 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 @@ -1658,14 +1651,6 @@ public class PhoneNumberUtil { return false; } - /** - * Returns true if a number is from a region whose national significant number couldn't contain a - * leading zero, but has the italian_leading_zero field set to true. - */ - private boolean hasUnexpectedItalianLeadingZero(PhoneNumber number) { - return number.isItalianLeadingZero() && !isLeadingZeroPossible(number.getCountryCode()); - } - private boolean hasFormattingPatternForNumber(PhoneNumber number) { int countryCallingCode = number.getCountryCode(); String phoneNumberRegion = getRegionCodeForCountryCode(countryCallingCode); @@ -1849,7 +1834,7 @@ public class PhoneNumberUtil { private String formatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat, - String carrierCode) { + CharSequence carrierCode) { List intlNumberFormats = metadata.intlNumberFormats(); // When the intlNumberFormats exists, we use that to format national number for the // INTERNATIONAL format instead of using the numberDesc.numberFormats. @@ -1891,7 +1876,7 @@ public class PhoneNumberUtil { private String formatNsnUsingPattern(String nationalNumber, NumberFormat formattingPattern, PhoneNumberFormat numberFormat, - String carrierCode) { + CharSequence carrierCode) { String numberFormatRule = formattingPattern.getFormat(); Matcher m = regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber); @@ -1901,8 +1886,7 @@ public class PhoneNumberUtil { && formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) { // Replace the $CC in the formatting rule with the desired carrier code. String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule(); - carrierCodeFormattingRule = - CC_PATTERN.matcher(carrierCodeFormattingRule).replaceFirst(carrierCode); + carrierCodeFormattingRule = carrierCodeFormattingRule.replace(CC_STRING, carrierCode); // Now replace the $FG in the formatting rule with the first group and the carrier code // combined in the appropriate way. numberFormatRule = FIRST_GROUP_PATTERN.matcher(numberFormatRule) @@ -2427,21 +2411,6 @@ public class PhoneNumberUtil { return nanpaRegions.contains(regionCode); } - /** - * Checks whether the country calling code is from a region whose national significant number - * could contain a leading zero. An example of such a region is Italy. Returns false if no - * metadata for the country is found. - */ - boolean isLeadingZeroPossible(int countryCallingCode) { - PhoneMetadata mainMetadataForCallingCode = - getMetadataForRegionOrCallingCode(countryCallingCode, - getRegionCodeForCountryCode(countryCallingCode)); - if (mainMetadataForCallingCode == null) { - return false; - } - return mainMetadataForCallingCode.isLeadingZeroPossible(); - } - /** * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. A valid vanity * number will start with at least 3 digits and will have three or more alpha characters. This @@ -2452,7 +2421,7 @@ public class PhoneNumberUtil { * @param number the number that needs to be checked * @return true if the number is a valid vanity number */ - public boolean isAlphaNumber(String number) { + public boolean isAlphaNumber(CharSequence number) { if (!isViablePhoneNumber(number)) { // Number is too short, or doesn't match the basic phone number pattern. return false; @@ -2503,7 +2472,7 @@ public class PhoneNumberUtil { * 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 testNumberLength(String number, PhoneMetadata metadata) { + private ValidationResult testNumberLength(CharSequence number, PhoneMetadata metadata) { return testNumberLength(number, metadata, PhoneNumberType.UNKNOWN); } @@ -2514,7 +2483,7 @@ public class PhoneNumberUtil { * entered, such as of length 8, this will return TOO_LONG. */ private ValidationResult testNumberLength( - String number, PhoneMetadata metadata, PhoneNumberType type) { + CharSequence number, PhoneMetadata metadata, PhoneNumberType type) { PhoneNumberDesc descForType = getNumberDescByType(metadata, type); // There should always be "possibleLengths" set for every element. This is declared in the XML // schema which is verified by PhoneNumberMetadataSchemaTest. @@ -2662,7 +2631,7 @@ public class PhoneNumberUtil { *

This method first parses the number, then invokes {@link #isPossibleNumber(PhoneNumber)} * with the resultant PhoneNumber object. * - * @param number the number that needs to be checked, in the form of a string + * @param number the number that needs to be checked * @param regionDialingFrom the region that we are expecting the number to be dialed from. * Note this is different from the region where the number belongs. For example, the number * +1 650 253 0000 is a number that belongs to US. When written in this form, it can be @@ -2673,7 +2642,7 @@ public class PhoneNumberUtil { * specific). * @return true if the number is possible */ - public boolean isPossibleNumber(String number, String regionDialingFrom) { + public boolean isPossibleNumber(CharSequence number, String regionDialingFrom) { try { return isPossibleNumber(parse(number, regionDialingFrom)); } catch (NumberParseException e) { @@ -2771,7 +2740,7 @@ public class PhoneNumberUtil { * @return the country calling code extracted or 0 if none could be extracted */ // @VisibleForTesting - int maybeExtractCountryCode(String number, PhoneMetadata defaultRegionMetadata, + int maybeExtractCountryCode(CharSequence number, PhoneMetadata defaultRegionMetadata, StringBuilder nationalNumber, boolean keepRawInput, PhoneNumber phoneNumber) throws NumberParseException { @@ -2824,8 +2793,7 @@ public class PhoneNumberUtil { // keep that instead. if ((!matcherApi.matchNationalNumber(fullNumber, generalDesc, false) && matcherApi.matchNationalNumber(potentialNationalNumber, generalDesc, false)) - || testNumberLength(fullNumber.toString(), defaultRegionMetadata) - == ValidationResult.TOO_LONG) { + || testNumberLength(fullNumber, defaultRegionMetadata) == ValidationResult.TOO_LONG) { nationalNumber.append(potentialNationalNumber); if (keepRawInput) { phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); @@ -2991,7 +2959,7 @@ public class PhoneNumberUtil { * parse starts with a + symbol so that we can attempt to infer the region from the number. * Returns false if it cannot use the region provided and the region cannot be inferred. */ - private boolean checkRegionForParsing(String numberToParse, String defaultRegion) { + private boolean checkRegionForParsing(CharSequence 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) @@ -3035,7 +3003,7 @@ public class PhoneNumberUtil { * 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) + public PhoneNumber parse(CharSequence numberToParse, String defaultRegion) throws NumberParseException { PhoneNumber phoneNumber = new PhoneNumber(); parse(numberToParse, defaultRegion, phoneNumber); @@ -3043,10 +3011,10 @@ public class PhoneNumberUtil { } /** - * Same as {@link #parse(String, String)}, but accepts mutable PhoneNumber as a parameter to - * decrease object creation when invoked many times. + * Same as {@link #parse(CharSequence, String)}, but accepts mutable PhoneNumber as a + * parameter to decrease object creation when invoked many times. */ - public void parse(String numberToParse, String defaultRegion, PhoneNumber phoneNumber) + public void parse(CharSequence numberToParse, String defaultRegion, PhoneNumber phoneNumber) throws NumberParseException { parseHelper(numberToParse, defaultRegion, false, true, phoneNumber); } @@ -3065,7 +3033,7 @@ public class PhoneNumberUtil { * @throws NumberParseException if the string is not considered to be a viable phone number or if * no default region was supplied */ - public PhoneNumber parseAndKeepRawInput(String numberToParse, String defaultRegion) + public PhoneNumber parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion) throws NumberParseException { PhoneNumber phoneNumber = new PhoneNumber(); parseAndKeepRawInput(numberToParse, defaultRegion, phoneNumber); @@ -3073,10 +3041,10 @@ public class PhoneNumberUtil { } /** - * Same as{@link #parseAndKeepRawInput(String, String)}, but accepts a mutable PhoneNumber as - * a parameter to decrease object creation when invoked many times. + * Same as{@link #parseAndKeepRawInput(CharSequence, String)}, but accepts a mutable + * PhoneNumber as a parameter to decrease object creation when invoked many times. */ - public void parseAndKeepRawInput(String numberToParse, String defaultRegion, + public void parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion, PhoneNumber phoneNumber) throws NumberParseException { parseHelper(numberToParse, defaultRegion, true, true, phoneNumber); @@ -3126,7 +3094,8 @@ public class PhoneNumberUtil { /** * A helper function to set the values related to leading zeros in a PhoneNumber. */ - static void setItalianLeadingZerosForPhoneNumber(String nationalNumber, PhoneNumber phoneNumber) { + static void setItalianLeadingZerosForPhoneNumber(CharSequence nationalNumber, + PhoneNumber phoneNumber) { if (nationalNumber.length() > 1 && nationalNumber.charAt(0) == '0') { phoneNumber.setItalianLeadingZero(true); int numberOfLeadingZeros = 1; @@ -3151,8 +3120,8 @@ public class PhoneNumberUtil { * Note if any new field is added to this method that should always be filled in, even when * keepRawInput is false, it should also be handled in the copyCoreFieldsOnly() method. */ - private void parseHelper(String numberToParse, String defaultRegion, boolean keepRawInput, - boolean checkRegion, PhoneNumber phoneNumber) + private void parseHelper(CharSequence numberToParse, String defaultRegion, + boolean keepRawInput, boolean checkRegion, PhoneNumber phoneNumber) throws NumberParseException { if (numberToParse == null) { throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, @@ -3163,22 +3132,23 @@ public class PhoneNumberUtil { } StringBuilder nationalNumber = new StringBuilder(); - buildNationalNumberForParsing(numberToParse, nationalNumber); + String numberBeingParsed = numberToParse.toString(); + buildNationalNumberForParsing(numberBeingParsed, nationalNumber); - if (!isViablePhoneNumber(nationalNumber.toString())) { + if (!isViablePhoneNumber(nationalNumber)) { throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, "The string supplied did not seem to be a phone number."); } // Check the region supplied is valid, or that the extracted number starts with some sort of + // sign so the number's region can be determined. - if (checkRegion && !checkRegionForParsing(nationalNumber.toString(), defaultRegion)) { + if (checkRegion && !checkRegionForParsing(nationalNumber, defaultRegion)) { throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, "Missing or invalid default region."); } if (keepRawInput) { - phoneNumber.setRawInput(numberToParse); + phoneNumber.setRawInput(numberBeingParsed); } // Attempt to parse extension first, since it doesn't require region-specific data and we want // to have the non-normalised number here. @@ -3196,10 +3166,10 @@ public class PhoneNumberUtil { // TODO: This method should really just take in the string buffer that has already // been created, and just remove the prefix, rather than taking in a string and then // outputting a string buffer. - countryCode = maybeExtractCountryCode(nationalNumber.toString(), regionMetadata, + countryCode = maybeExtractCountryCode(nationalNumber, regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber); } catch (NumberParseException e) { - Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber.toString()); + Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber); if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE && matcher.lookingAt()) { // Strip the plus-char, and try again. @@ -3223,8 +3193,7 @@ public class PhoneNumberUtil { } else { // If no extracted country calling code, use the region supplied instead. The national number // is just the normalized version of the number we were given to parse. - normalize(nationalNumber); - normalizedNationalNumber.append(nationalNumber); + normalizedNationalNumber.append(normalize(nationalNumber)); if (defaultRegion != null) { countryCode = regionMetadata.getCountryCode(); phoneNumber.setCountryCode(countryCode); @@ -3243,8 +3212,7 @@ public class PhoneNumberUtil { // We require that the NSN remaining after stripping the national prefix and carrier code be // 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) - != ValidationResult.TOO_SHORT) { + if (testNumberLength(potentialNationalNumber, regionMetadata) != ValidationResult.TOO_SHORT) { normalizedNationalNumber = potentialNationalNumber; if (keepRawInput && carrierCode.length() > 0) { phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString()); @@ -3260,7 +3228,7 @@ public class PhoneNumberUtil { throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG, "The string supplied is too long to be a phone number."); } - setItalianLeadingZerosForPhoneNumber(normalizedNationalNumber.toString(), phoneNumber); + setItalianLeadingZerosForPhoneNumber(normalizedNationalNumber, phoneNumber); phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString())); } @@ -3413,7 +3381,7 @@ public class PhoneNumberUtil { * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. */ - public MatchType isNumberMatch(String firstNumber, String secondNumber) { + public MatchType isNumberMatch(CharSequence firstNumber, CharSequence secondNumber) { try { PhoneNumber firstNumberAsProto = parse(firstNumber, UNKNOWN_REGION); return isNumberMatch(firstNumberAsProto, secondNumber); @@ -3451,7 +3419,7 @@ public class PhoneNumberUtil { * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. */ - public MatchType isNumberMatch(PhoneNumber firstNumber, String secondNumber) { + public MatchType isNumberMatch(PhoneNumber firstNumber, CharSequence secondNumber) { // First see if the second number has an implicit country calling code, by attempting to parse // it. try { diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java index 2ed5ab5a1..3e7df59e9 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java @@ -428,14 +428,14 @@ public class ShortNumberInfo { * @param regionCode the region where the phone number is being dialed * @return whether the number exactly matches an emergency services number in the given region */ - public boolean isEmergencyNumber(String number, String regionCode) { + public boolean isEmergencyNumber(CharSequence number, String regionCode) { return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */); } - private boolean matchesEmergencyNumberHelper(String number, String regionCode, + private boolean matchesEmergencyNumberHelper(CharSequence number, String regionCode, boolean allowPrefixMatch) { - number = PhoneNumberUtil.extractPossibleNumber(number); - if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(number).lookingAt()) { + CharSequence possibleNumber = PhoneNumberUtil.extractPossibleNumber(number); + if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(possibleNumber).lookingAt()) { // Returns false if the number starts with a plus sign. We don't believe dialing the country // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can // add additional logic here to handle it. @@ -446,11 +446,10 @@ public class ShortNumberInfo { return false; } - String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number); - PhoneNumberDesc emergencyDesc = metadata.getEmergency(); + String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(possibleNumber); boolean allowPrefixMatchForRegion = allowPrefixMatch && !REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.contains(regionCode); - return matcherApi.matchNationalNumber(normalizedNumber, emergencyDesc, + return matcherApi.matchNationalNumber(normalizedNumber, metadata.getEmergency(), allowPrefixMatchForRegion); } diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java index 8cb798c43..ee09103bf 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java @@ -418,33 +418,29 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase { } public void testNormaliseRemovePunctuation() { - String inputNumber = "034-56&+#2\u00AD34"; + StringBuilder inputNumber = new StringBuilder("034-56&+#2\u00AD34"); String expectedOutput = "03456234"; assertEquals("Conversion did not correctly remove punctuation", - expectedOutput, - PhoneNumberUtil.normalize(inputNumber)); + expectedOutput, PhoneNumberUtil.normalize(inputNumber).toString()); } public void testNormaliseReplaceAlphaCharacters() { - String inputNumber = "034-I-am-HUNGRY"; + StringBuilder inputNumber = new StringBuilder("034-I-am-HUNGRY"); String expectedOutput = "034426486479"; assertEquals("Conversion did not correctly replace alpha characters", - expectedOutput, - PhoneNumberUtil.normalize(inputNumber)); + expectedOutput, PhoneNumberUtil.normalize(inputNumber).toString()); } public void testNormaliseOtherDigits() { - String inputNumber = "\uFF125\u0665"; + StringBuilder inputNumber = new StringBuilder("\uFF125\u0665"); String expectedOutput = "255"; assertEquals("Conversion did not correctly replace non-latin digits", - expectedOutput, - PhoneNumberUtil.normalize(inputNumber)); + expectedOutput, PhoneNumberUtil.normalize(inputNumber).toString()); // Eastern-Arabic digits. - inputNumber = "\u06F52\u06F0"; + inputNumber = new StringBuilder("\u06F52\u06F0"); expectedOutput = "520"; assertEquals("Conversion did not correctly replace non-latin digits", - expectedOutput, - PhoneNumberUtil.normalize(inputNumber)); + expectedOutput, PhoneNumberUtil.normalize(inputNumber).toString()); } public void testNormaliseStripAlphaCharacters() { diff --git a/pending_code_changes.txt b/pending_code_changes.txt index 4d9fad3a3..1e001990a 100644 --- a/pending_code_changes.txt +++ b/pending_code_changes.txt @@ -8,3 +8,13 @@ Code changes: - Documentation update for private variables VALID_PUNCTUATION and SINGLE_INTERNATIONAL_PREFIX, also renaming the latter from UNIQUE_INTERNATIONAL_PREFIX. + - [Java only] Changing public APIs that take in strings representing phone + numbers or parts of phone numbers to take in CharSequence instead. Updating + some of the internal methods to do the same. This affects ShortNumberInfo and + PhoneNumberUtil, namely the following methods: + - parse & parseAndKeepRawInput + - formatWithCarrierCode & formatWithPreferredCarrierCode + - isNumberMatch + - isPossibleNumber + - isAlphaNumber + - normalizeDigitsOnly & normalizeDiallableCharsOnly