// Helper method to get the region code for a given phone number, from a list of possible region // codes. If the list contains more than one region, the first region for which the number is // valid is returned. private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number, List <String> regionCodes) { if (regionCodes.size() == 0) { return(null); } else if (regionCodes.size() == 1) { return(regionCodes.get(0)); } String nationalNumber = phoneUtil.getNationalSignificantNumber(number); foreach (String regionCode in regionCodes) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata != null && phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getShortCode())) { // The number is valid for this region. return(regionCode); } } return(null); }
/** * Gets the expected cost category of a short number (however, nothing is implied about its * validity). If it is important that the number is valid, then its validity must first be checked * using {@link isValidShortNumber}. Note that emergency numbers are always considered toll-free. * Example usage: * <pre>{@code * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance(); * PhoneNumber number = phoneUtil.parse("110", "FR"); * if (shortInfo.isValidShortNumber(number)) { * ShortNumberInfo.ShortNumberCost cost = shortInfo.getExpectedCost(number); * // Do something with the cost information here. * }}</pre> * * @param number the short number for which we want to know the expected cost category * @return the expected cost category of the short number. Returns UNKNOWN_COST if the number does * not match a cost category. Note that an invalid number may match any cost category. */ public ShortNumberCost getExpectedCost(PhoneNumber number) { List <String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); // Note that regionCode may be null, in which case phoneMetadata will also be null. PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return(ShortNumberCost.UNKNOWN_COST); } String nationalNumber = phoneUtil.getNationalSignificantNumber(number); // The cost categories are tested in order of decreasing expense, since if for some reason the // patterns overlap the most expensive matching cost category should be returned. if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getPremiumRate())) { return(ShortNumberCost.PREMIUM_RATE); } if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getStandardRate())) { return(ShortNumberCost.STANDARD_RATE); } if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getTollFree())) { return(ShortNumberCost.TOLL_FREE); } if (isEmergencyNumber(nationalNumber, regionCode)) { // Emergency numbers are implicitly toll-free. return(ShortNumberCost.TOLL_FREE); } return(ShortNumberCost.UNKNOWN_COST); }
internal static boolean containsOnlyValidXChars( PhoneNumber number, String candidate, PhoneNumberUtil util) { // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the // national significant number or (2) an extension sign, in which case they always precede the // extension number. We assume a carrier code is more than 1 digit, so the first case has to // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x' // or 'X'. We ignore the character if it appears as the last character of the string. for (int index = 0; index < candidate.length() - 1; index++) { char charAtIndex = candidate.charAt(index); if (charAtIndex == 'x' || charAtIndex == 'X') { char charAtNextIndex = candidate.charAt(index + 1); if (charAtNextIndex == 'x' || charAtNextIndex == 'X') { // This is the carrier code case, in which the 'X's always precede the national // significant number. index++; if (util.isNumberMatch(number, candidate.substring(index)) != MatchType.NSN_MATCH) { return(false); } // This is the extension sign case, in which the 'x' or 'X' should always precede the // extension number. } else if (!PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(index)).equals( number.getExtension())) { return(false); } } } return(true); }
/** * Returns the description of the geographical area the {@code number} corresponds to. This method * distinguishes the case of an invalid prefix and a prefix for which the name is not available in * the current language. If the description is not available in the current language an empty * string is returned. If no description was found for the provided number, null is returned. * * @param number the phone number to look up * @return the description of the geographical area */ internal String lookup(PhoneNumber number) { int numOfEntries = areaCodeMapStorage.getNumOfEntries(); if (numOfEntries == 0) { return(null); } long phonePrefix = Long.parseLong(number.getCountryCode() + phoneUtil.getNationalSignificantNumber(number)); int currentIndex = numOfEntries - 1; SortedSet <Integer> currentSetOfLengths = areaCodeMapStorage.getPossibleLengths(); while (currentSetOfLengths.size() > 0) { Integer possibleLength = currentSetOfLengths.last(); String phonePrefixStr = String.valueOf(phonePrefix); if (phonePrefixStr.length() > possibleLength) { phonePrefix = Long.parseLong(phonePrefixStr.substring(0, possibleLength)); } currentIndex = binarySearch(0, currentIndex, phonePrefix); if (currentIndex < 0) { return(null); } int currentPrefix = areaCodeMapStorage.getPrefix(currentIndex); if (phonePrefix == currentPrefix) { return(areaCodeMapStorage.getDescription(currentIndex)); } currentSetOfLengths = currentSetOfLengths.headSet(possibleLength); } return(null); }
/** * Helper method to get the national-number part of a number, formatted without any national * prefix, and return it as a set of digit blocks that would be formatted together. */ private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number, NumberFormat formattingPattern) { if (formattingPattern == null) { // This will be in the format +CC-DG;ext=EXT where DG represents groups of digits. String rfc3966Format = util.format(number, PhoneNumberFormat.RFC3966); // We remove the extension part from the formatted string before splitting it into different // groups. int endIndex = rfc3966Format.indexOf(';'); if (endIndex < 0) { endIndex = rfc3966Format.length(); } // The country-code will have a '-' following it. int startIndex = rfc3966Format.indexOf('-') + 1; return(rfc3966Format.substring(startIndex, endIndex).split("-")); } else { // We format the NSN only, and split that according to the separator. String nationalSignificantNumber = util.getNationalSignificantNumber(number); return(util.formatNsnUsingPattern(nationalSignificantNumber, formattingPattern, PhoneNumberFormat.RFC3966).split("-")); } }
/** * @param exampleNumberRequestedType type we are requesting an example number for * @param possibleExpectedTypes acceptable types that this number should match, such as * FIXED_LINE and FIXED_LINE_OR_MOBILE for a fixed line example number. */ private void checkNumbersValidAndCorrectType(PhoneNumberType exampleNumberRequestedType, Set <PhoneNumberType> possibleExpectedTypes) { foreach (String regionCode in phoneNumberUtil.getSupportedRegions()) { PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumberForType(regionCode, exampleNumberRequestedType); if (exampleNumber != null) { if (!phoneNumberUtil.isValidNumber(exampleNumber)) { invalidCases.add(exampleNumber); LOGGER.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString()); } else { // We know the number is valid, now we check the type. PhoneNumberType exampleNumberType = phoneNumberUtil.getNumberType(exampleNumber); if (!possibleExpectedTypes.contains(exampleNumberType)) { wrongTypeCases.add(exampleNumber); LOGGER.log(Level.SEVERE, "Wrong type for " + exampleNumber.toString() + ": got " + exampleNumberType); LOGGER.log(Level.WARNING, "Expected types: "); foreach (PhoneNumberType type in possibleExpectedTypes) { LOGGER.log(Level.WARNING, type.ToString()); } } } } } }
/** * Returns an area-level text description in the given language for the given phone number. * * @param number the phone number for which we want to get a text description * @param lang two-letter lowercase ISO language codes as defined by ISO 639-1 * @param script four-letter titlecase (the first letter is uppercase and the rest of the letters * are lowercase) ISO script codes as defined in ISO 15924 * @param region two-letter uppercase ISO country codes as defined by ISO 3166-1 * @return an area-level text description in the given language for the given phone number, or an * empty string if such a description is not available */ private String getAreaDescriptionForNumber( PhoneNumber number, String lang, String script, String region) { int countryCallingCode = number.getCountryCode(); // As the NANPA data is split into multiple files covering 3-digit areas, use a phone number // prefix of 4 digits for NANPA instead, e.g. 1650. int phonePrefix = (countryCallingCode != 1) ? countryCallingCode : (1000 + (int)(number.getNationalNumber() / 10000000)); AreaCodeMap phonePrefixDescriptions = getPhonePrefixDescriptions(phonePrefix, lang, script, region); String description = (phonePrefixDescriptions != null) ? phonePrefixDescriptions.lookup(number) : null; // When a location is not available in the requested language, fall back to English. if ((description == null || description.length() == 0) && mayFallBackToEnglish(lang)) { AreaCodeMap defaultMap = getPhonePrefixDescriptions(phonePrefix, "en", "", ""); if (defaultMap == null) { return(""); } description = defaultMap.lookup(number); } return(description != null ? (string)description : ""); }
internal static boolean containsMoreThanOneSlashInNationalNumber(PhoneNumber number, String candidate) { int firstSlashInBodyIndex = candidate.indexOf('/'); if (firstSlashInBodyIndex < 0) { // No slashes, this is okay. return(false); } // Now look for a second one. int secondSlashInBodyIndex = candidate.indexOf('/', firstSlashInBodyIndex + 1); if (secondSlashInBodyIndex < 0) { // Only one slash, this is okay. return(false); } // If the first slash is after the country calling code, this is permitted. boolean candidateHasCountryCode = (number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN || number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); if (candidateHasCountryCode && PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(0, firstSlashInBodyIndex)) .equals(Integer.toString(number.getCountryCode()))) { // Any more slashes and this is illegal. return(candidate.substring(secondSlashInBodyIndex + 1).contains("/")); } return(true); }
internal static boolean checkNumberGroupingIsValid( PhoneNumber number, String 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 = PhoneNumberUtil.normalizeDigits(candidate, true /* keep non-digits */); String[] formattedNumberGroups = getNationalNumberGroups(util, number, null); if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { return(true); } // If this didn't pass, see if there are any alternate formats, and try them instead. PhoneMetadata alternateFormats = MetadataManager.getAlternateFormatsForCountry(number.getCountryCode()); if (alternateFormats != null) { foreach (NumberFormat alternateFormat in alternateFormats.numberFormats()) { formattedNumberGroups = getNationalNumberGroups(util, number, alternateFormat); if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { return(true); } } } return(false); }
[TestMethod] public void testEveryRegionHasAnExampleNumber() { foreach (String regionCode in phoneNumberUtil.getSupportedRegions()) { PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumber(regionCode); assertNotNull("None found for region " + regionCode, exampleNumber); } }
/** * Given a valid short number, determines whether it is carrier-specific (however, nothing is * implied about its validity). If it is important that the number is valid, then its validity * must first be checked using {@link isValidShortNumber}. * * @param number the valid short number to check * @return whether the short number is carrier-specific (assuming the input was a valid short * number). */ public boolean isCarrierSpecific(PhoneNumber number) { List <String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); String nationalNumber = phoneUtil.getNationalSignificantNumber(number); PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); return((phoneMetadata != null) && (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getCarrierSpecific()))); }
public void testEqualSimpleNumber() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
public void testEqualWithCountryCodeSourceSet() { PhoneNumber numberA = new PhoneNumber(); numberA.setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); PhoneNumber numberB = new PhoneNumber(); numberB.setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
/** * Returns a text description for the given phone number, in the language provided. The * description might consist of the name of the country where the phone number is from, or the * name of the geographical area the phone number is from if more detailed information is * available. * * <p>This method assumes the validity of the number passed in has already been checked, and that * the number is suitable for geocoding. We consider fixed-line and mobile numbers possible * candidates for geocoding. * * @param number a valid phone number for which we want to get a text description * @param languageCode the language code for which the description should be written * @return a text description for the given language code for the given phone number */ public String getDescriptionForValidNumber(PhoneNumber number, Locale languageCode) { String langStr = languageCode.getLanguage(); String scriptStr = ""; // No script is specified String regionStr = languageCode.getCountry(); String areaDescription = getAreaDescriptionForNumber(number, langStr, scriptStr, regionStr); return((areaDescription.length() > 0) ? areaDescription : getCountryNameForNumber(number, languageCode)); }
/** * Creates a new match. * * @param start the start index into the target text * @param rawString the matched substring of the target text * @param number the matched phone number */ internal PhoneNumberMatch(int start, String rawString, PhoneNumber number) { if (start < 0) { throw new IllegalArgumentException("Start index must be >= 0."); } if (rawString == null || number == null) { throw new NullPointerException(); } this._start = start; this._rawString = rawString; this._number = number; }
/** * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null. * * @param candidate the candidate match * @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) { try { // Check the candidate doesn't contain any formatting which would indicate that it really // isn't a phone number. if (!MATCHING_BRACKETS.matcher(candidate).matches()) { return(null); } // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def. if (leniency.compareTo(Leniency.VALID) >= 0) { // If the candidate is not at the start of the text, and does not start with phone-number // punctuation, check the previous character. if (offset > 0 && !LEAD_CLASS.matcher(candidate).lookingAt()) { char previousChar = text.charAt(offset - 1); // We return null if it is a latin letter or an invalid punctuation symbol. if (isInvalidPunctuationSymbol(previousChar) || isLatinLetter(previousChar)) { return(null); } } int lastCharIndex = offset + candidate.length(); if (lastCharIndex < text.length()) { char nextChar = text.charAt(lastCharIndex); if (isInvalidPunctuationSymbol(nextChar) || isLatinLetter(nextChar)) { return(null); } } } PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion); if (leniency.verify(number, candidate, phoneUtil)) { // We used parseAndKeepRawInput to create this number, but for now we don't return the extra // values parsed. TODO: stop clearing all values here and switch all users over // to using rawInput() rather than the rawString() of PhoneNumberMatch. number.clearCountryCodeSource(); number.clearRawInput(); number.clearPreferredDomesticCarrierCode(); return(new PhoneNumberMatch(offset, candidate, number)); } } catch (NumberParseException) { // ignore and continue } return(null); }
[TestMethod] public void testEqualWithPreferredDomesticCarrierCodeSetToDefault() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode(""); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode(""); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
[TestMethod] public void testEqualSimpleNumber() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
[TestMethod] public void testEqualWithCountryCodeSourceSet() { PhoneNumber numberA = new PhoneNumber(); numberA.setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); PhoneNumber numberB = new PhoneNumber(); numberB.setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
[TestMethod] public void testNonEqualWithItalianLeadingZeroSetToTrue() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(true); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); assertFalse(numberA.equals(numberB)); assertFalse(numberA.hashCode() == numberB.hashCode()); }
[TestMethod] public void testEqualWithItalianLeadingZeroSetToDefault() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(false); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); // These should still be equal, since the default value for this field is false. assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
/** * Check whether a short number is a possible number. This provides a more lenient check than * {@link #isValidShortNumber}. See {@link #isPossibleShortNumber(String, String)} for * details. * * @param number the short number to check * @return whether the number is a possible short number */ public boolean isPossibleShortNumber(PhoneNumber number) { List <String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String shortNumber = phoneUtil.getNationalSignificantNumber(number); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); if (regionCodes.size() > 1 && regionCode != null) { // If a matching region had been found for the phone number from among two or more regions, // then we have already implicitly verified its validity for that region. return(true); } return(isPossibleShortNumber(shortNumber, regionCode)); }
[TestMethod] public void testIsPossibleShortNumber() { PhoneNumber possibleNumber = new PhoneNumber(); possibleNumber.setCountryCode(33).setNationalNumber(123456L); assertTrue(shortInfo.isPossibleShortNumber(possibleNumber)); assertTrue(shortInfo.isPossibleShortNumber("123456", RegionCode.FR)); PhoneNumber impossibleNumber = new PhoneNumber(); impossibleNumber.setCountryCode(33).setNationalNumber(9L); assertFalse(shortInfo.isPossibleShortNumber(impossibleNumber)); assertFalse(shortInfo.isPossibleShortNumber("9", RegionCode.FR)); }
/** * As per {@link #getDescriptionForValidNumber(PhoneNumber, Locale)} but explicitly checks * the validity of the number passed in. * * @param number the phone number for which we want to get a text description * @param languageCode the language code for which the description should be written * @return a text description for the given language code for the given phone number, or empty * string if the number passed in is invalid */ public String getDescriptionForNumber(PhoneNumber number, Locale languageCode) { PhoneNumberType numberType = phoneUtil.getNumberType(number); if (numberType == PhoneNumberType.UNKNOWN) { return(""); } else if (!canBeGeocoded(numberType)) { return(getCountryNameForNumber(number, languageCode)); } return(getDescriptionForValidNumber(number, languageCode)); }
/** * Creates a new match. * * @param start the start index into the target text * @param rawString the matched substring of the target text * @param number the matched phone number */ internal PhoneNumberMatch(int start, String rawString, PhoneNumber number) { if (start < 0) { throw new IllegalArgumentException("Start index must be >= 0."); } if (rawString == null || number == null) { throw new NullPointerException(); } this._start = start; this._rawString = rawString; this._number = number; }
/** * Tests the value type semantics. Equality and hash code must be based on the covered range and * corresponding phone number. Range and number correctness are tested by * {@link PhoneNumberMatcherTest}. */ [TestMethod] public void testValueTypeSemantics() { PhoneNumber number = new PhoneNumber(); PhoneNumberMatch match1 = new PhoneNumberMatch(10, "1 800 234 45 67", number); PhoneNumberMatch match2 = new PhoneNumberMatch(10, "1 800 234 45 67", number); assertEquals(match1, match2); assertEquals(match1.hashCode(), match2.hashCode()); assertEquals(match1.start(), match2.start()); assertEquals(match1.end(), match2.end()); assertEquals(match1.number(), match2.number()); assertEquals(match1.rawString(), match2.rawString()); assertEquals("1 800 234 45 67", match1.rawString()); }
[TestMethod] public void testGlobalNetworkNumbers() { foreach (Integer callingCode in phoneNumberUtil.getSupportedGlobalNetworkCallingCodes()) { PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumberForNonGeoEntity(callingCode); assertNotNull("No example phone number for calling code " + callingCode, exampleNumber); if (!phoneNumberUtil.isValidNumber(exampleNumber)) { invalidCases.add(exampleNumber); LOGGER.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString()); } } assertEquals(0, invalidCases.size()); }
[TestMethod] public void testGetExpectedCost() { PhoneNumber premiumRateNumber = new PhoneNumber(); premiumRateNumber.setCountryCode(33).setNationalNumber( Integer.parseInt(shortInfo.getExampleShortNumberForCost( RegionCode.FR, ShortNumberInfo.ShortNumberCost.PREMIUM_RATE))); assertEquals(ShortNumberInfo.ShortNumberCost.PREMIUM_RATE, shortInfo.getExpectedCost(premiumRateNumber)); PhoneNumber standardRateNumber = new PhoneNumber(); standardRateNumber.setCountryCode(33).setNationalNumber( Integer.parseInt(shortInfo.getExampleShortNumberForCost( RegionCode.FR, ShortNumberInfo.ShortNumberCost.STANDARD_RATE))); assertEquals(ShortNumberInfo.ShortNumberCost.STANDARD_RATE, shortInfo.getExpectedCost(standardRateNumber)); PhoneNumber tollFreeNumber = new PhoneNumber(); tollFreeNumber.setCountryCode(33).setNationalNumber( Integer.parseInt(shortInfo.getExampleShortNumberForCost( RegionCode.FR, ShortNumberInfo.ShortNumberCost.TOLL_FREE))); assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE, shortInfo.getExpectedCost(tollFreeNumber)); PhoneNumber unknownCostNumber = new PhoneNumber(); unknownCostNumber.setCountryCode(33).setNationalNumber(12345L); assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST, shortInfo.getExpectedCost(unknownCostNumber)); // Test that an invalid number may nevertheless have a cost other than UNKNOWN_COST. PhoneNumber invalidNumber = new PhoneNumber(); invalidNumber.setCountryCode(33).setNationalNumber(116123L); assertFalse(shortInfo.isValidShortNumber(invalidNumber)); assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE, shortInfo.getExpectedCost(invalidNumber)); // Test a non-existent country code. unknownCostNumber.clear(); unknownCostNumber.setCountryCode(123).setNationalNumber(911L); assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST, shortInfo.getExpectedCost(unknownCostNumber)); }
/** * As per {@link #getDescriptionForValidNumber(PhoneNumber, Locale)} but also considers the * region of the user. If the phone number is from the same region as the user, only a lower-level * description will be returned, if one exists. Otherwise, the phone number's region will be * returned, with optionally some more detailed information. * * <p>For example, for a user from the region "US" (United States), we would show "Mountain View, * CA" for a particular number, omitting the United States from the description. For a user from * the United Kingdom (region "GB"), for the same number we may show "Mountain View, CA, United * States" or even just "United States". * * <p>This method assumes the validity of the number passed in has already been checked. * * @param number the phone number for which we want to get a text description * @param languageCode the language code for which the description should be written * @param userRegion the region code for a given user. This region will be omitted from the * description if the phone number comes from this region. It is a two-letter uppercase ISO * country code as defined by ISO 3166-1. * @return a text description for the given language code for the given phone number, or empty * string if the number passed in is invalid */ public String getDescriptionForValidNumber(PhoneNumber number, Locale languageCode, String userRegion) { // If the user region matches the number's region, then we just show the lower-level // description, if one exists - if no description exists, we will show the region(country) name // for the number. String regionCode = phoneUtil.getRegionCodeForNumber(number); if (userRegion.equals(regionCode)) { return(getDescriptionForValidNumber(number, languageCode)); } // Otherwise, we just show the region(country) name for now. return(getRegionDisplayName(regionCode, languageCode)); // TODO: Concatenate the lower-level and country-name information in an appropriate // way for each language. }
[TestMethod] public void testNonEqualWithDifferingRawInput() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); PhoneNumber numberB = new PhoneNumber(); // Although these numbers would pass an isNumberMatch test, they are not considered "equal" as // objects, since their raw input is different. numberB.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1-650-253-00-00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); assertFalse(numberA.equals(numberB)); assertFalse(numberA.hashCode() == numberB.hashCode()); }
internal static boolean isNationalPrefixPresentIfRequired(PhoneNumber number, PhoneNumberUtil util) { // First, check how we deduced the country code. If it was written in international format, then // the national prefix is not required. if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) { return(true); } String phoneNumberRegion = util.getRegionCodeForCountryCode(number.getCountryCode()); PhoneMetadata metadata = util.getMetadataForRegion(phoneNumberRegion); if (metadata == null) { return(true); } // Check if a national prefix should be present when formatting this number. String nationalNumber = util.getNationalSignificantNumber(number); NumberFormat formatRule = util.chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber); // To do this, we check that a national prefix formatting rule was present and that it wasn't // just the first-group symbol ($1) with punctuation. if ((formatRule != null) && formatRule.getNationalPrefixFormattingRule().length() > 0) { if (formatRule.isNationalPrefixOptionalWhenFormatting()) { // The national-prefix is optional in these cases, so we don't need to check if it was // present. return(true); } if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly( formatRule.getNationalPrefixFormattingRule())) { // National Prefix not needed for this number. return(true); } // Normalize the remainder. String rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput()); StringBuilder rawInput = new StringBuilder(rawInputCopy); // Check if we found a national prefix and/or carrier code at the start of the raw input, and // return the result. return(util.maybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null)); } return(true); }
[TestMethod] public void testShortNumbersValidAndCorrectCost() { List <String> invalidStringCases = new ArrayList <String>(); foreach (String regionCode in shortNumberInfo.getSupportedRegions()) { if (regionCode == RegionCode.PG) { // The only short number for Papua New Guinea is 000, which fails the test, since the // national prefix is 0. This needs to be fixed. continue; } String exampleShortNumber = shortNumberInfo.getExampleShortNumber(regionCode); if (!shortNumberInfo.isValidShortNumber(exampleShortNumber, regionCode)) { String invalidStringCase = "region_code: " + regionCode + ", national_number: " + exampleShortNumber; invalidStringCases.add(invalidStringCase); LOGGER.log(Level.SEVERE, "Failed validation for string " + invalidStringCase); } PhoneNumber phoneNumber = phoneNumberUtil.parse(exampleShortNumber, regionCode); if (!shortNumberInfo.isValidShortNumber(phoneNumber)) { invalidCases.add(phoneNumber); LOGGER.log(Level.SEVERE, "Failed validation for " + phoneNumber.toString()); } foreach (ShortNumberInfo.ShortNumberCost cost in System.Enum.GetValues(typeof(ShortNumberInfo.ShortNumberCost))) { exampleShortNumber = shortNumberInfo.getExampleShortNumberForCost(regionCode, cost); if (!exampleShortNumber.equals("")) { phoneNumber = phoneNumberUtil.parse(exampleShortNumber, regionCode); if (cost != shortNumberInfo.getExpectedCost(phoneNumber)) { wrongTypeCases.add(phoneNumber); LOGGER.log(Level.SEVERE, "Wrong cost for " + phoneNumber.toString()); } } } } assertEquals(0, invalidStringCases.size()); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); }
internal static boolean allNumberGroupsRemainGrouped(PhoneNumberUtil util, PhoneNumber number, StringBuilder normalizedCandidate, String[] formattedNumberGroups) { int fromIndex = 0; // Check each group of consecutive digits are not broken into separate groupings in the // {@code normalizedCandidate} string. for (int i = 0; i < formattedNumberGroups.length(); i++) { // Fails if the substring of {@code normalizedCandidate} starting from {@code fromIndex} // doesn't contain the consecutive digits in formattedNumberGroups[i]. fromIndex = normalizedCandidate.indexOf(formattedNumberGroups[i], fromIndex); if (fromIndex < 0) { return(false); } // Moves {@code fromIndex} forward. fromIndex += formattedNumberGroups[i].length(); if (i == 0 && fromIndex < normalizedCandidate.length()) { // We are at the position right after the NDC. We get the region used for formatting // information based on the country code in the phone number, rather than the number itself, // as we do not need to distinguish between different countries with the same country // calling code and this is faster. String region = util.getRegionCodeForCountryCode(number.getCountryCode()); if (util.getNddPrefixForRegion(region, true) != null && Character.isDigit(normalizedCandidate.charAt(fromIndex))) { // This means there is no formatting symbol after the NDC. In this case, we only // accept the number if there is no formatting symbol at all in the number, except // for extensions. This is only important for countries with national prefixes. String nationalSignificantNumber = util.getNationalSignificantNumber(number); return(normalizedCandidate.substring(fromIndex - formattedNumberGroups[i].length()) .startsWith(nationalSignificantNumber)); } } } // The check here makes sure that we haven't mistakenly already used the extension to // match the last group of the subscriber number. Note the extension cannot have // formatting in-between digits. return(normalizedCandidate.substring(fromIndex).contains(number.getExtension())); }
public void testParseNumbersMexico() { // Test parsing fixed-line numbers of Mexico. PhoneNumber mxNumber = new PhoneNumber(); mxNumber.setCountryCode(52).setNationalNumber(4499780001L); assertEquals(mxNumber, phoneUtil.parse("+52 (449)978-0001", RegionCode.MX)); assertEquals(mxNumber, phoneUtil.parse("01 (449)978-0001", RegionCode.MX)); assertEquals(mxNumber, phoneUtil.parse("(449)978-0001", RegionCode.MX)); // Test parsing mobile numbers of Mexico. mxNumber.clear(); mxNumber.setCountryCode(52).setNationalNumber(13312345678L); assertEquals(mxNumber, phoneUtil.parse("+52 1 33 1234-5678", RegionCode.MX)); assertEquals(mxNumber, phoneUtil.parse("044 (33) 1234-5678", RegionCode.MX)); assertEquals(mxNumber, phoneUtil.parse("045 33 1234-5678", RegionCode.MX)); }
public void testFormatOutOfCountryCallingNumber() { assertEquals("00 1 900 253 0000", phoneUtil.formatOutOfCountryCallingNumber(US_PREMIUM, RegionCode.DE)); assertEquals("1 650 253 0000", phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.BS)); assertEquals("00 1 650 253 0000", phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.PL)); assertEquals("011 44 7912 345 678", phoneUtil.formatOutOfCountryCallingNumber(GB_MOBILE, RegionCode.US)); assertEquals("00 49 1234", phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, RegionCode.GB)); // Note this number is correctly formatted without national prefix. Most of the numbers that // are treated as invalid numbers by the library are short numbers, and they are usually not // dialed with national prefix. assertEquals("1234", phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, RegionCode.DE)); assertEquals("011 39 02 3661 8300", phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.US)); assertEquals("02 3661 8300", phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.IT)); assertEquals("+39 02 3661 8300", phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.SG)); assertEquals("6521 8000", phoneUtil.formatOutOfCountryCallingNumber(SG_NUMBER, RegionCode.SG)); assertEquals("011 54 9 11 8765 4321", phoneUtil.formatOutOfCountryCallingNumber(AR_MOBILE, RegionCode.US)); assertEquals("011 800 1234 5678", phoneUtil.formatOutOfCountryCallingNumber(INTERNATIONAL_TOLL_FREE, RegionCode.US)); PhoneNumber arNumberWithExtn = new PhoneNumber().mergeFrom(AR_MOBILE).setExtension("1234"); assertEquals("011 54 9 11 8765 4321 ext. 1234", phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.US)); assertEquals("0011 54 9 11 8765 4321 ext. 1234", phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.AU)); assertEquals("011 15 8765-4321 ext. 1234", phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.AR)); }
public void testParseNumbersWithPlusWithNoRegion() { // RegionCode.ZZ is allowed only if the number starts with a '+' - then the country calling code // can be calculated. assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", RegionCode.ZZ)); // Test with full-width plus. assertEquals(NZ_NUMBER, phoneUtil.parse("\uFF0B64 3 331 6005", RegionCode.ZZ)); // Test with normal plus but leading characters that need to be stripped. assertEquals(NZ_NUMBER, phoneUtil.parse("Tel: +64 3 331 6005", RegionCode.ZZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", null)); assertEquals(INTERNATIONAL_TOLL_FREE, phoneUtil.parse("+800 1234 5678", null)); assertEquals(UNIVERSAL_PREMIUM_RATE, phoneUtil.parse("+979 123 456 789", null)); // Test parsing RFC3966 format with a phone context. assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64", RegionCode.ZZ)); assertEquals(NZ_NUMBER, phoneUtil.parse(" tel:03-331-6005;phone-context=+64", RegionCode.ZZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;isub=12345;phone-context=+64", RegionCode.ZZ)); // It is important that we set the carrier code to an empty string, since we used // ParseAndKeepRawInput and no carrier code was found. PhoneNumber nzNumberWithRawInput = new PhoneNumber().mergeFrom(NZ_NUMBER). setRawInput("+64 3 331 6005"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN). setPreferredDomesticCarrierCode(""); assertEquals(nzNumberWithRawInput, phoneUtil.parseAndKeepRawInput("+64 3 331 6005", RegionCode.ZZ)); // Null is also allowed for the region code in these cases. assertEquals(nzNumberWithRawInput, phoneUtil.parseAndKeepRawInput("+64 3 331 6005", null)); }
public void testFormatOutOfCountryKeepingAlphaChars() { PhoneNumber alphaNumericNumber = new PhoneNumber(); alphaNumericNumber.setCountryCode(1).setNationalNumber(8007493524L) .setRawInput("1800 six-flag"); assertEquals("0011 1 800 SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); alphaNumericNumber.setRawInput("1-800-SIX-flag"); assertEquals("0011 1 800-SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); alphaNumericNumber.setRawInput("Call us from UK: 00 1 800 SIX-flag"); assertEquals("0011 1 800 SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); alphaNumericNumber.setRawInput("800 SIX-flag"); assertEquals("0011 1 800 SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); // Formatting from within the NANPA region. assertEquals("1 800 SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.US)); assertEquals("1 800 SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.BS)); // Testing that if the raw input doesn't exist, it is formatted using // formatOutOfCountryCallingNumber. alphaNumericNumber.clearRawInput(); assertEquals("00 1 800 749 3524", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE)); // Testing AU alpha number formatted from Australia. alphaNumericNumber.setCountryCode(61).setNationalNumber(827493524L) .setRawInput("+61 82749-FLAG"); // This number should have the national prefix fixed. assertEquals("082749-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); alphaNumericNumber.setRawInput("082749-FLAG"); assertEquals("082749-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); alphaNumericNumber.setNationalNumber(18007493524L).setRawInput("1-800-SIX-flag"); // This number should not have the national prefix prefixed, in accordance with the override for // this specific formatting rule. assertEquals("1-800-SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU)); // The metadata should not be permanently changed, since we copied it before modifying patterns. // Here we check this. alphaNumericNumber.setNationalNumber(1800749352L); assertEquals("1800 749 352", phoneUtil.formatOutOfCountryCallingNumber(alphaNumericNumber, RegionCode.AU)); // Testing a region with multiple international prefixes. assertEquals("+61 1-800-SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.SG)); // Testing the case of calling from a non-supported region. assertEquals("+61 1-800-SIX-FLAG", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ)); // Testing the case with an invalid country calling code. alphaNumericNumber.setCountryCode(0).setNationalNumber(18007493524L) .setRawInput("1-800-SIX-flag"); // Uses the raw input only. assertEquals("1-800-SIX-flag", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE)); // Testing the case of an invalid alpha number. alphaNumericNumber.setCountryCode(1).setNationalNumber(80749L).setRawInput("180-SIX"); // No country-code stripping can be done. assertEquals("00 1 180-SIX", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE)); // Testing the case of calling from a non-supported region. alphaNumericNumber.setCountryCode(1).setNationalNumber(80749L).setRawInput("180-SIX"); // No country-code stripping can be done since the number is invalid. assertEquals("+1 180-SIX", phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ)); }
/** * Returns the description of the geographical area the {@code number} corresponds to. This method * distinguishes the case of an invalid prefix and a prefix for which the name is not available in * the current language. If the description is not available in the current language an empty * string is returned. If no description was found for the provided number, null is returned. * * @param number the phone number to look up * @return the description of the geographical area */ internal String lookup(PhoneNumber number) { int numOfEntries = areaCodeMapStorage.getNumOfEntries(); if (numOfEntries == 0) { return null; } long phonePrefix = Long.parseLong(number.getCountryCode() + phoneUtil.getNationalSignificantNumber(number)); int currentIndex = numOfEntries - 1; SortedSet<Integer> currentSetOfLengths = areaCodeMapStorage.getPossibleLengths(); while (currentSetOfLengths.size() > 0) { Integer possibleLength = currentSetOfLengths.last(); String phonePrefixStr = String.valueOf(phonePrefix); if (phonePrefixStr.length() > possibleLength) { phonePrefix = Long.parseLong(phonePrefixStr.substring(0, possibleLength)); } currentIndex = binarySearch(0, currentIndex, phonePrefix); if (currentIndex < 0) { return null; } int currentPrefix = areaCodeMapStorage.getPrefix(currentIndex); if (phonePrefix == currentPrefix) { return areaCodeMapStorage.getDescription(currentIndex); } currentSetOfLengths = currentSetOfLengths.headSet(possibleLength); } return null; }
public void testTruncateTooLongNumber() { // GB number 080 1234 5678, but entered with 4 extra digits at the end. PhoneNumber tooLongNumber = new PhoneNumber(); tooLongNumber.setCountryCode(44).setNationalNumber(80123456780123L); PhoneNumber validNumber = new PhoneNumber(); validNumber.setCountryCode(44).setNationalNumber(8012345678L); assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber)); assertEquals(validNumber, tooLongNumber); // IT number 022 3456 7890, but entered with 3 extra digits at the end. tooLongNumber.clear(); tooLongNumber.setCountryCode(39).setNationalNumber(2234567890123L).setItalianLeadingZero(true); validNumber.clear(); validNumber.setCountryCode(39).setNationalNumber(2234567890L).setItalianLeadingZero(true); assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber)); assertEquals(validNumber, tooLongNumber); // US number 650-253-0000, but entered with one additional digit at the end. tooLongNumber.clear(); tooLongNumber.mergeFrom(US_LONG_NUMBER); assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber)); assertEquals(US_NUMBER, tooLongNumber); tooLongNumber.clear(); tooLongNumber.mergeFrom(INTERNATIONAL_TOLL_FREE_TOO_LONG); assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber)); assertEquals(INTERNATIONAL_TOLL_FREE, tooLongNumber); // Tests what happens when a valid number is passed in. PhoneNumber validNumberCopy = new PhoneNumber().mergeFrom(validNumber); assertTrue(phoneUtil.truncateTooLongNumber(validNumber)); // Tests the number is not modified. assertEquals(validNumberCopy, validNumber); // Tests what happens when a number with invalid prefix is passed in. PhoneNumber numberWithInvalidPrefix = new PhoneNumber(); // The test metadata says US numbers cannot have prefix 240. numberWithInvalidPrefix.setCountryCode(1).setNationalNumber(2401234567L); PhoneNumber invalidNumberCopy = new PhoneNumber().mergeFrom(numberWithInvalidPrefix); assertFalse(phoneUtil.truncateTooLongNumber(numberWithInvalidPrefix)); // Tests the number is not modified. assertEquals(invalidNumberCopy, numberWithInvalidPrefix); // Tests what happens when a too short number is passed in. PhoneNumber tooShortNumber = new PhoneNumber().setCountryCode(1).setNationalNumber(1234L); PhoneNumber tooShortNumberCopy = new PhoneNumber().mergeFrom(tooShortNumber); assertFalse(phoneUtil.truncateTooLongNumber(tooShortNumber)); // Tests the number is not modified. assertEquals(tooShortNumberCopy, tooShortNumber); }
public void testParseNationalNumberArgentina() { // Test parsing mobile numbers of Argentina. PhoneNumber arNumber = new PhoneNumber(); arNumber.setCountryCode(54).setNationalNumber(93435551212L); assertEquals(arNumber, phoneUtil.parse("+54 9 343 555 1212", RegionCode.AR)); assertEquals(arNumber, phoneUtil.parse("0343 15 555 1212", RegionCode.AR)); arNumber.clear(); arNumber.setCountryCode(54).setNationalNumber(93715654320L); assertEquals(arNumber, phoneUtil.parse("+54 9 3715 65 4320", RegionCode.AR)); assertEquals(arNumber, phoneUtil.parse("03715 15 65 4320", RegionCode.AR)); assertEquals(AR_MOBILE, phoneUtil.parse("911 876 54321", RegionCode.AR)); // Test parsing fixed-line numbers of Argentina. assertEquals(AR_NUMBER, phoneUtil.parse("+54 11 8765 4321", RegionCode.AR)); assertEquals(AR_NUMBER, phoneUtil.parse("011 8765 4321", RegionCode.AR)); arNumber.clear(); arNumber.setCountryCode(54).setNationalNumber(3715654321L); assertEquals(arNumber, phoneUtil.parse("+54 3715 65 4321", RegionCode.AR)); assertEquals(arNumber, phoneUtil.parse("03715 65 4321", RegionCode.AR)); arNumber.clear(); arNumber.setCountryCode(54).setNationalNumber(2312340000L); assertEquals(arNumber, phoneUtil.parse("+54 23 1234 0000", RegionCode.AR)); assertEquals(arNumber, phoneUtil.parse("023 1234 0000", RegionCode.AR)); }
public void testNonEqualWithDifferingRawInput() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1 650 253 00 00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); PhoneNumber numberB = new PhoneNumber(); // Although these numbers would pass an isNumberMatch test, they are not considered "equal" as // objects, since their raw input is different. numberB.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1-650-253-00-00"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); assertFalse(numberA.equals(numberB)); assertFalse(numberA.hashCode() == numberB.hashCode()); }
public void testMaybeExtractCountryCode() { PhoneNumber number = new PhoneNumber(); PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US); // Note that for the US, the IDD is 011. try { String phoneNumber = "011112-3456789"; String strippedNumber = "123456789"; int countryCallingCode = 1; StringBuilder numberToFill = new StringBuilder(); assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.", countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_NUMBER_WITH_IDD, number.getCountryCodeSource()); // Should strip and normalize national significant number. assertEquals("Did not strip off the country calling code correctly.", strippedNumber, numberToFill.toString()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "+6423456789"; int countryCallingCode = 64; StringBuilder numberToFill = new StringBuilder(); assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.", countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN, number.getCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "+80012345678"; int countryCallingCode = 800; StringBuilder numberToFill = new StringBuilder(); assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.", countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN, number.getCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "2345-6789"; StringBuilder numberToFill = new StringBuilder(); assertEquals( "Should not have extracted a country calling code - no international prefix present.", 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_DEFAULT_COUNTRY, number.getCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "0119991123456789"; StringBuilder numberToFill = new StringBuilder(); phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number); fail("Should have thrown an exception, no valid country calling code present."); } catch (NumberParseException e) { // Expected. assertEquals("Wrong error type stored in exception.", NumberParseException.ErrorType.INVALID_COUNTRY_CODE, e.getErrorType()); } number.clear(); try { String phoneNumber = "(1 610) 619 4466"; int countryCallingCode = 1; StringBuilder numberToFill = new StringBuilder(); assertEquals("Should have extracted the country calling code of the region passed in", countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN, number.getCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "(1 610) 619 4466"; int countryCallingCode = 1; StringBuilder numberToFill = new StringBuilder(); assertEquals("Should have extracted the country calling code of the region passed in", countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false, number)); assertFalse("Should not contain CountryCodeSource.", number.hasCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "(1 610) 619 446"; StringBuilder numberToFill = new StringBuilder(); assertEquals("Should not have extracted a country calling code - invalid number after " + "extraction of uncertain country calling code.", 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false, number)); assertFalse("Should not contain CountryCodeSource.", number.hasCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } number.clear(); try { String phoneNumber = "(1 610) 619"; StringBuilder numberToFill = new StringBuilder(); assertEquals("Should not have extracted a country calling code - too short number both " + "before and after extraction of uncertain country calling code.", 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals("Did not figure out CountryCodeSource correctly", CountryCodeSource.FROM_DEFAULT_COUNTRY, number.getCountryCodeSource()); } catch (NumberParseException e) { fail("Should not have thrown an exception: " + e.toString()); } }
public void testParseNationalNumber() { // National prefix attached. assertEquals(NZ_NUMBER, phoneUtil.parse("033316005", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("33316005", RegionCode.NZ)); // National prefix attached and some formatting present. assertEquals(NZ_NUMBER, phoneUtil.parse("03-331 6005", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("03 331 6005", RegionCode.NZ)); // Test parsing RFC3966 format with a phone context. assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("tel:331-6005;phone-context=+64-3", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("tel:331-6005;phone-context=+64-3", RegionCode.US)); // Test parsing RFC3966 format with optional user-defined parameters. The parameters will appear // after the context if present. assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64;a=%A1", RegionCode.NZ)); // Test parsing RFC3966 with an ISDN subaddress. assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;isub=12345;phone-context=+64", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("tel:+64-3-331-6005;isub=12345", RegionCode.NZ)); // Testing international prefixes. // Should strip country calling code. assertEquals(NZ_NUMBER, phoneUtil.parse("0064 3 331 6005", RegionCode.NZ)); // Try again, but this time we have an international number with Region Code US. It should // recognise the country calling code and parse accordingly. assertEquals(NZ_NUMBER, phoneUtil.parse("01164 3 331 6005", RegionCode.US)); assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", RegionCode.US)); // We should ignore the leading plus here, since it is not followed by a valid country code but // instead is followed by the IDD for the US. assertEquals(NZ_NUMBER, phoneUtil.parse("+01164 3 331 6005", RegionCode.US)); assertEquals(NZ_NUMBER, phoneUtil.parse("+0064 3 331 6005", RegionCode.NZ)); assertEquals(NZ_NUMBER, phoneUtil.parse("+ 00 64 3 331 6005", RegionCode.NZ)); assertEquals(US_LOCAL_NUMBER, phoneUtil.parse("tel:253-0000;phone-context=www.google.com", RegionCode.US)); assertEquals(US_LOCAL_NUMBER, phoneUtil.parse("tel:253-0000;isub=12345;phone-context=www.google.com", RegionCode.US)); // This is invalid because no "+" sign is present as part of phone-context. The phone context // is simply ignored in this case just as if it contains a domain. assertEquals(US_LOCAL_NUMBER, phoneUtil.parse("tel:2530000;isub=12345;phone-context=1-650", RegionCode.US)); assertEquals(US_LOCAL_NUMBER, phoneUtil.parse("tel:2530000;isub=12345;phone-context=1234.com", RegionCode.US)); PhoneNumber nzNumber = new PhoneNumber(); nzNumber.setCountryCode(64).setNationalNumber(64123456L); assertEquals(nzNumber, phoneUtil.parse("64(0)64123456", RegionCode.NZ)); // Check that using a "/" is fine in a phone number. assertEquals(DE_NUMBER, phoneUtil.parse("301/23456", RegionCode.DE)); PhoneNumber usNumber = new PhoneNumber(); // Check it doesn't use the '1' as a country calling code when parsing if the phone number was // already possible. usNumber.setCountryCode(1).setNationalNumber(1234567890L); assertEquals(usNumber, phoneUtil.parse("123-456-7890", RegionCode.US)); // Test star numbers. Although this is not strictly valid, we would like to make sure we can // parse the output we produce when formatting the number. assertEquals(JP_STAR_NUMBER, phoneUtil.parse("+81 *2345", RegionCode.JP)); PhoneNumber shortNumber = new PhoneNumber(); shortNumber.setCountryCode(64).setNationalNumber(12L); assertEquals(shortNumber, phoneUtil.parse("12", RegionCode.NZ)); }
public void testEqualWithPreferredDomesticCarrierCodeSetToDefault() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode(""); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode(""); assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
public void testEqualWithItalianLeadingZeroSetToDefault() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(false); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); // These should still be equal, since the default value for this field is false. assertEquals(numberA, numberB); assertEquals(numberA.hashCode(), numberB.hashCode()); }
public void testParseWithXInNumber() { // Test that having an 'x' in the phone number at the start is ok and that it just gets removed. assertEquals(AR_NUMBER, phoneUtil.parse("01187654321", RegionCode.AR)); assertEquals(AR_NUMBER, phoneUtil.parse("(0) 1187654321", RegionCode.AR)); assertEquals(AR_NUMBER, phoneUtil.parse("0 1187654321", RegionCode.AR)); assertEquals(AR_NUMBER, phoneUtil.parse("(0xx) 1187654321", RegionCode.AR)); PhoneNumber arFromUs = new PhoneNumber(); arFromUs.setCountryCode(54).setNationalNumber(81429712L); // This test is intentionally constructed such that the number of digit after xx is larger than // 7, so that the number won't be mistakenly treated as an extension, as we allow extensions up // to 7 digits. This assumption is okay for now as all the countries where a carrier selection // code is written in the form of xx have a national significant number of length larger than 7. assertEquals(arFromUs, phoneUtil.parse("011xx5481429712", RegionCode.US)); }
public void testFormatNumberWithExtension() { PhoneNumber nzNumber = new PhoneNumber().mergeFrom(NZ_NUMBER).setExtension("1234"); // Uses default extension prefix: assertEquals("03-331 6005 ext. 1234", phoneUtil.format(nzNumber, PhoneNumberFormat.NATIONAL)); // Uses RFC 3966 syntax. assertEquals("tel:+64-3-331-6005;ext=1234", phoneUtil.format(nzNumber, PhoneNumberFormat.RFC3966)); // Extension prefix overridden in the territory information for the US: PhoneNumber usNumberWithExtension = new PhoneNumber().mergeFrom(US_NUMBER).setExtension("4567"); assertEquals("650 253 0000 extn. 4567", phoneUtil.format(usNumberWithExtension, PhoneNumberFormat.NATIONAL)); }
public void testFormatDENumber() { PhoneNumber deNumber = new PhoneNumber(); deNumber.setCountryCode(49).setNationalNumber(301234L); assertEquals("030/1234", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+49 30/1234", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL)); assertEquals("tel:+49-30-1234", phoneUtil.format(deNumber, PhoneNumberFormat.RFC3966)); deNumber.clear(); deNumber.setCountryCode(49).setNationalNumber(291123L); assertEquals("0291 123", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+49 291 123", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL)); deNumber.clear(); deNumber.setCountryCode(49).setNationalNumber(29112345678L); assertEquals("0291 12345678", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+49 291 12345678", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL)); deNumber.clear(); deNumber.setCountryCode(49).setNationalNumber(912312345L); assertEquals("09123 12345", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+49 9123 12345", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL)); deNumber.clear(); deNumber.setCountryCode(49).setNationalNumber(80212345L); assertEquals("08021 2345", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+49 8021 2345", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL)); // Note this number is correctly formatted without national prefix. Most of the numbers that // are treated as invalid numbers by the library are short numbers, and they are usually not // dialed with national prefix. assertEquals("1234", phoneUtil.format(DE_SHORT_NUMBER, PhoneNumberFormat.NATIONAL)); assertEquals("+49 1234", phoneUtil.format(DE_SHORT_NUMBER, PhoneNumberFormat.INTERNATIONAL)); deNumber.clear(); deNumber.setCountryCode(49).setNationalNumber(41341234); assertEquals("04134 1234", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL)); }
public void testFormatNumberForMobileDialing() { // Numbers are normally dialed in national format in-country, and international format from // outside the country. assertEquals("030123456", phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.DE, false)); assertEquals("+4930123456", phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.CH, false)); PhoneNumber deNumberWithExtn = new PhoneNumber().mergeFrom(DE_NUMBER).setExtension("1234"); assertEquals("030123456", phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.DE, false)); assertEquals("+4930123456", phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.CH, false)); // US toll free numbers are marked as noInternationalDialling in the test metadata for testing // purposes. For such numbers, we expect nothing to be returned when the region code is not the // same one. assertEquals("800 253 0000", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.US, true /* keep formatting */)); assertEquals("", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.CN, true)); assertEquals("+1 650 253 0000", phoneUtil.formatNumberForMobileDialing(US_NUMBER, RegionCode.US, true)); PhoneNumber usNumberWithExtn = new PhoneNumber().mergeFrom(US_NUMBER).setExtension("1234"); assertEquals("+1 650 253 0000", phoneUtil.formatNumberForMobileDialing(usNumberWithExtn, RegionCode.US, true)); assertEquals("8002530000", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.US, false /* remove formatting */)); assertEquals("", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.CN, false)); assertEquals("+16502530000", phoneUtil.formatNumberForMobileDialing(US_NUMBER, RegionCode.US, false)); assertEquals("+16502530000", phoneUtil.formatNumberForMobileDialing(usNumberWithExtn, RegionCode.US, false)); // An invalid US number, which is one digit too long. assertEquals("+165025300001", phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER, RegionCode.US, false)); assertEquals("+1 65025300001", phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER, RegionCode.US, true)); // Star numbers. In real life they appear in Israel, but we have them in JP in our test // metadata. assertEquals("*2345", phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER, RegionCode.JP, false)); assertEquals("*2345", phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER, RegionCode.JP, true)); assertEquals("+80012345678", phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.JP, false)); assertEquals("+800 1234 5678", phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.JP, true)); // UAE numbers beginning with 600 (classified as UAN) need to be dialled without +971 locally. assertEquals("+971600123456", phoneUtil.formatNumberForMobileDialing(AE_UAN, RegionCode.JP, false)); assertEquals("600123456", phoneUtil.formatNumberForMobileDialing(AE_UAN, RegionCode.AE, false)); assertEquals("+523312345678", phoneUtil.formatNumberForMobileDialing(MX_NUMBER1, RegionCode.MX, false)); assertEquals("+523312345678", phoneUtil.formatNumberForMobileDialing(MX_NUMBER1, RegionCode.US, false)); // Non-geographical numbers should always be dialed in international format. assertEquals("+80012345678", phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.US, false)); assertEquals("+80012345678", phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.UN001, false)); }
public void testParseNumberWithAlphaCharacters() { // Test case with alpha characters. PhoneNumber tollfreeNumber = new PhoneNumber(); tollfreeNumber.setCountryCode(64).setNationalNumber(800332005L); assertEquals(tollfreeNumber, phoneUtil.parse("0800 DDA 005", RegionCode.NZ)); PhoneNumber premiumNumber = new PhoneNumber(); premiumNumber.setCountryCode(64).setNationalNumber(9003326005L); assertEquals(premiumNumber, phoneUtil.parse("0900 DDA 6005", RegionCode.NZ)); // Not enough alpha characters for them to be considered intentional, so they are stripped. assertEquals(premiumNumber, phoneUtil.parse("0900 332 6005a", RegionCode.NZ)); assertEquals(premiumNumber, phoneUtil.parse("0900 332 600a5", RegionCode.NZ)); assertEquals(premiumNumber, phoneUtil.parse("0900 332 600A5", RegionCode.NZ)); assertEquals(premiumNumber, phoneUtil.parse("0900 a332 600A5", RegionCode.NZ)); }
/** * Gets the expected cost category of a short number (however, nothing is implied about its * validity). If it is important that the number is valid, then its validity must first be checked * using {@link isValidShortNumber}. Note that emergency numbers are always considered toll-free. * Example usage: * <pre>{@code * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance(); * PhoneNumber number = phoneUtil.parse("110", "FR"); * if (shortInfo.isValidShortNumber(number)) { * ShortNumberInfo.ShortNumberCost cost = shortInfo.getExpectedCost(number); * // Do something with the cost information here. * }}</pre> * * @param number the short number for which we want to know the expected cost category * @return the expected cost category of the short number. Returns UNKNOWN_COST if the number does * not match a cost category. Note that an invalid number may match any cost category. */ public ShortNumberCost getExpectedCost(PhoneNumber number) { List<String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); // Note that regionCode may be null, in which case phoneMetadata will also be null. PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return ShortNumberCost.UNKNOWN_COST; } String nationalNumber = phoneUtil.getNationalSignificantNumber(number); // The cost categories are tested in order of decreasing expense, since if for some reason the // patterns overlap the most expensive matching cost category should be returned. if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getPremiumRate())) { return ShortNumberCost.PREMIUM_RATE; } if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getStandardRate())) { return ShortNumberCost.STANDARD_RATE; } if (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getTollFree())) { return ShortNumberCost.TOLL_FREE; } if (isEmergencyNumber(nationalNumber, regionCode)) { // Emergency numbers are implicitly toll-free. return ShortNumberCost.TOLL_FREE; } return ShortNumberCost.UNKNOWN_COST; }
public void testNonEqualWithItalianLeadingZeroSetToTrue() { PhoneNumber numberA = new PhoneNumber(); numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(true); PhoneNumber numberB = new PhoneNumber(); numberB.setCountryCode(1).setNationalNumber(6502530000L); assertFalse(numberA.equals(numberB)); assertFalse(numberA.hashCode() == numberB.hashCode()); }
public void testParseExtensions() { PhoneNumber nzNumber = new PhoneNumber(); nzNumber.setCountryCode(64).setNationalNumber(33316005L).setExtension("3456"); assertEquals(nzNumber, phoneUtil.parse("03 331 6005 ext 3456", RegionCode.NZ)); assertEquals(nzNumber, phoneUtil.parse("03-3316005x3456", RegionCode.NZ)); assertEquals(nzNumber, phoneUtil.parse("03-3316005 int.3456", RegionCode.NZ)); assertEquals(nzNumber, phoneUtil.parse("03 3316005 #3456", RegionCode.NZ)); // Test the following do not extract extensions: assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("1800 six-flags", RegionCode.US)); assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("1800 SIX FLAGS", RegionCode.US)); assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("0~0 1800 7493 5247", RegionCode.PL)); assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("(1800) 7493.5247", RegionCode.US)); // Check that the last instance of an extension token is matched. PhoneNumber extnNumber = new PhoneNumber().mergeFrom(ALPHA_NUMERIC_NUMBER).setExtension("1234"); assertEquals(extnNumber, phoneUtil.parse("0~0 1800 7493 5247 ~1234", RegionCode.PL)); // Verifying bug-fix where the last digit of a number was previously omitted if it was a 0 when // extracting the extension. Also verifying a few different cases of extensions. PhoneNumber ukNumber = new PhoneNumber(); ukNumber.setCountryCode(44).setNationalNumber(2034567890L).setExtension("456"); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", RegionCode.NZ)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x 456 ", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("+44-2034567890;ext=456", RegionCode.GB)); assertEquals(ukNumber, phoneUtil.parse("tel:2034567890;ext=456;phone-context=+44", RegionCode.ZZ)); // Full-width extension, "extn" only. assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF45\uFF58\uFF54\uFF4E456", RegionCode.GB)); // "xtn" only. assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF58\uFF54\uFF4E456", RegionCode.GB)); // "xt" only. assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF58\uFF54456", RegionCode.GB)); PhoneNumber usWithExtension = new PhoneNumber(); usWithExtension.setCountryCode(1).setNationalNumber(8009013355L).setExtension("7246433"); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 x 7246433", RegionCode.US)); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , ext 7246433", RegionCode.US)); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ,extension 7246433", RegionCode.US)); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ,extensi\u00F3n 7246433", RegionCode.US)); // Repeat with the small letter o with acute accent created by combining characters. assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ,extensio\u0301n 7246433", RegionCode.US)); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , 7246433", RegionCode.US)); assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ext: 7246433", RegionCode.US)); // Test that if a number has two extensions specified, we ignore the second. PhoneNumber usWithTwoExtensionsNumber = new PhoneNumber(); usWithTwoExtensionsNumber.setCountryCode(1).setNationalNumber(2121231234L).setExtension("508"); assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/x1234", RegionCode.US)); assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/ x1234", RegionCode.US)); assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508\\x1234", RegionCode.US)); // Test parsing numbers in the form (645) 123-1234-910# works, where the last 3 digits before // the # are an extension. usWithExtension.clear(); usWithExtension.setCountryCode(1).setNationalNumber(6451231234L).setExtension("910"); assertEquals(usWithExtension, phoneUtil.parse("+1 (645) 123 1234-910#", RegionCode.US)); // Retry with the same number in a slightly different format. assertEquals(usWithExtension, phoneUtil.parse("+1 (645) 123 1234 ext. 910#", RegionCode.US)); }
/** * Given a valid short number, determines whether it is carrier-specific (however, nothing is * implied about its validity). If it is important that the number is valid, then its validity * must first be checked using {@link isValidShortNumber}. * * @param number the valid short number to check * @return whether the short number is carrier-specific (assuming the input was a valid short * number). */ public boolean isCarrierSpecific(PhoneNumber number) { List<String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); String nationalNumber = phoneUtil.getNationalSignificantNumber(number); PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); return (phoneMetadata != null) && (phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getCarrierSpecific())); }
public void testParseAndKeepRaw() { PhoneNumber alphaNumericNumber = new PhoneNumber().mergeFrom(ALPHA_NUMERIC_NUMBER). setRawInput("800 six-flags"). setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY). setPreferredDomesticCarrierCode(""); assertEquals(alphaNumericNumber, phoneUtil.parseAndKeepRawInput("800 six-flags", RegionCode.US)); PhoneNumber shorterAlphaNumber = new PhoneNumber(). setCountryCode(1).setNationalNumber(8007493524L). setRawInput("1800 six-flag"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN). setPreferredDomesticCarrierCode(""); assertEquals(shorterAlphaNumber, phoneUtil.parseAndKeepRawInput("1800 six-flag", RegionCode.US)); shorterAlphaNumber.setRawInput("+1800 six-flag"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); assertEquals(shorterAlphaNumber, phoneUtil.parseAndKeepRawInput("+1800 six-flag", RegionCode.NZ)); shorterAlphaNumber.setRawInput("001800 six-flag"). setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_IDD); assertEquals(shorterAlphaNumber, phoneUtil.parseAndKeepRawInput("001800 six-flag", RegionCode.NZ)); // Invalid region code supplied. try { phoneUtil.parseAndKeepRawInput("123 456 7890", RegionCode.CS); fail("Deprecated region code not allowed: should fail."); } catch (NumberParseException e) { // Expected this exception. assertEquals("Wrong error type stored in exception.", NumberParseException.ErrorType.INVALID_COUNTRY_CODE, e.getErrorType()); } PhoneNumber koreanNumber = new PhoneNumber(); koreanNumber.setCountryCode(82).setNationalNumber(22123456).setRawInput("08122123456"). setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY). setPreferredDomesticCarrierCode("81"); assertEquals(koreanNumber, phoneUtil.parseAndKeepRawInput("08122123456", RegionCode.KR)); }
/** * Tests whether a short number matches a valid pattern. Note that this doesn't verify the number * is actually in use, which is impossible to tell by just looking at the number itself. See * {@link #isValidShortNumber(String, String)} for details. * * @param number the short number for which we want to test the validity * @return whether the short number matches a valid pattern */ public boolean isValidShortNumber(PhoneNumber number) { List<String> regionCodes = phoneUtil.getRegionCodesForCountryCode(number.getCountryCode()); String shortNumber = phoneUtil.getNationalSignificantNumber(number); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); if (regionCodes.size() > 1 && regionCode != null) { // If a matching region had been found for the phone number from among two or more regions, // then we have already implicitly verified its validity for that region. return true; } return isValidShortNumber(shortNumber, regionCode); }
public void testIsVoip() { PhoneNumber gbNumber = new PhoneNumber(); gbNumber.setCountryCode(44).setNationalNumber(5631231234L); assertEquals(PhoneNumberUtil.PhoneNumberType.VOIP, phoneUtil.getNumberType(gbNumber)); }
// Helper method to get the region code for a given phone number, from a list of possible region // codes. If the list contains more than one region, the first region for which the number is // valid is returned. private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number, List<String> regionCodes) { if (regionCodes.size() == 0) { return null; } else if (regionCodes.size() == 1) { return regionCodes.get(0); } String nationalNumber = phoneUtil.getNationalSignificantNumber(number); foreach (String regionCode in regionCodes) { PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); if (phoneMetadata != null && phoneUtil.isNumberMatchingDesc(nationalNumber, phoneMetadata.getShortCode())) { // The number is valid for this region. return regionCode; } } return null; }
public void testValueTypeSemantics() { PhoneNumber number = new PhoneNumber(); PhoneNumberMatch match1 = new PhoneNumberMatch(10, "1 800 234 45 67", number); PhoneNumberMatch match2 = new PhoneNumberMatch(10, "1 800 234 45 67", number); assertEquals(match1, match2); assertEquals(match1.hashCode(), match2.hashCode()); assertEquals(match1.start(), match2.start()); assertEquals(match1.end(), match2.end()); assertEquals(match1.number(), match2.number()); assertEquals(match1.rawString(), match2.rawString()); assertEquals("1 800 234 45 67", match1.rawString()); }
public void testFormatAUNumber() { assertEquals("02 3661 8300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.NATIONAL)); assertEquals("+61 2 3661 8300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.INTERNATIONAL)); assertEquals("+61236618300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.E164)); PhoneNumber auNumber = new PhoneNumber().setCountryCode(61).setNationalNumber(1800123456L); assertEquals("1800 123 456", phoneUtil.format(auNumber, PhoneNumberFormat.NATIONAL)); assertEquals("+61 1800 123 456", phoneUtil.format(auNumber, PhoneNumberFormat.INTERNATIONAL)); assertEquals("+611800123456", phoneUtil.format(auNumber, PhoneNumberFormat.E164)); }