diff --git a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1667_en b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1667_en new file mode 100644 index 000000000..878e9f06c Binary files /dev/null and b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1667_en differ diff --git a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1984_en b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1984_en new file mode 100644 index 000000000..917d35105 Binary files /dev/null and b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/1984_en differ diff --git a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/54_en b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/54_en index ae2fbddc8..3f3986951 100644 Binary files a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/54_en and b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/54_en differ diff --git a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/config b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/config index c7db9c8ef..8b2181a22 100644 Binary files a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/config and b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/config differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java index 37aabb672..3f3042ded 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java @@ -523,7 +523,9 @@ public class AsYouTypeFormatter { nationalNumber.setLength(0); nationalNumber.append(numberWithoutCountryCallingCode); String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode); - if (!newRegionCode.equals(defaultCountry)) { + if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(newRegionCode)) { + currentMetaData = phoneUtil.getMetadataForNonGeographicalRegion(countryCode); + } else if (!newRegionCode.equals(defaultCountry)) { currentMetaData = getMetadataForRegion(newRegionCode); } String countryCodeString = Integer.toString(countryCode); diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java index b69c3cab4..915c02b1e 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java @@ -31,10 +31,10 @@ public class CountryCodeToRegionCodeMap { // countries sharing a calling code, such as the NANPA countries, the one // indicated with "isMainCountryForCode" in the metadata should be first. static Map> getCountryCodeToRegionCodeMap() { - // The capacity is set to 273 as there are 205 different country codes, + // The capacity is set to 280 as there are 210 different country codes, // and this offers a load factor of roughly 0.75. Map> countryCodeToRegionCodeMap = - new HashMap>(273); + new HashMap>(280); ArrayList listWithRegionCode; @@ -773,6 +773,14 @@ public class CountryCodeToRegionCodeMap { listWithRegionCode.add("MH"); countryCodeToRegionCodeMap.put(692, listWithRegionCode); + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(800, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(808, listWithRegionCode); + listWithRegionCode = new ArrayList(1); listWithRegionCode.add("KP"); countryCodeToRegionCodeMap.put(850, listWithRegionCode); @@ -797,10 +805,18 @@ public class CountryCodeToRegionCodeMap { listWithRegionCode.add("BD"); countryCodeToRegionCodeMap.put(880, listWithRegionCode); + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(883, listWithRegionCode); + listWithRegionCode = new ArrayList(1); listWithRegionCode.add("TW"); countryCodeToRegionCodeMap.put(886, listWithRegionCode); + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(888, listWithRegionCode); + listWithRegionCode = new ArrayList(1); listWithRegionCode.add("MV"); countryCodeToRegionCodeMap.put(960, listWithRegionCode); @@ -869,6 +885,10 @@ public class CountryCodeToRegionCodeMap { listWithRegionCode.add("NP"); countryCodeToRegionCodeMap.put(977, listWithRegionCode); + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(979, listWithRegionCode); + listWithRegionCode = new ArrayList(1); listWithRegionCode.add("TJ"); countryCodeToRegionCodeMap.put(992, listWithRegionCode); diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index 1b7759160..1ac393321 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -75,9 +75,9 @@ public class PhoneNumberUtil { private Map> countryCallingCodeToRegionCodeMap = null; // The set of regions the library supports. - // There are roughly 220 of them and we set the initial capacity of the HashSet to 300 to offer a + // There are roughly 240 of them and we set the initial capacity of the HashSet to 320 to offer a // load factor of roughly 0.75. - private final Set supportedRegions = new HashSet(300); + private final Set supportedRegions = new HashSet(320); // Region-code for the unknown region. private static final String UNKNOWN_REGION = "ZZ"; @@ -337,11 +337,19 @@ public class PhoneNumberUtil { private final Map regionToMetadataMap = Collections.synchronizedMap(new HashMap()); + // A mapping from a country calling code for a non-geographical entity to the PhoneMetadata for + // that country calling code. Examples of the country calling codes include 800 (International + // Toll Free Service) and 808 (International Shared Cost Service). + private final Map countryCodeToNonGeographicalMetadataMap = + Collections.synchronizedMap(new HashMap()); + // A cache for frequently used region-specific regular expressions. // As most people use phone numbers primarily from one to two countries, and there are roughly 60 // regular expressions needed, the initial capacity of 100 offers a rough load factor of 0.75. private RegexCache regexCache = new RegexCache(100); + public static final String REGION_CODE_FOR_NON_GEO_ENTITY = "001"; + /** * INTERNATIONAL and NATIONAL formats are consistent with the definition in ITU-T Recommendation * E123. For example, the number of the Google Switzerland office will be written as @@ -667,19 +675,26 @@ public class PhoneNumberUtil { for (List regionCodes : countryCallingCodeToRegionCodeMap.values()) { supportedRegions.addAll(regionCodes); } + supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY); nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE)); } - private void loadMetadataForRegionFromFile(String filePrefix, String regionCode) { - InputStream source = - PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + regionCode); + private void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode) { + boolean isNonGeoRegion = REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode); + InputStream source = isNonGeoRegion + ? PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + countryCallingCode) + : PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + regionCode); ObjectInputStream in = null; try { in = new ObjectInputStream(source); PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection(); metadataCollection.readExternal(in); for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { - regionToMetadataMap.put(regionCode, metadata); + if (isNonGeoRegion) { + countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata); + } else { + regionToMetadataMap.put(regionCode, metadata); + } } } catch (IOException e) { LOGGER.log(Level.WARNING, e.toString()); @@ -854,7 +869,8 @@ public class PhoneNumberUtil { * therefore, it doesn't guarantee the stability of the result it produces. *
  • subscriber numbers may not be diallable from all devices (notably mobile devices, which * typically requires the full national_number to be dialled in most regions). - *
  • most non-geographical numbers have no area codes. + *
  • most non-geographical numbers have no area codes, including numbers from non-geographical + * entities *
  • some geographical numbers have no area codes. * * @param number the PhoneNumber object for which clients want to know the length of the area @@ -1029,19 +1045,10 @@ public class PhoneNumberUtil { } /** - * Helper function to check region code is not unknown or null and log an error message. The - * {@code countryCallingCode} and {@code number} supplied is used only for the resultant log - * message. + * Helper function to check the country calling code is valid. */ - private boolean hasValidRegionCode(String regionCode, - int countryCallingCode, String number) { - if (!isValidRegionCode(regionCode)) { - LOGGER.log(Level.WARNING, - "Number " + number + " has invalid or missing country calling code (" - + countryCallingCode + ")"); - return false; - } - return true; + private boolean hasValidCountryCallingCode(int countryCallingCode) { + return countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode); } /** @@ -1091,12 +1098,13 @@ public class PhoneNumberUtil { // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. String regionCode = getRegionCodeForCountryCode(countryCallingCode); - if (!isValidRegionCode(regionCode)) { + if (!hasValidCountryCallingCode(countryCallingCode)) { formattedNumber.append(nationalSignificantNumber); return; } - PhoneMetadata metadata = getMetadataForRegion(regionCode); + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); formattedNumber.append(formatNationalNumber(nationalSignificantNumber, metadata, numberFormat)); maybeGetFormattedExtension(number, metadata, numberFormat, formattedNumber); formatNumberByFormat(countryCallingCode, numberFormat, formattedNumber); @@ -1122,12 +1130,13 @@ public class PhoneNumberUtil { // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. String regionCode = getRegionCodeForCountryCode(countryCallingCode); - if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + if (!hasValidCountryCallingCode(countryCallingCode)) { return nationalSignificantNumber; } List userDefinedFormatsCopy = new ArrayList(userDefinedFormats.size()); - PhoneMetadata metadata = getMetadataForRegion(regionCode); + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); for (NumberFormat numFormat : userDefinedFormats) { String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule(); if (nationalPrefixFormattingRule.length() > 0) { @@ -1182,12 +1191,12 @@ public class PhoneNumberUtil { // share a country calling code is contained by only one region for performance reasons. For // example, for NANPA regions it will be contained in the metadata for US. String regionCode = getRegionCodeForCountryCode(countryCallingCode); - if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + if (!hasValidCountryCallingCode(countryCallingCode)) { return nationalSignificantNumber; } StringBuilder formattedNumber = new StringBuilder(20); - PhoneMetadata metadata = getMetadataForRegion(regionCode); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); formattedNumber.append(formatNationalNumber(nationalSignificantNumber, metadata, PhoneNumberFormat.NATIONAL, @@ -1197,6 +1206,13 @@ public class PhoneNumberUtil { return formattedNumber.toString(); } + private PhoneMetadata getMetadataForRegionOrCallingCode( + int countryCallingCode, String regionCode) { + return REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + ? getMetadataForNonGeographicalRegion(countryCallingCode) + : getMetadataForRegion(regionCode); + } + /** * Formats a phone number in national format for dialing using the carrier as specified in the * preferredDomesticCarrierCode field of the PhoneNumber object passed in. If that is missing, @@ -1235,8 +1251,8 @@ public class PhoneNumberUtil { */ public String formatNumberForMobileDialing(PhoneNumber number, String regionCallingFrom, boolean withFormatting) { - String regionCode = getRegionCodeForCountryCode(number.getCountryCode()); - if (!isValidRegionCode(regionCode)) { + int countryCallingCode = number.getCountryCode(); + if (!hasValidCountryCallingCode(countryCallingCode)) { return number.hasRawInput() ? number.getRawInput() : ""; } @@ -1244,6 +1260,7 @@ public class PhoneNumberUtil { // Clear the extension, as that part cannot normally be dialed together with the main number. PhoneNumber numberNoExt = new PhoneNumber().mergeFrom(number).clearExtension(); PhoneNumberType numberType = getNumberType(numberNoExt); + String regionCode = getRegionCodeForCountryCode(countryCallingCode); if (regionCode.equals("CO") && regionCallingFrom.equals("CO")) { if (numberType == PhoneNumberType.FIXED_LINE) { formattedNumber = @@ -1300,9 +1317,8 @@ public class PhoneNumberUtil { return format(number, PhoneNumberFormat.INTERNATIONAL); } int countryCallingCode = number.getCountryCode(); - String regionCode = getRegionCodeForCountryCode(countryCallingCode); String nationalSignificantNumber = getNationalSignificantNumber(number); - if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + if (!hasValidCountryCallingCode(countryCallingCode)) { return nationalSignificantNumber; } if (countryCallingCode == NANPA_COUNTRY_CODE) { @@ -1333,7 +1349,9 @@ public class PhoneNumberUtil { metadataForRegionCallingFrom.getPreferredInternationalPrefix(); } - PhoneMetadata metadataForRegion = getMetadataForRegion(regionCode); + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadataForRegion = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); String formattedNationalNumber = formatNationalNumber(nationalSignificantNumber, metadataForRegion, PhoneNumberFormat.INTERNATIONAL); @@ -1359,6 +1377,8 @@ public class PhoneNumberUtil { * country, or we don't have a formatting pattern for the number, the method returns the raw input * when it is available. * + * Note this method guarantees no digit will be inserted, removed or modified as a result of + * formatting. * @param number the phone number that needs to be formatted in its original number format * @param regionCallingFrom the region whose IDD needs to be prefixed if the original number * has one @@ -1374,17 +1394,94 @@ public class PhoneNumberUtil { if (!number.hasCountryCodeSource()) { return format(number, PhoneNumberFormat.NATIONAL); } + String formattedNumber; switch (number.getCountryCodeSource()) { case FROM_NUMBER_WITH_PLUS_SIGN: - return format(number, PhoneNumberFormat.INTERNATIONAL); + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL); + break; case FROM_NUMBER_WITH_IDD: - return formatOutOfCountryCallingNumber(number, regionCallingFrom); + formattedNumber = formatOutOfCountryCallingNumber(number, regionCallingFrom); + break; case FROM_NUMBER_WITHOUT_PLUS_SIGN: - return format(number, PhoneNumberFormat.INTERNATIONAL).substring(1); + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL).substring(1); + break; case FROM_DEFAULT_COUNTRY: + // Fall-through to default case. default: - return format(number, PhoneNumberFormat.NATIONAL); + String regionCode = getRegionCodeForCountryCode(number.getCountryCode()); + // We strip non-digits from the NDD here, and from the raw input later, so that we can + // compare them easily. + String nationalPrefix = getNddPrefixForRegion(regionCode, true /* strip non-digits */); + String nationalFormat = format(number, PhoneNumberFormat.NATIONAL); + if (nationalPrefix == null || nationalPrefix.length() == 0) { + // If the region doesn't have a national prefix at all, we can safely return the national + // format without worrying about a national prefix being added. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we check if the original number was entered with a national prefix. + if (rawInputContainsNationalPrefix( + number.getRawInput(), nationalPrefix, regionCode)) { + // If so, we can safely return the national format. + formattedNumber = nationalFormat; + break; + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + String nationalNumber = getNationalSignificantNumber(number); + NumberFormat formatRule = + chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber); + // When the format we apply to this number doesn't contain national prefix, we can just + // return the national format. + // TODO: Refactor the code below with the code in isNationalPrefixPresentIfRequired. + String candidateNationalPrefixRule = formatRule.getNationalPrefixFormattingRule(); + // We assume that the first-group symbol will never be _before_ the national prefix. + int indexOfFirstGroup = candidateNationalPrefixRule.indexOf("$1"); + if (indexOfFirstGroup <= 0) { + formattedNumber = nationalFormat; + break; + } + candidateNationalPrefixRule = + candidateNationalPrefixRule.substring(0, indexOfFirstGroup); + candidateNationalPrefixRule = normalizeDigitsOnly(candidateNationalPrefixRule); + if (candidateNationalPrefixRule.length() == 0) { + // National prefix not used when formatting this number. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we need to remove the national prefix from our output. + formatRule.clearNationalPrefixFormattingRule(); + List numberFormats = new ArrayList(1); + numberFormats.add(formatRule); + formattedNumber = formatByPattern(number, PhoneNumberFormat.NATIONAL, numberFormats); + break; + } + String rawInput = number.getRawInput(); + // If no digit is inserted/removed/modified as a result of our formatting, we return the + // formatted phone number; otherwise we return the raw input the user entered. + return (formattedNumber != null && + normalizeDigitsOnly(formattedNumber).equals(normalizeDigitsOnly(rawInput))) + ? formattedNumber + : rawInput; + } + + // Check if rawInput, which is assumed to be in the national format, has a national prefix. The + // national prefix is assumed to be in digits-only form. + private boolean rawInputContainsNationalPrefix(String rawInput, String nationalPrefix, + String regionCode) { + String normalizedNationalNumber = normalizeDigitsOnly(rawInput); + if (normalizedNationalNumber.startsWith(nationalPrefix)) { + try { + // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the national prefix + // when written without it (e.g. 0777123) if we just do prefix matching. To tackle that, we + // check the validity of the number if the assumed national prefix is removed (777123 won't + // be valid in Japan). + return isValidNumber( + parse(normalizedNationalNumber.substring(nationalPrefix.length()), regionCode)); + } catch (NumberParseException e) { + return false; + } } + return false; } /** @@ -1396,8 +1493,10 @@ public class PhoneNumberUtil { } private boolean hasFormattingPatternForNumber(PhoneNumber number) { - String phoneNumberRegion = getRegionCodeForCountryCode(number.getCountryCode()); - PhoneMetadata metadata = getMetadataForRegion(phoneNumberRegion); + int countryCallingCode = number.getCountryCode(); + String phoneNumberRegion = getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, phoneNumberRegion); if (metadata == null) { return false; } @@ -1440,8 +1539,7 @@ public class PhoneNumberUtil { return formatOutOfCountryCallingNumber(number, regionCallingFrom); } int countryCode = number.getCountryCode(); - String regionCode = getRegionCodeForCountryCode(countryCode); - if (!hasValidRegionCode(regionCode, countryCode, rawInput)) { + if (!hasValidCountryCallingCode(countryCode)) { return rawInput; } // Strip any prefix such as country calling code, IDD, that was present. We do this by comparing @@ -1460,7 +1558,7 @@ public class PhoneNumberUtil { rawInput = rawInput.substring(firstNationalNumberDigit); } } - PhoneMetadata metadata = getMetadataForRegion(regionCallingFrom); + PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom); if (countryCode == NANPA_COUNTRY_CODE) { if (isNANPACountry(regionCallingFrom)) { return countryCode + " " + rawInput; @@ -1468,8 +1566,8 @@ public class PhoneNumberUtil { } else if (countryCode == getCountryCodeForRegion(regionCallingFrom)) { // Here we copy the formatting rules so we can modify the pattern we expect to match against. List availableFormats = - new ArrayList(metadata.numberFormatSize()); - for (NumberFormat format : metadata.numberFormats()) { + new ArrayList(metadataForRegionCallingFrom.numberFormatSize()); + for (NumberFormat format : metadataForRegionCallingFrom.numberFormats()) { NumberFormat newFormat = new NumberFormat(); newFormat.mergeFrom(format); // The first group is the first group of digits that the user determined. @@ -1486,20 +1584,28 @@ public class PhoneNumberUtil { // anything, but that is not the case in the metadata to date. return formatAccordingToFormats(rawInput, availableFormats, PhoneNumberFormat.NATIONAL); } - String internationalPrefix = metadata.getInternationalPrefix(); - // For countries that have multiple international prefixes, the international format of the - // number is returned, unless there is a preferred international prefix. - String internationalPrefixForFormatting = - UNIQUE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches() - ? internationalPrefix - : metadata.getPreferredInternationalPrefix(); + String internationalPrefixForFormatting = ""; + // If an unsupported region-calling-from is entered, or a country with multiple international + // prefixes, the international format of the number is returned, unless there is a preferred + // international prefix. + if (metadataForRegionCallingFrom != null) { + String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix(); + internationalPrefixForFormatting = + UNIQUE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches() + ? internationalPrefix + : metadataForRegionCallingFrom.getPreferredInternationalPrefix(); + } StringBuilder formattedNumber = new StringBuilder(rawInput); - maybeGetFormattedExtension(number, getMetadataForRegion(regionCode), + String regionCode = getRegionCodeForCountryCode(countryCode); + PhoneMetadata metadataForRegion = getMetadataForRegionOrCallingCode(countryCode, regionCode); + maybeGetFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL, formattedNumber); if (internationalPrefixForFormatting.length() > 0) { formattedNumber.insert(0, " ").insert(0, countryCode).insert(0, " ") .insert(0, internationalPrefixForFormatting); } else { + // Invalid region entered as country-calling-from (so no metadata was found for it) or the + // region chosen has multiple international dialling prefixes. formatNumberByFormat(countryCode, PhoneNumberFormat.INTERNATIONAL, formattedNumber); @@ -1641,7 +1747,8 @@ public class PhoneNumberUtil { * * @param regionCode the region for which an example number is needed * @return a valid fixed-line number for the specified region. Returns null when the metadata - * does not contain such information. + * does not contain such information, or the region 001 is passed in. For 001 (representing + * non-geographical numbers), call {@link #getExampleNumberForNonGeoEntity} instead. */ public PhoneNumber getExampleNumber(String regionCode) { return getExampleNumberForType(regionCode, PhoneNumberType.FIXED_LINE); @@ -1653,7 +1760,9 @@ public class PhoneNumberUtil { * @param regionCode the region for which an example number is needed * @param type the type of number that is needed * @return a valid number for the specified region and type. Returns null when the metadata - * does not contain such information or if an invalid region was entered. + * does not contain such information or if an invalid region or region 001 was entered. + * For 001 (representing non-geographical numbers), call + * {@link #getExampleNumberForNonGeoEntity} instead. */ public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) { // Check the region code is valid. @@ -1672,6 +1781,29 @@ public class PhoneNumberUtil { return null; } + /** + * Gets a valid number for the specified country calling code for a non-geographical entity. + * + * @param countryCallingCode the country calling code for a non-geographical entity + * @return a valid number for the non-geographical entity. Returns null when the metadata + * does not contain such information, or the country calling code passed in does not belong + * to a non-geographical entity. + */ + public PhoneNumber getExampleNumberForNonGeoEntity(int countryCallingCode) { + PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); + if (metadata != null) { + PhoneNumberDesc desc = metadata.getGeneralDesc(); + try { + if (desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), "ZZ"); + } + } catch (NumberParseException e) { + LOGGER.log(Level.SEVERE, e.toString()); + } + } + return null; + } + /** * Appends the formatted extension of a phone number to formattedNumber, if the phone number had * an extension specified. @@ -1738,11 +1870,12 @@ public class PhoneNumberUtil { */ public PhoneNumberType getNumberType(PhoneNumber number) { String regionCode = getRegionCodeForNumber(number); - if (!isValidRegionCode(regionCode)) { + if (!isValidRegionCode(regionCode) && !REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode)) { return PhoneNumberType.UNKNOWN; } String nationalSignificantNumber = getNationalSignificantNumber(number); - return getNumberTypeHelper(nationalSignificantNumber, getMetadataForRegion(regionCode)); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode); + return getNumberTypeHelper(nationalSignificantNumber, metadata); } private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) { @@ -1801,12 +1934,26 @@ public class PhoneNumberUtil { } synchronized (regionToMetadataMap) { if (!regionToMetadataMap.containsKey(regionCode)) { - loadMetadataForRegionFromFile(currentFilePrefix, regionCode); + // The regionCode here will be valid and won't be '001', so we don't need to worry about + // what to pass in for the country calling code. + loadMetadataFromFile(currentFilePrefix, regionCode, 0); } } return regionToMetadataMap.get(regionCode); } + PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { + synchronized (countryCodeToNonGeographicalMetadataMap) { + if (!countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode)) { + return null; + } + if (!countryCodeToNonGeographicalMetadataMap.containsKey(countryCallingCode)) { + loadMetadataFromFile(currentFilePrefix, REGION_CODE_FOR_NON_GEO_ENTITY, countryCallingCode); + } + } + return countryCodeToNonGeographicalMetadataMap.get(countryCallingCode); + } + private boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) { Matcher possibleNumberPatternMatcher = regexCache.getPatternForRegex(numberDesc.getPossibleNumberPattern()) @@ -1826,7 +1973,7 @@ public class PhoneNumberUtil { */ public boolean isValidNumber(PhoneNumber number) { String regionCode = getRegionCodeForNumber(number); - return (isValidRegionCode(regionCode) && isValidNumberForRegion(number, regionCode)); + return isValidNumberForRegion(number, regionCode); } /** @@ -1842,10 +1989,13 @@ public class PhoneNumberUtil { * @return a boolean that indicates whether the number is of a valid pattern */ public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) { - if (number.getCountryCode() != getCountryCodeForRegion(regionCode)) { + int countryCode = number.getCountryCode(); + if (countryCode == 0 || + (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) && + countryCode != getCountryCodeForRegion(regionCode))) { return false; } - PhoneMetadata metadata = getMetadataForRegion(regionCode); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); PhoneNumberDesc generalNumDesc = metadata.getGeneralDesc(); String nationalSignificantNumber = getNationalSignificantNumber(number); @@ -1871,6 +2021,9 @@ public class PhoneNumberUtil { int countryCode = number.getCountryCode(); List regions = countryCallingCodeToRegionCodeMap.get(countryCode); if (regions == null) { + String numberString = getNationalSignificantNumber(number); + LOGGER.log(Level.WARNING, + "Missing/invalid country_code (" + countryCode + ") for number " + numberString); return null; } if (regions.size() == 1) { @@ -1917,6 +2070,10 @@ public class PhoneNumberUtil { */ public int getCountryCodeForRegion(String regionCode) { if (!isValidRegionCode(regionCode)) { + LOGGER.log(Level.SEVERE, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); return 0; } PhoneMetadata metadata = getMetadataForRegion(regionCode); @@ -1939,7 +2096,10 @@ public class PhoneNumberUtil { */ public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) { if (!isValidRegionCode(regionCode)) { - LOGGER.log(Level.SEVERE, "Invalid or missing region code provided."); + LOGGER.log(Level.SEVERE, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); return null; } PhoneMetadata metadata = getMetadataForRegion(regionCode); @@ -2055,11 +2215,12 @@ public class PhoneNumberUtil { // Russia) since the getRegionCodeForNumber will not work if the number is possible but not // valid. This would need to be revisited if the possible number pattern ever differed between // various regions within those plans. - String regionCode = getRegionCodeForCountryCode(countryCode); - if (!isValidRegionCode(regionCode)) { + if (!hasValidCountryCallingCode(countryCode)) { return ValidationResult.INVALID_COUNTRY_CODE; } - PhoneNumberDesc generalNumDesc = getMetadataForRegion(regionCode).getGeneralDesc(); + String regionCode = getRegionCodeForCountryCode(countryCode); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); + PhoneNumberDesc generalNumDesc = metadata.getGeneralDesc(); // Handling case of numbers with no metadata. if (!generalNumDesc.hasNationalNumberPattern()) { LOGGER.log(Level.FINER, "Checking if number is possible with incomplete metadata."); @@ -2607,7 +2768,7 @@ public class PhoneNumberUtil { if (countryCode != 0) { String phoneNumberRegion = getRegionCodeForCountryCode(countryCode); if (!phoneNumberRegion.equals(defaultRegion)) { - regionMetadata = getMetadataForRegion(phoneNumberRegion); + regionMetadata = getMetadataForRegionOrCallingCode(countryCode, phoneNumberRegion); } } else { // If no extracted country calling code, use the region supplied instead. The national number @@ -2819,23 +2980,24 @@ public class PhoneNumberUtil { } /** - * Returns true if the number can only be dialled from within the region. If unknown, or the - * number can be dialled from outside the region as well, returns false. Does not check the - * number is a valid number. - * TODO: Make this method public when we have enough metadata to make it worthwhile. Currently - * visible for testing purposes only. + * Returns true if the number can be dialled from outside the region, or unknown. If the number + * can only be dialled from within the region, returns false. Does not check the number is a valid + * number. + * TODO: Make this method public when we have enough metadata to make it worthwhile. * - * @param number the phone-number for which we want to know whether it is only diallable from - * within the region + * @param number the phone-number for which we want to know whether it is diallable from + * outside the region */ // @VisibleForTesting boolean canBeInternationallyDialled(PhoneNumber number) { String regionCode = getRegionCodeForNumber(number); - String nationalSignificantNumber = getNationalSignificantNumber(number); - if (!hasValidRegionCode(regionCode, number.getCountryCode(), nationalSignificantNumber)) { + if (!isValidRegionCode(regionCode)) { + // Note numbers belonging to non-geographical entities (e.g. +800 numbers) are always + // internationally diallable, and will be caught here. return true; } PhoneMetadata metadata = getMetadataForRegion(regionCode); + String nationalSignificantNumber = getNationalSignificantNumber(number); return !isNumberMatchingDesc(nationalSignificantNumber, metadata.getNoInternationalDialling()); } } diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 new file mode 100644 index 000000000..e958189ae Binary files /dev/null and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 new file mode 100644 index 000000000..866291685 Binary files /dev/null and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 new file mode 100644 index 000000000..ffa9a8df0 Binary files /dev/null and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 new file mode 100644 index 000000000..7cc7cff0b Binary files /dev/null and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 new file mode 100644 index 000000000..0c143ce55 Binary files /dev/null and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR index 509048bdf..ca23407be 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH index 0d8751e98..9cc62646a 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI index 330776dcb..5598d7fb6 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN index bbf50d729..2105a58f3 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR index 8f24de016..307c8abfc 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE index 422e0141c..673ba16f5 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA index 7de2f9b9a..438299c66 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL index 7a3018607..5faf3433a 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO index ffe41589f..b9c11bff4 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP index 835ee2861..eaae271cf 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE index 3a115efbe..197ff1edc 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ index f07d1d531..0fe135af4 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB index e7ed25942..255bc5f71 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK index 27342215e..a97babade 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT index e4a8d6727..4b646f755 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV index 4f76c810b..7d100a39d 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW index 0d113a6b3..2fb695207 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ index 1293ba58e..cac3c1473 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA index b1c73ab61..2ee1fa962 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL index da3955cfc..ab3aa54fc 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ index cf5911844..1c8cb6362 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL index 14f82a0a4..9424b977f 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO index 548fcc98c..e3924d3fe 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA index cf10bc745..b4f4e3b26 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV index 17cb40f8f..a38632516 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM index 1d3a3d7ab..2243056e8 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG index 2d0f9b358..039084ff3 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG differ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US index 74a30081a..f06745352 100644 Binary files a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US and b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US differ diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java index a4f7244cb..24eb8d708 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java @@ -685,6 +685,24 @@ public class AsYouTypeFormatterTest extends TestCase { assertEquals("+52 1 541 234 5678", formatter.inputDigit('8')); } + public void testAYTF_International_Toll_Free() { + AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US); + // +800 1234 5678 + assertEquals("+", formatter.inputDigit('+')); + assertEquals("+8", formatter.inputDigit('8')); + assertEquals("+80", formatter.inputDigit('0')); + assertEquals("+800 ", formatter.inputDigit('0')); + assertEquals("+800 1", formatter.inputDigit('1')); + assertEquals("+800 12", formatter.inputDigit('2')); + assertEquals("+800 123", formatter.inputDigit('3')); + assertEquals("+800 1234", formatter.inputDigit('4')); + assertEquals("+800 1234 5", formatter.inputDigit('5')); + assertEquals("+800 1234 56", formatter.inputDigit('6')); + assertEquals("+800 1234 567", formatter.inputDigit('7')); + assertEquals("+800 1234 5678", formatter.inputDigit('8')); + assertEquals("+800123456789", formatter.inputDigit('9')); + } + public void testAYTFMultipleLeadingDigitPatterns() { // +81 50 2345 6789 AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.JP); diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java index 6d7417dea..8b78fe920 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java @@ -31,10 +31,10 @@ public class CountryCodeToRegionCodeMapForTesting { // countries sharing a calling code, such as the NANPA countries, the one // indicated with "isMainCountryForCode" in the metadata should be first. static Map> getCountryCodeToRegionCodeMap() { - // The capacity is set to 21 as there are 16 different country codes, + // The capacity is set to 22 as there are 17 different country codes, // and this offers a load factor of roughly 0.75. Map> countryCodeToRegionCodeMap = - new HashMap>(21); + new HashMap>(22); ArrayList listWithRegionCode; @@ -104,6 +104,10 @@ public class CountryCodeToRegionCodeMapForTesting { listWithRegionCode.add("AD"); countryCodeToRegionCodeMap.put(376, listWithRegionCode); + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(800, listWithRegionCode); + return countryCodeToRegionCodeMap; } } diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java index 9ee4bafc0..a9f841d07 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java @@ -369,20 +369,20 @@ public class PhoneNumberMatcherTest extends TestCase { new NumberTest("31/8/2011", RegionCode.US), new NumberTest("1/12/2011", RegionCode.US), new NumberTest("10/12/82", RegionCode.DE), + new NumberTest("650x2531234", RegionCode.US), }; /** * Strings with number-like things that should only be found under "possible". */ private static final NumberTest[] POSSIBLE_ONLY_CASES = { - new NumberTest("abc8002345678", RegionCode.US), // US numbers cannot start with 7 in the test metadata to be valid. new NumberTest("7121115678", RegionCode.US), // 'X' should not be found in numbers at leniencies stricter than POSSIBLE, unless it represents // a carrier code or extension. new NumberTest("1650 x 253 - 1234", RegionCode.US), new NumberTest("650 x 253 - 1234", RegionCode.US), - new NumberTest("650x2531234", RegionCode.US), + new NumberTest("6502531x234", RegionCode.US), new NumberTest("(20) 3346 1234", RegionCode.GB), // Non-optional NP omitted }; @@ -391,18 +391,19 @@ public class PhoneNumberMatcherTest extends TestCase { * leniency level. */ private static final NumberTest[] VALID_CASES = { - new NumberTest("65 02 53 00 00.", RegionCode.US), + new NumberTest("65 02 53 00 00", RegionCode.US), new NumberTest("6502 538365", RegionCode.US), new NumberTest("650//253-1234", RegionCode.US), // 2 slashes are illegal at higher levels new NumberTest("650/253/1234", RegionCode.US), new NumberTest("9002309. 158", RegionCode.US), - new NumberTest("21 7/8 - 14 12/34 - 5", RegionCode.US), + new NumberTest("12 7/8 - 14 12/34 - 5", RegionCode.US), new NumberTest("12.1 - 23.71 - 23.45", RegionCode.US), - new NumberTest("1979-2011 100%", RegionCode.US), + new NumberTest("800 234 1 111x1111", RegionCode.US), + new NumberTest("1979-2011 100", RegionCode.US), new NumberTest("+494949-4-94", RegionCode.DE), // National number in wrong format - new NumberTest("\uFF14\uFF11\uFF15\uFF16\uFF16\uFF16\uFF16-\uFF17\uFF17\uFF17\uFF17", - RegionCode.US), + new NumberTest("\uFF14\uFF11\uFF15\uFF16\uFF16\uFF16\uFF16-\uFF17\uFF17\uFF17", RegionCode.US), + }; /** @@ -443,6 +444,36 @@ public class PhoneNumberMatcherTest extends TestCase { new NumberTest("(33) 3461 2234", RegionCode.MX), // Optional NP omitted }; + public void testMatchesWithPossibleLeniency() throws Exception { + List testCases = new ArrayList(); + testCases.addAll(Arrays.asList(STRICT_GROUPING_CASES)); + testCases.addAll(Arrays.asList(EXACT_GROUPING_CASES)); + testCases.addAll(Arrays.asList(VALID_CASES)); + testCases.addAll(Arrays.asList(POSSIBLE_ONLY_CASES)); + doTestNumberMatchesForLeniency(testCases, Leniency.POSSIBLE); + } + + public void testNonMatchesWithPossibleLeniency() throws Exception { + List testCases = new ArrayList(); + testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES)); + doTestNumberNonMatchesForLeniency(testCases, Leniency.POSSIBLE); + } + + public void testMatchesWithValidLeniency() throws Exception { + List testCases = new ArrayList(); + testCases.addAll(Arrays.asList(STRICT_GROUPING_CASES)); + testCases.addAll(Arrays.asList(EXACT_GROUPING_CASES)); + testCases.addAll(Arrays.asList(VALID_CASES)); + doTestNumberMatchesForLeniency(testCases, Leniency.VALID); + } + + public void testNonMatchesWithValidLeniency() throws Exception { + List testCases = new ArrayList(); + testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES)); + testCases.addAll(Arrays.asList(POSSIBLE_ONLY_CASES)); + doTestNumberNonMatchesForLeniency(testCases, Leniency.VALID); + } + public void testMatchesWithStrictGroupingLeniency() throws Exception { List testCases = new ArrayList(); testCases.addAll(Arrays.asList(STRICT_GROUPING_CASES)); diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java index c2e28e1d2..ea480c017 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java @@ -105,6 +105,10 @@ public class PhoneNumberUtilTest extends TestCase { private static final PhoneNumber US_SPOOF_WITH_RAW_INPUT = new PhoneNumber().setCountryCode(1).setNationalNumber(0L) .setRawInput("000-000-0000"); + private static final PhoneNumber INTERNATIONAL_TOLL_FREE = + new PhoneNumber().setCountryCode(800).setNationalNumber(12345678L); + private static final PhoneNumber INTERNATIONAL_TOLL_FREE_TOO_LONG = + new PhoneNumber().setCountryCode(800).setNationalNumber(1234567890L); public PhoneNumberUtilTest() { phoneUtil = initializePhoneUtilForTesting(); @@ -123,7 +127,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testGetInstanceLoadUSMetadata() { PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US); - assertEquals(RegionCode.US, metadata.getId()); + assertEquals("US", metadata.getId()); assertEquals(1, metadata.getCountryCode()); assertEquals("011", metadata.getInternationalPrefix()); assertTrue(metadata.hasNationalPrefix()); @@ -144,7 +148,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testGetInstanceLoadDEMetadata() { PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.DE); - assertEquals(RegionCode.DE, metadata.getId()); + assertEquals("DE", metadata.getId()); assertEquals(49, metadata.getCountryCode()); assertEquals("00", metadata.getInternationalPrefix()); assertEquals("0", metadata.getNationalPrefix()); @@ -164,7 +168,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testGetInstanceLoadARMetadata() { PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.AR); - assertEquals(RegionCode.AR, metadata.getId()); + assertEquals("AR", metadata.getId()); assertEquals(54, metadata.getCountryCode()); assertEquals("00", metadata.getInternationalPrefix()); assertEquals("0", metadata.getNationalPrefix()); @@ -178,10 +182,21 @@ public class PhoneNumberUtilTest extends TestCase { assertEquals("$1 $2 $3 $4", metadata.getIntlNumberFormat(3).getFormat()); } + public void testGetInstanceLoadInternationalTollFreeMetadata() { + PhoneMetadata metadata = phoneUtil.getMetadataForNonGeographicalRegion(800); + assertEquals("001", metadata.getId()); + assertEquals(800, metadata.getCountryCode()); + assertEquals("$1 $2", metadata.getNumberFormat(0).getFormat()); + assertEquals("(\\d{4})(\\d{4})", metadata.getNumberFormat(0).getPattern()); + assertEquals("12345678", metadata.getGeneralDesc().getExampleNumber()); + assertEquals("12345678", metadata.getTollFree().getExampleNumber()); + } + public void testIsLeadingZeroPossible() { assertTrue(phoneUtil.isLeadingZeroPossible(39)); // Italy assertFalse(phoneUtil.isLeadingZeroPossible(1)); // USA - assertFalse(phoneUtil.isLeadingZeroPossible(800)); // Not in metadata file, just default to + assertFalse(phoneUtil.isLeadingZeroPossible(800)); // International toll free numbers + assertFalse(phoneUtil.isLeadingZeroPossible(888)); // Not in metadata file, just default to // false. } @@ -209,6 +224,9 @@ public class PhoneNumberUtilTest extends TestCase { // An invalid US number (1 digit shorter), which has no area code. assertEquals(0, phoneUtil.getLengthOfGeographicalAreaCode(US_SHORT_BY_ONE_NUMBER)); + + // An international toll free number, which has no area code. + assertEquals(0, phoneUtil.getLengthOfGeographicalAreaCode(INTERNATIONAL_TOLL_FREE)); } public void testGetLengthOfNationalDestinationCode() { @@ -242,6 +260,9 @@ public class PhoneNumberUtilTest extends TestCase { // A number containing an invalid country calling code, which shouldn't have any NDC. PhoneNumber number = new PhoneNumber().setCountryCode(123).setNationalNumber(6502530000L); assertEquals(0, phoneUtil.getLengthOfNationalDestinationCode(number)); + + // An international toll free number, which has NDC "1234". + assertEquals(4, phoneUtil.getLengthOfNationalDestinationCode(INTERNATIONAL_TOLL_FREE)); } public void testGetNationalSignificantNumber() { @@ -252,6 +273,8 @@ public class PhoneNumberUtilTest extends TestCase { // An Italian fixed line number. assertEquals("0236618300", phoneUtil.getNationalSignificantNumber(IT_NUMBER)); + + assertEquals("12345678", phoneUtil.getNationalSignificantNumber(INTERNATIONAL_TOLL_FREE)); } public void testGetExampleNumber() { @@ -272,6 +295,13 @@ public class PhoneNumberUtilTest extends TestCase { // CS is an invalid region, so we have no data for it. assertNull(phoneUtil.getExampleNumberForType(RegionCode.CS, PhoneNumberUtil.PhoneNumberType.MOBILE)); + // RegionCode 001 is reserved for supporting non-geographical country calling code. We don't + // support getting an example number for it with this method. + assertEquals(null, phoneUtil.getExampleNumber(RegionCode.UN001)); + } + + public void testGetExampleNumberForNonGeoEntity() { + assertEquals(INTERNATIONAL_TOLL_FREE, phoneUtil.getExampleNumberForNonGeoEntity(800)); } public void testConvertAlphaCharactersInNumber() { @@ -469,6 +499,8 @@ public class PhoneNumberUtilTest extends TestCase { 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", @@ -483,7 +515,10 @@ public class PhoneNumberUtilTest extends TestCase { // AQ/Antarctica isn't a valid region code for phone number formatting, // so this falls back to intl formatting. assertEquals("+1 650 253 0000", - phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, "AQ")); + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.AQ)); + // For region code 001, the out-of-country format always turns into the international format. + assertEquals("+1 650 253 0000", + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.UN001)); } public void testFormatOutOfCountryWithPreferredIntlPrefix() { @@ -551,6 +586,9 @@ public class PhoneNumberUtilTest extends TestCase { // 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) @@ -564,6 +602,12 @@ public class PhoneNumberUtilTest extends TestCase { // 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)); } public void testFormatWithCarrierCode() { @@ -646,6 +690,11 @@ public class PhoneNumberUtilTest extends TestCase { 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)); } public void testFormatByPattern() { @@ -709,6 +758,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testFormatE164Number() { assertEquals("+16502530000", phoneUtil.format(US_NUMBER, PhoneNumberFormat.E164)); assertEquals("+4930123456", phoneUtil.format(DE_NUMBER, PhoneNumberFormat.E164)); + assertEquals("+80012345678", phoneUtil.format(INTERNATIONAL_TOLL_FREE, PhoneNumberFormat.E164)); } public void testFormatNumberWithExtension() { @@ -723,7 +773,7 @@ public class PhoneNumberUtilTest extends TestCase { PhoneNumberFormat.NATIONAL)); } - public void testFormatUsingOriginalNumberFormat() throws Exception { + public void testFormatInOriginalFormat() throws Exception { PhoneNumber number1 = phoneUtil.parseAndKeepRawInput("+442087654321", RegionCode.GB); assertEquals("+44 20 8765 4321", phoneUtil.formatInOriginalFormat(number1, RegionCode.GB)); @@ -746,17 +796,88 @@ public class PhoneNumberUtilTest extends TestCase { // US is not a leading zero country, and the presence of the leading zero leads us to format the // number using raw_input. - PhoneNumber number7 = phoneUtil.parseAndKeepRawInput("07345678901", RegionCode.US); - assertEquals("07345678901", phoneUtil.formatInOriginalFormat(number7, RegionCode.US)); + PhoneNumber number7 = phoneUtil.parseAndKeepRawInput("0734567 8901", RegionCode.US); + assertEquals("0734567 8901", phoneUtil.formatInOriginalFormat(number7, RegionCode.US)); // This number is valid, but we don't have a formatting pattern for it. Fall back to the raw // input. PhoneNumber number8 = phoneUtil.parseAndKeepRawInput("02-4567-8900", RegionCode.KR); assertEquals("02-4567-8900", phoneUtil.formatInOriginalFormat(number8, RegionCode.KR)); + PhoneNumber number9 = phoneUtil.parseAndKeepRawInput("01180012345678", RegionCode.US); + assertEquals("011 800 1234 5678", phoneUtil.formatInOriginalFormat(number9, RegionCode.US)); + + PhoneNumber number10 = phoneUtil.parseAndKeepRawInput("+80012345678", RegionCode.KR); + assertEquals("+800 1234 5678", phoneUtil.formatInOriginalFormat(number10, RegionCode.KR)); + // US local numbers are formatted correctly, as we have formatting patterns for them. PhoneNumber localNumberUS = phoneUtil.parseAndKeepRawInput("2530000", RegionCode.US); assertEquals("253 0000", phoneUtil.formatInOriginalFormat(localNumberUS, RegionCode.US)); + + PhoneNumber numberWithNationalPrefixUS = + phoneUtil.parseAndKeepRawInput("18003456789", RegionCode.US); + assertEquals("1 800 345 6789", + phoneUtil.formatInOriginalFormat(numberWithNationalPrefixUS, RegionCode.US)); + + PhoneNumber numberWithoutNationalPrefixGB = + phoneUtil.parseAndKeepRawInput("2087654321", RegionCode.GB); + assertEquals("20 8765 4321", + phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixGB, RegionCode.GB)); + + PhoneNumber numberWithNationalPrefixMX = + phoneUtil.parseAndKeepRawInput("013312345678", RegionCode.MX); + assertEquals("01 33 1234 5678", + phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX, RegionCode.MX)); + + PhoneNumber numberWithoutNationalPrefixMX = + phoneUtil.parseAndKeepRawInput("3312345678", RegionCode.MX); + assertEquals("33 1234 5678", + phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixMX, RegionCode.MX)); + + PhoneNumber italianFixedLineNumber = + phoneUtil.parseAndKeepRawInput("0212345678", RegionCode.IT); + assertEquals("02 1234 5678", + phoneUtil.formatInOriginalFormat(italianFixedLineNumber, RegionCode.IT)); + + PhoneNumber numberWithNationalPrefixJP = + phoneUtil.parseAndKeepRawInput("00777012", RegionCode.JP); + assertEquals("0077-7012", + phoneUtil.formatInOriginalFormat(numberWithNationalPrefixJP, RegionCode.JP)); + + PhoneNumber numberWithoutNationalPrefixJP = + phoneUtil.parseAndKeepRawInput("0777012", RegionCode.JP); + assertEquals("0777012", + phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixJP, RegionCode.JP)); + + PhoneNumber numberWithCarrierCodeBR = + phoneUtil.parseAndKeepRawInput("012 3121286979", RegionCode.BR); + assertEquals("012 3121286979", + phoneUtil.formatInOriginalFormat(numberWithCarrierCodeBR, RegionCode.BR)); + + // The default national prefix used in this case is 045. When a number with national prefix 044 + // is entered, we return the raw input as we don't want to change the number entered. + PhoneNumber numberWithNationalPrefixMX1 = + phoneUtil.parseAndKeepRawInput("044(33)1234-5678", RegionCode.MX); + assertEquals("044(33)1234-5678", + phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX1, RegionCode.MX)); + + PhoneNumber numberWithNationalPrefixMX2 = + phoneUtil.parseAndKeepRawInput("045(33)1234-5678", RegionCode.MX); + assertEquals("045 33 1234 5678", + phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX2, RegionCode.MX)); + + // The default international prefix used in this case is 0011. When a number with international + // prefix 0012 is entered, we return the raw input as we don't want to change the number + // entered. + PhoneNumber outOfCountryNumberFromAU1 = + phoneUtil.parseAndKeepRawInput("0012 16502530000", RegionCode.AU); + assertEquals("0012 16502530000", + phoneUtil.formatInOriginalFormat(outOfCountryNumberFromAU1, RegionCode.AU)); + + PhoneNumber outOfCountryNumberFromAU2 = + phoneUtil.parseAndKeepRawInput("0011 16502530000", RegionCode.AU); + assertEquals("0011 1 650 253 0000", + phoneUtil.formatInOriginalFormat(outOfCountryNumberFromAU2, RegionCode.AU)); } public void testIsPremiumRate() { @@ -804,6 +925,9 @@ public class PhoneNumberUtilTest extends TestCase { tollFreeNumber.setCountryCode(49).setNationalNumber(8001234567L); assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE, phoneUtil.getNumberType(tollFreeNumber)); + + assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE, + phoneUtil.getNumberType(INTERNATIONAL_TOLL_FREE)); } public void testIsMobile() { @@ -862,6 +986,7 @@ public class PhoneNumberUtilTest extends TestCase { assertTrue(phoneUtil.isValidNumber(US_NUMBER)); assertTrue(phoneUtil.isValidNumber(IT_NUMBER)); assertTrue(phoneUtil.isValidNumber(GB_MOBILE)); + assertTrue(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE)); PhoneNumber nzNumber = new PhoneNumber().setCountryCode(64).setNationalNumber(21387835L); assertTrue(phoneUtil.isValidNumber(nzNumber)); @@ -898,6 +1023,8 @@ public class PhoneNumberUtilTest extends TestCase { reNumber.setNationalNumber(800123456L); assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT)); assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE)); + assertTrue(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.UN001)); + assertFalse(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.US)); } public void testIsNotValidNumber() { @@ -918,18 +1045,22 @@ public class PhoneNumberUtilTest extends TestCase { invalidNumber.clear(); invalidNumber.setCountryCode(64).setNationalNumber(3316005L); assertFalse(phoneUtil.isValidNumber(invalidNumber)); + + assertFalse(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE_TOO_LONG)); } public void testGetRegionCodeForCountryCode() { assertEquals(RegionCode.US, phoneUtil.getRegionCodeForCountryCode(1)); assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForCountryCode(44)); assertEquals(RegionCode.DE, phoneUtil.getRegionCodeForCountryCode(49)); + assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForCountryCode(800)); } public void testGetRegionCodeForNumber() { assertEquals(RegionCode.BS, phoneUtil.getRegionCodeForNumber(BS_NUMBER)); assertEquals(RegionCode.US, phoneUtil.getRegionCodeForNumber(US_NUMBER)); assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForNumber(GB_MOBILE)); + assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForNumber(INTERNATIONAL_TOLL_FREE)); } public void testGetCountryCodeForRegion() { @@ -937,6 +1068,7 @@ public class PhoneNumberUtilTest extends TestCase { assertEquals(64, phoneUtil.getCountryCodeForRegion(RegionCode.NZ)); assertEquals(0, phoneUtil.getCountryCodeForRegion(null)); assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.ZZ)); + assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.UN001)); // CS is already deprecated so the library doesn't support it. assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.CS)); } @@ -953,6 +1085,7 @@ public class PhoneNumberUtilTest extends TestCase { // Test cases with invalid regions. assertEquals(null, phoneUtil.getNddPrefixForRegion(null, false)); assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.ZZ, false)); + assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.UN001, false)); // CS is already deprecated so the library doesn't support it. assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.CS, false)); } @@ -962,6 +1095,7 @@ public class PhoneNumberUtilTest extends TestCase { assertTrue(phoneUtil.isNANPACountry(RegionCode.BS)); assertFalse(phoneUtil.isNANPACountry(RegionCode.DE)); assertFalse(phoneUtil.isNANPACountry(RegionCode.ZZ)); + assertFalse(phoneUtil.isNANPACountry(RegionCode.UN001)); assertFalse(phoneUtil.isNANPACountry(null)); } @@ -969,6 +1103,7 @@ public class PhoneNumberUtilTest extends TestCase { assertTrue(phoneUtil.isPossibleNumber(US_NUMBER)); assertTrue(phoneUtil.isPossibleNumber(US_LOCAL_NUMBER)); assertTrue(phoneUtil.isPossibleNumber(GB_NUMBER)); + assertTrue(phoneUtil.isPossibleNumber(INTERNATIONAL_TOLL_FREE)); assertTrue(phoneUtil.isPossibleNumber("+1 650 253 0000", RegionCode.US)); assertTrue(phoneUtil.isPossibleNumber("+1 650 GOO OGLE", RegionCode.US)); @@ -979,6 +1114,7 @@ public class PhoneNumberUtilTest extends TestCase { assertTrue(phoneUtil.isPossibleNumber("(020) 7031 3000", RegionCode.GB)); assertTrue(phoneUtil.isPossibleNumber("7031 3000", RegionCode.GB)); assertTrue(phoneUtil.isPossibleNumber("3331 6005", RegionCode.NZ)); + assertTrue(phoneUtil.isPossibleNumber("+800 1234 5678", RegionCode.UN001)); } public void testIsPossibleNumberWithReason() { @@ -1007,6 +1143,9 @@ public class PhoneNumberUtilTest extends TestCase { assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE, phoneUtil.isPossibleNumberWithReason(number)); + assertEquals(PhoneNumberUtil.ValidationResult.TOO_LONG, + phoneUtil.isPossibleNumberWithReason(INTERNATIONAL_TOLL_FREE_TOO_LONG)); + // Try with number that we don't have metadata for. PhoneNumber adNumber = new PhoneNumber(); adNumber.setCountryCode(376).setNationalNumber(12345L); @@ -1022,6 +1161,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testIsNotPossibleNumber() { assertFalse(phoneUtil.isPossibleNumber(US_LONG_NUMBER)); + assertFalse(phoneUtil.isPossibleNumber(INTERNATIONAL_TOLL_FREE_TOO_LONG)); PhoneNumber number = new PhoneNumber(); number.setCountryCode(1).setNationalNumber(253000L); @@ -1030,20 +1170,16 @@ public class PhoneNumberUtilTest extends TestCase { number.clear(); number.setCountryCode(44).setNationalNumber(300L); assertFalse(phoneUtil.isPossibleNumber(number)); - assertFalse(phoneUtil.isPossibleNumber("+1 650 253 00000", RegionCode.US)); assertFalse(phoneUtil.isPossibleNumber("(650) 253-00000", RegionCode.US)); assertFalse(phoneUtil.isPossibleNumber("I want a Pizza", RegionCode.US)); assertFalse(phoneUtil.isPossibleNumber("253-000", RegionCode.US)); assertFalse(phoneUtil.isPossibleNumber("1 3000", RegionCode.GB)); assertFalse(phoneUtil.isPossibleNumber("+44 300", RegionCode.GB)); + assertFalse(phoneUtil.isPossibleNumber("+800 1234 5678 9", RegionCode.UN001)); } public void testTruncateTooLongNumber() { - // US number 650-253-0000, but entered with one additional digit at the end. - assertTrue(phoneUtil.truncateTooLongNumber(US_LONG_NUMBER)); - assertEquals(US_NUMBER, US_LONG_NUMBER); - // GB number 080 1234 5678, but entered with 4 extra digits at the end. PhoneNumber tooLongNumber = new PhoneNumber(); tooLongNumber.setCountryCode(44).setNationalNumber(80123456780123L); @@ -1060,6 +1196,17 @@ public class PhoneNumberUtilTest extends TestCase { 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)); @@ -1275,6 +1422,20 @@ public class PhoneNumberUtilTest extends TestCase { 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(); @@ -1407,6 +1568,7 @@ public class PhoneNumberUtilTest extends TestCase { public void testParseWithInternationalPrefixes() throws Exception { assertEquals(US_NUMBER, phoneUtil.parse("+1 (650) 253-0000", RegionCode.NZ)); + assertEquals(INTERNATIONAL_TOLL_FREE, phoneUtil.parse("011 800 1234 5678", RegionCode.US)); assertEquals(US_NUMBER, phoneUtil.parse("1-650-253-0000", RegionCode.US)); // Calling the US number from Singapore by using different service providers // 1st test: calling using SingTel IDD service (IDD is 001) @@ -1685,6 +1847,7 @@ public class PhoneNumberUtilTest extends TestCase { // 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)); // It is important that we set the carrier code to an empty string, since we used // ParseAndKeepRawInput and no carrier code was found. @@ -1839,6 +2002,8 @@ public class PhoneNumberUtilTest extends TestCase { // has been specified. assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH, phoneUtil.isNumberMatch("+64 3 331 6005", "+64 03 331 6005")); + assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH, + phoneUtil.isNumberMatch("+800 1234 5678", "+80012345678")); assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH, phoneUtil.isNumberMatch("+64 03 331-6005", "+64 03331 6005")); assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH, @@ -1886,6 +2051,8 @@ public class PhoneNumberUtilTest extends TestCase { // Non-matches. assertEquals(PhoneNumberUtil.MatchType.NO_MATCH, phoneUtil.isNumberMatch("03 331 6005", "03 331 6006")); + assertEquals(PhoneNumberUtil.MatchType.NO_MATCH, + phoneUtil.isNumberMatch("+800 1234 5678", "+1 800 1234 5678")); // Different country calling code, partial number match. assertEquals(PhoneNumberUtil.MatchType.NO_MATCH, phoneUtil.isNumberMatch("+64 3 331-6005", "+16433316005")); @@ -1993,12 +2160,15 @@ public class PhoneNumberUtilTest extends TestCase { // We have no data for NZ - should return true. assertTrue(phoneUtil.canBeInternationallyDialled(NZ_NUMBER)); + assertTrue(phoneUtil.canBeInternationallyDialled(INTERNATIONAL_TOLL_FREE)); } public void testIsAlphaNumber() throws Exception { assertTrue(phoneUtil.isAlphaNumber("1800 six-flags")); assertTrue(phoneUtil.isAlphaNumber("1800 six-flags ext. 1234")); + assertTrue(phoneUtil.isAlphaNumber("+800 six-flags")); assertFalse(phoneUtil.isAlphaNumber("1800 123-1234")); assertFalse(phoneUtil.isAlphaNumber("1800 123-1234 extension: 1234")); + assertFalse(phoneUtil.isAlphaNumber("+800 1234-1234")); } } diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java index 36e44e502..6b3a4e7a8 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java @@ -20,8 +20,11 @@ package com.google.i18n.phonenumbers; * Class containing string constants of region codes for easier testing. */ final class RegionCode { + // Region code for global networks (e.g. +800 numbers). + static final String UN001 = "001"; static final String AD = "AD"; static final String AO = "AO"; + static final String AQ = "AQ"; static final String AR = "AR"; static final String AU = "AU"; static final String BR = "BR"; diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800 b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800 new file mode 100644 index 000000000..e958189ae Binary files /dev/null and b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800 differ diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP index 6a1e5e054..97e1d0f6b 100644 Binary files a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP and b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP differ diff --git a/java/release_notes.txt b/java/release_notes.txt index ba1005bf1..4df4e8d94 100644 --- a/java/release_notes.txt +++ b/java/release_notes.txt @@ -1,3 +1,16 @@ +January 19th, 2012: libphonenumber-4.5 +* Code changes + - Support for non-geographical country calling codes (e.g. +800). + - Modify formatInOriginalFormat to not insert/remove/modify digits in the original number passed + in. + - Fix formatOutOfCountryKeepingAlphaChars to not throw a NPE. + +* Metadata changes + - Updates for AR, BH, CI, CN, CR, DE, GA, IL, JO, JP, KE, KZ, LB, LK, LT, MV, MW, MZ, NA, NL, NZ, + PL, RO, SA, SV, TM, UG, US + - New country calling codes: 800, 808, 883, 888, 979 + - Geocoding data updates: AR, US + December 9th, 2011: libphonenumber-4.4 * Code changes - Support for Voicemail numbers diff --git a/resources/PhoneNumberMetaData.xml b/resources/PhoneNumberMetaData.xml index 705a845b2..925e00a2a 100644 --- a/resources/PhoneNumberMetaData.xml +++ b/resources/PhoneNumberMetaData.xml @@ -42,7 +42,7 @@ - + @@ -72,7 +72,7 @@ - + @@ -804,8 +804,101 @@ + nationalPrefix="0" nationalPrefixForParsing=" + 0(?: + (11| + 2(?: + 2(?: + 02?| + [13]| + 2[13-79]| + 4[1-6]| + 5[2457]| + 6[124-8]| + 7[1-4]| + 8[13-6]| + 9[1-367] + )| + 3(?: + [06]2| + 1[467]| + 2[02-6]| + 3[13-8]| + [49][2-6]| + 5[2-8]| + 7 + )| + 47[3-578]| + 6(?: + [0136]| + 2[2-7]| + 4[6-8]?| + 5[15-8] + )| + 80| + 9(?: + 0[1-3]| + [19]| + 2\d| + 3[1-6]| + 4[024-68]?| + 5[2-4]| + 6[2-46]| + 72?| + 8[23]? + ) + )| + 3(?: + 3(?: + 2[79]| + 8[2578] + )| + 4(?: + 0[124-9]| + [12]| + 3[5-8]?| + 4[24-7]| + 5[4-68]?| + 6\d| + 7[126]| + 8[237-9]| + 9[1-36-8] + )| + 5(?: + 1| + 2[1245]| + 3[2-47]?| + 4[1-46-9]| + 6[2-4]| + 7[1-6]| + 8[2-5]? + )| + 6[24]| + 7(?: + 1[15-8]| + 2[125]| + 3[1245]| + 4[13]| + 5[14-8]| + [69]| + 7[2-57]| + 8[1-36] + )| + 8(?: + 1| + 2[125-7]| + 3[23578]| + 4[13-6]| + 5[4-8]?| + 6[1-357-9]| + 7[36-8]?| + 8[5-8]?| + 9[124] + ) + ) + )15 + )?" + nationalPrefixTransformRule="9$1" nationalPrefixFormattingRule="$NP$FG"> [68] @@ -817,10 +910,12 @@ $1 $2 $3-$4 + 9(?: - 2[2369]| - 3[458] + 2[23689]| + 3[4-8] ) @@ -828,76 +923,120 @@ 2(?: 2[013]| 37| - 6[14]| - 9[179] + 6[01346]| + 80| + 9[147-9] )| 3(?: 4[1235]| 5[138]| + 6[24]| + 7[69]| 8[1578] ) ) + + + 9(?: + 2(?: + 2[013]| + 37| + 6[01346]| + 80| + 9(?: + [17-9]| + 4[1379] + ) + )| + 3(?: + 4[1235]| + 5(?: + [18]| + 3[0-35689] + )| + 6[24]| + 7[69]| + 8(?: + [15]| + 7[0-24-9]| + 8[0-79] + ) + ) + ) + $2 15-$3-$4 $1 $2 $3-$4 - + + + 93[58] 9(?: - 2[2-469]| - 3[3-578] + 3(?: + 53| + 8[78] + ) ) 9(?: - 2(?: - 2[24-9]| - 3[0-69]| - 47| - 6[25]| - 9[02-68] - )| 3(?: - 3[28]| - 4[046-9]| - 5[2467]| - 7[1-578]| - 8[23469] + 537| + 8(?: + 73| + 88 + ) ) ) $2 15-$3-$4 + + + 9[23] + $2 15-$3-$4 $1 $2 $3-$4 1 $1 $2-$3 - + 2(?: 2[013]| 37| - 6[146]| + 6[01346]| 80| - 9[17-9] + 9[147-9] )| 3(?: 4[1235]| 5[138]| - 76| + 6[24]| + 7[69]| 8[1578] ) + 2(?: 2[013]| 37| - 6[146]| + 6[01346]| 80| - 9[17-9] + 9(?: + [17-9]| + 4[1379] + ) )| 3(?: 4[1235]| @@ -905,7 +1044,8 @@ [18]| 3[0-35689] )| - 76| + 6[24]| + 7[69]| 8(?: [15]| 7[0-24-9]| @@ -983,7 +1123,7 @@ [0124789]\d| 3[1-6]| 5[234]| - 6[2-6] + 6[2-46] ) )| 3(?: @@ -1005,10 +1145,11 @@ 6[2-4]| 7[1-6] )| + 6[24]\d| 7(?: - [12468]\d| + [124689]\d| 3[1245]| - 5[124-8]| + 5[14-8]| 7[2-57] )| 8(?: @@ -1026,6 +1167,9 @@ + 675\d{7}| 9(?: @@ -1034,12 +1178,15 @@ 2(?: 2[013]| 37| - 6[14]| - 9[179] + 6[01346]| + 80| + 9[147-9] )| 3(?: 4[1235]| 5[138]| + 6[24]| + 7[69]| 8[1578] ) )[2-9]\d{6}| @@ -1064,6 +1211,17 @@ \d{10} 8101234567 + + + 1(?: + 0[2356]| + 1[02-5]| + 21 + ) + + \d{3} + 121 + 1(?: @@ -2515,9 +2673,9 @@ 6(?: 1[16]\d| 6(?: - [06]\d + [06]\d| 3[03-9]| - 44| + 44 )| 9(?: 69| @@ -3870,14 +4028,14 @@ 21234567 - + (?: 0[1-9]| 4[04-9]| - 5[07-9]| - 6[0567] + 5[057-9]| + 6[05679] )\d{6} 01234567 @@ -4419,11 +4577,11 @@ \d{8} 16812345 - + 400\d{7} \d{10} 4001234567 - + 1(?: @@ -4550,7 +4708,7 @@ - [245]| + [24-7]| 8[3-9] $1 $2 @@ -4561,7 +4719,7 @@ - [24589]\d{7,9} + [24-9]\d{7,9} \d{8,10} @@ -4571,12 +4729,13 @@ + assigned.--> 5(?: - 0[0-4]\d{5}| - 7[01]\d[01]\d{3} - )| + 0[0-4]| + 7[01] + )\d{5}| + [67][01]\d{6}| 8[36-9]\d{6} \d{8} @@ -4602,6 +4761,7 @@ 00\d| 900 )\d{2}| + 3[01]\d{4}| 5\d{5} ) @@ -4632,10 +4792,12 @@ 333| 400| 55[15]| + 693| 7(?: 00| 1[78]| - 77 + 22| + [67]7 ) ) @@ -4973,6 +5135,7 @@ + @@ -5176,17 +5339,18 @@ 30123456 + 1(?: - 5\d{9}| + 5[0-2579]\d{8}| + 6[023]\d{7,8}| 7(?: - [0-57-9]| + [0-57-9]\d?| 6\d - )\d{7}| - 6(?: - [02]\d{7,8}| - 3\d{7} - ) + )\d{7} ) \d{10,11} @@ -6638,11 +6802,13 @@ - + - - [4-9] - $1 $2 $3 + + [12] + $1 $2 $3 $4 0 @@ -6651,33 +6817,41 @@ - [4-9]\d{5}| + [12]\d{6}| 0\d{7} \d{6,8} + (?: - 4(?: - [04-8]\d| - 2[04] + 1(?: + 4[4-8]| + 7\d )| - (?: + 2(?: + 4[02]| 5[04-689]| - 6[024-9]| - 7\d| + 6[024-79]| 8[236]| 9[02368] - )\d - )\d{3} + ) + )\d{4} - \d{6} - 441234 + \d{6,7} + 1441234 - + + @@ -9408,7 +9584,20 @@ 21234567 - 5[024679]\d{7} + + 5(?: + [0246-9]\d{2}| + 5(?: + 22| + 33| + 44| + 5[58]| + 66| + 77| + 88 + ) + )\d{5} + \d{9} 501234567 @@ -11099,18 +11288,20 @@ - [2356] + [2356]| + 87 $1 $2 $3 - + 7[457-9] - $1 $2 $3 $4 $5 + $1 $2 $3 70| - [89] + 8[0158]| + 9 $1 $2 @@ -11120,22 +11311,44 @@ \d{7,9} - - [2356][2-8]\d{6} + + (?: + 2[67]| + 32| + 53| + 6[2-5]| + 87 + )\d{6} + \d{7,8} 62001234 + + 7(?: - [1-8]\d| - 9[02-9] + 45| + 5\d| + 7[2-79]| + 8[5-8]| + 9[035-9] )\d{6} \d{9} 790123456 + + + 74(?: + 66| + 77 + )\d{5} + + \d{9} + 746612345 + 80\d{6} \d{8} @@ -11162,15 +11375,29 @@ 8(?: 10| - [78]\d + 8\d )\d{5} \d{8} - 87101234 + 88101234 + + + 1(?: + 09| + 1[01]| + 9[024-79] + ) + + \d{3} + 111 + - 112| + 1(?: + 12| + 91 + )| 911 \d{3} @@ -11199,8 +11426,8 @@ 800 $1-$2-$3 - + 077 $1-$2 @@ -11213,6 +11440,10 @@ 088 $1-$2-$3 + + 037 + $1-$2-$3 + 0(?: + 37\d{8}| 777(?: [01]\d{2}| 5\d{3}| @@ -11999,7 +12232,7 @@ 882[1245]\d{4} ) - \d{7,9} + \d{7,11} 0777012 @@ -12078,6 +12311,7 @@ 882[1245]\d{4} ) + \d{7,10} 120123456 @@ -12091,8 +12325,13 @@ 601234567 - 50\d{8} - \d{10} + + (?: + 037| + 50 + )\d{8} + + \d{10,11} 5012345678 @@ -12146,12 +12385,12 @@ 202012345 - + 7(?: 0[0-5]| [123]\d| - 5[0-3]| + 5[0-4]| 7[0-5]| 8[6-9] )\d{6} @@ -13127,8 +13366,7 @@ 59 )| 6(?: - 2\d| - [34]\d| + [234]\d| 5[19]| 61 )| @@ -13136,7 +13374,7 @@ 8(?: [27]\d| 3[1-46-9]| - 4[0-5]| + 4[0-5] ) )| 2(?: @@ -13149,11 +13387,11 @@ 2\d| 3[0679]| 46| - 5[12679]| + 5[12679] )| 3(?: [234]\d| - 5[139]| + 5[139] )| 4(?: 2\d| @@ -13199,7 +13437,7 @@ 7(?: 0[01257]| 6[02-4]| - 7[157] + 7[1578] )\d{7} 7710009998 @@ -13285,9 +13523,9 @@ + nationalPrefix="0"> - + [13-6]| 7(?: @@ -13302,7 +13540,7 @@ [89][01]| 7(?: [01]| - 6[136-9]) + 6[01346-9]) $1 $2 $3 @@ -13330,7 +13568,7 @@ 3\d| 7(?: [01]\d| - 6[136-9] + 6[01346-9] ) )\d{5} @@ -13648,7 +13886,8 @@ 112345678 - 7[12578]\d{7} + + 7[125-8]\d{7} \d{9} 712345678 @@ -13778,10 +14017,11 @@ + nationalPrefix="8" nationalPrefixFormattingRule="($NP-$FG)"> + - + 37| 4(?: @@ -13790,25 +14030,27 @@ 6[2-4] ) - $1 $2 $3 $4 + $1 $2 - + 3[148]| 4(?: [24]| 6[09] )| - 5(?: - [0189]| - 28 - )| - [6-9] + 528| + 6 + $1 $2 + + + [7-9] $1 $2 $3 - + 52[0-79] $1 $2 $3 @@ -15579,7 +15821,7 @@ - [367]| + [3467]| 9(?: [1-9]| 0[1-9] @@ -15594,7 +15836,7 @@ - [367]\d{6}| + [3467]\d{6}| 9(?: 00\d{7}| \d{6} @@ -15622,12 +15864,14 @@ 6701234 - + (?: - 7[3-9]| - 9[6-9] - )\d{5} + 46[46]| + 7[3-9]\d| + 9[6-9]\d + )\d{4} \d{7} 7712345 @@ -15679,24 +15923,27 @@ 2 $1 $2 $3 - - 7 - $1 $2 $3 + + [1789] + $1 $2 $3 $4 - + + [89] $1 $2 $3 + websites. Recent information provided by ITU stated that final migration happened on 30th + November 2011, and from December 1st only the 9-digit plan will be in use. We will delete + the old-format numbers in January 2010. --> (?: - [13-5]| + [3-5]| [27]\d{2}| - [89](?: + [189](?: \d{2} )? )\d{6} @@ -15704,6 +15951,9 @@ \d{7,9} + (?: 1[2-9]| @@ -15715,11 +15965,12 @@ (?: + 111| [3-5]| - 77| + 77\d| 8(?: 8\d - )? | + )?| 9(?: 9\d )? @@ -16068,7 +16319,7 @@ 2| - 8[24] + 8[246] $1 $2 $3 @@ -16094,7 +16345,7 @@ 21123456 - 8[24]\d{7} + 8[246]\d{7} \d{9} 821234567 @@ -16108,6 +16359,11 @@ + + 1[0234]\d + \d{3} + 101 + @@ -16129,7 +16385,7 @@ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG"> - 8[125] + 8[1235] $1 $2 $3 @@ -16260,8 +16516,13 @@ 870123456 - 886\d{5} - \d{8} + + + 8( + 3\d{2}| + 86 + )\d{5} + 88612345 @@ -16597,7 +16858,7 @@ - + @@ -16624,7 +16885,15 @@ $1 $2 $3 - 6 + 6[0-57-9] + $1 $2 + + + 66 + $1 $2 + + + 14 $1 $2 @@ -16636,9 +16905,17 @@ - [1-9]\d{6,9} - \d{7,10} + + 1\d{4,8}| + [2-7]\d{8}| + [89]\d{6,9} + + \d{5,10} + + 14\d{3,4} + \d{5,6} + (?: @@ -16658,6 +16935,11 @@ \d{9} 612345678 + + 66\d{7} + \d{9} + 662345678 + 800\d{4,7} \d{7,10} @@ -16671,7 +16953,45 @@ 85\d{7} \d{9} + 851234567 + + + + 140(?: + 1(?: + [035]| + [16-8]\d + )| + 2(?: + [0346]| + [259]\d + )| + 3(?: + [03568]| + [124]\d + )| + 4(?: + [0356]| + [17-9]\d + )| + 5(?: + [0358]| + [124679]\d + )| + 7\d| + 8[458] + ) + + \d{5,6} + 14020 + + + 18\d{2} + \d{4} + 1833 + 112| @@ -16953,8 +17273,18 @@ 21 $1 $2 $3 - + + + 22 + $1 $2 $3 + + + 2[0247-9]| 5| @@ -17954,6 +18284,7 @@ + @@ -18026,7 +18357,7 @@ 7[14-6]| 8[1-7] )\d{5,7}| - 77\d{4,6}| + 77\d{4,7}| (?: 89| 9[145] @@ -18699,6 +19030,13 @@ 802\d{6} 802123456 + + + 37\d{7} + 372123456 + 112 \d{3} @@ -18998,10 +19336,10 @@ \d{7,11} + (?: - 1[24-7]| - 2[24-8]| + [12][24-8]| 3[35-8]| 4[34-68]| 6[2-5]| @@ -19032,6 +19370,20 @@ \d{11} 92001234567 + + + 9( + 0[24-79]| + 33| + 40| + 66| + 8[59]| + 9[02-6] + ) + + \d{3} + 902 + 99[7-9] \d{3} @@ -20229,7 +20581,7 @@ - [27] + [267] $1 $2 @@ -20243,7 +20595,7 @@ - [27]\d{7}| + [267]\d{7}| [89]\d{6}(?:\d{4})? @@ -20258,7 +20610,7 @@ 21234567 - 7\d{7} + [67]\d{7} \d{8} 70123456 @@ -20917,15 +21269,28 @@ + + nationalPrefixFormattingRule="($NP $FG)"> - - $1 $2 $3 $4 + + 12 + $1 $2-$3-$4 + + + 6 + $1 $2 + + + + 13| + [2-5] + + $1 $2-$3-$4 @@ -20933,18 +21298,42 @@ \d{8} + (?: - 12\d| - 243| - [3-5]22 + 1(?: + 2\d| + 3[1-9] + )| + 2(?: + 22| + 4[0-35-8] + )| + 3(?: + 22| + 4[03-9] + )| + 4(?: + 22| + 3[128]| + 4\d| + 6[15] + )| + 5(?: + 22| + 5[7-9]| + 6[014-689] + ) )\d{5} 12345678 - - 6[6-8]\d{6} + + 6[3-8]\d{6} 66123456 @@ -21635,7 +22024,7 @@ [7-9]| 20(?: - 0| + [013-5]| 2[5-9] )| 4(?: @@ -21647,7 +22036,6 @@ - 204| 3| 4(?: [1-5]| @@ -21666,6 +22054,7 @@ \d{5,9} + 20(?: [014]\d{2}| @@ -21673,20 +22062,25 @@ 40| [5-9]\d )| - 3[23]| - 4\d + 3[23]\d| + 5[0-4]\d )\d{4}| [34]\d{8} + \d{5,9} 312345678 + 7(?: 0[0-7]| - [15789]\d + [15789]\d| + 20| + [46][0-4] )\d{6} \d{9} @@ -21790,7 +22184,7 @@ 3[016]| 4[16]| 5[017]| - 6[0-29]| + 6[0-279]| 78| 8[12] )| @@ -21823,7 +22217,7 @@ 4[0179]| 5[1246]| 7[0-3589]| - 8[059] + 8[0459] ) )[2-9]\d{6} @@ -21882,7 +22276,7 @@ 3[016]| 4[16]| 5[017]| - 6[0-29]| + 6[0-279]| 78| 8[12] )| @@ -21915,7 +22309,7 @@ 4[0179]| 5[1246]| 7[0-3589]| - 8[059] + 8[0459] ) )[2-9]\d{6} @@ -23602,5 +23996,148 @@ 999 + + + + + + + $1 $2 + + + + \d{8} + \d{8} + 12345678 + + + NA + NA + + + NA + NA + + + \d{8} + + + + + + + + + $1 $2 + + + + \d{8} + \d{8} + 12345678 + + + NA + NA + + + NA + NA + + + \d{8} + + + + + + + + + $1 $2 $3 + + + $1 $2 $3 $4 + + + + + 51\d{7}(?:\d{3})? + \d{9}(?:\d{3})? + 510012345 + + + NA + NA + + + NA + NA + + + + 51(?: + 00\d{5}(?:\d{3})?| + 10\d{8} + ) + + + + + + + + + + + $1 $2 $3 + + + + \d{11} + \d{11} + 12345678901 + + + NA + NA + + + NA + NA + + + \d{11} + + + + + + + + + $1 $2 $3 + + + + \d{9} + \d{9} + 123456789 + + + NA + NA + + + NA + NA + + + \d{9} + + diff --git a/resources/PhoneNumberMetaDataForTesting.xml b/resources/PhoneNumberMetaDataForTesting.xml index 56e207c8c..a18e41f56 100644 --- a/resources/PhoneNumberMetaDataForTesting.xml +++ b/resources/PhoneNumberMetaDataForTesting.xml @@ -335,7 +335,7 @@ patterns as digits beyond the third one are entered. As a result, only a few fake formatting rules are added. --> + nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG" leadingZeroPossible="true"> [57-9]0 @@ -362,6 +362,10 @@ [23] $1 $2 $3 + + 077 + $1-$2 + @@ -373,6 +377,15 @@ [23]\d{3} \d{4} + + 07\d{5}|[1-357-9]\d{3,10} + \d{4,11} + + + 0777[01]\d{2} + \d{7} + 0777012 + @@ -753,5 +766,30 @@ 801234567 + + + + + + $1 $2 + + + + \d{8} + \d{8} + 12345678 + + + NA + NA + + + NA + NA + + + \d{8} + + diff --git a/resources/geocoding/en/1.txt b/resources/geocoding/en/1.txt index 26445af6e..29e41f75c 100644 --- a/resources/geocoding/en/1.txt +++ b/resources/geocoding/en/1.txt @@ -14123,6 +14123,7 @@ 1662963|Nettleton, MS 1662983|Bruce, MS 1662993|Ripley, MS +1667|Maryland 1678|Georgia 1678339|Alpharetta, GA 1678493|Canton, GA @@ -23247,6 +23248,7 @@ 1979968|La Grange, TX 1980|North Carolina 1980207|Charlotte, NC +1984|North Carolina 1985|Louisiana 1985223|Houma, LA 1985229|Kentwood, LA diff --git a/resources/geocoding/en/54.txt b/resources/geocoding/en/54.txt index 85e29beb5..de1d7e372 100644 --- a/resources/geocoding/en/54.txt +++ b/resources/geocoding/en/54.txt @@ -89,16 +89,19 @@ 542475|Rojas, Buenos Aires 542477|Pergamino 542478|Arrecifes, Buenos Aires +54260|San Rafael 54261|Mendoza, Capital 542622|Tunuyán, Mendoza 542623|San Martin 542625|General Alvear, Mendoza 542627|San Rafael +54263|San Martin 54264|San Juan, Capital 542646|Valle Fértil -542652|San Luis, La Capital 542656|Merlo, San Luis 542657|Villa Mercedes, General Pedernera +54266|San Luis, La Capital +54280|Trelew, Rawson 542901|Ushuaia 542902|El Calafate, Lago Argentino 54291|Bahía Blanca @@ -114,21 +117,22 @@ 542932|Punta Alta, Buenos Aires 542934|San Antonio Oeste, Río Negro 542936|Buenos Aires Province -542941|Confluencia +54294|San Carlos de Bariloche, Río Negro +542940|Ingeniero Jacobacci, Río Negro 542942|Zapala 542944|San Carlos de Bariloche, Río Negro 542945|Esquel, Futaleufú -542946|Choele-choel, Río Negro +542946|Choele Choel, Río Negro 542948|Chos Malal, Neuquén 542952|General Acha, La Pampa 542953|Macachín, La Pampa 542954|Santa Rosa, La Pampa 542962|Puerto San Julián, Santa Cruz 542964|Río Grande -542965|Trelew, Rawson 542966|Río Gallegos, Ger Aike 54297|Comodoro Rivadavia, Escalante 542972|San Martín de los Andes +54298|General Roca, Río Negro 542983|Tres Arroyos 54299|Neuquén, Confluencia 543327|López Camelo, Buenos Aires @@ -193,6 +197,8 @@ 543573|Villa del Rosario, Córdoba 543576|Córdoba 54358|Río Cuarto +54362|Resistencia, San Fernando +54364|Presidencia Roque Sáenz Pena, Chaco 543717|Formosa 543718|Clorinda, Formosa 543722|Resistencia, San Fernando @@ -203,18 +209,19 @@ 543735|Villa Angela, Mayor Luis Fonta 543743|Puerto Rico, Misiones 543751|El Dorado, Misiones -543752|Posadas, Capital 543754|Leandro N. Alem, Misiones 543755|Oberá, Misiones 543756|Santo Tomé, Corrientes 543757|Puerto Iguazú, Misiones 543758|Apóstoles, Misiones +54376|Posadas, Capital 543772|Paso de Los Libres, Corrientes/Resistencia 543773|Mercedes, Corrientes 543774|Curuzú Cuatiá, Corrientes 543775|Monte Caseros, Corrientes 543777|Goya, Corrientes 543783|Corrientes, Capital +54379|Corrientes, Capital 54381|San Miguel de Tucumán, Capital 543822|La Rioja, Capital 543825|Chilecito, La Rioja diff --git a/resources/geocoding/es/54.txt b/resources/geocoding/es/54.txt index 41a185ead..64721d6fa 100644 --- a/resources/geocoding/es/54.txt +++ b/resources/geocoding/es/54.txt @@ -91,16 +91,19 @@ 542475|Rojas, Buenos Aires 542477|Pergamino 542478|Arrecifes, Buenos Aires +54260|San Rafael 54261|Mendoza, Capital 542622|Tunuyán, Mendoza 542623|San Martin 542625|General Alvear, Mendoza 542627|San Rafael +54263|San Martin 54264|San Juan, Capital 542646|Valle Fértil -542652|San Luis, La Capital 542656|Merlo, San Luis 542657|Villa Mercedes, General Pedernera +54266|San Luis, La Capital +54280|Trelew, Rawson 542901|Ushuaia 542902|El Calafate, Lago Argentino 54291|Bahía Blanca @@ -116,21 +119,22 @@ 542932|Punta Alta, Buenos Aires 542934|San Antonio Oeste, Río Negro 542936|Buenos Aires -542941|Confluencia +54294|San Carlos de Bariloche, Río Negro +542940|Ingeniero Jacobacci, Río Negro 542942|Zapala 542944|San Carlos de Bariloche, Río Negro 542945|Esquel, Futaleufú -542946|Choele-choel, Río Negro +542946|Choele Choel, Río Negro 542948|Chos Malal, Neuquén 542952|General Acha, La Pampa 542953|Macachín, La Pampa 542954|Santa Rosa, La Pampa 542962|Puerto San Julián, Santa Cruz 542964|Río Grande -542965|Trelew, Rawson 542966|Río Gallegos, Ger Aike 54297|Comodoro Rivadavia, Escalante 542972|San Martín de los Andes +54298|General Roca, Río Negro 542983|Tres Arroyos 54299|Neuquén, Confluencia 543327|López Camelo, Buenos Aires @@ -195,6 +199,8 @@ 543573|Villa del Rosario, Córdoba 543576|Córdoba 54358|Río Cuarto +54362|Resistencia, San Fernando +54364|Presidencia Roque Sáenz Pena, Chaco 543717|Formosa 543718|Clorinda, Formosa 543722|Resistencia, San Fernando @@ -205,18 +211,19 @@ 543735|Villa Angela, Mayor Luis Fonta 543743|Puerto Rico, Misiones 543751|El Dorado, Misiones -543752|Posadas, Capital 543754|Leandro N. Alem, Misiones 543755|Oberá, Misiones 543756|Santo Tomé, Corrientes 543757|Puerto Iguazú, Misiones 543758|Apóstoles, Misiones +54376|Posadas, Capital 543772|Paso de Los Libres, Corrientes/Resistencia 543773|Mercedes, Corrientes 543774|Curuzú Cuatiá, Corrientes 543775|Monte Caseros, Corrientes 543777|Goya, Corrientes 543783|Corrientes, Capital +54379|Corrientes, Capital 54381|San Miguel de Tucumán, Capital 543822|La Rioja, Capital 543825|Chilecito, La Rioja diff --git a/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java b/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java index 42b5db4bf..eb761496d 100644 --- a/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java +++ b/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java @@ -183,7 +183,7 @@ public class BuildMetadataFromXml { } if (element.hasAttribute(NATIONAL_PREFIX_FOR_PARSING)) { metadata.setNationalPrefixForParsing( - validateRE(element.getAttribute(NATIONAL_PREFIX_FOR_PARSING))); + validateRE(element.getAttribute(NATIONAL_PREFIX_FOR_PARSING), true)); if (element.hasAttribute(NATIONAL_PREFIX_TRANSFORM_RULE)) { metadata.setNationalPrefixTransformRule( validateRE(element.getAttribute(NATIONAL_PREFIX_TRANSFORM_RULE))); diff --git a/tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar b/tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar index 394bc7f4a..23c7ea9e0 100644 Binary files a/tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar and b/tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java index 094a892ab..4b0b902cb 100644 --- a/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java @@ -102,6 +102,11 @@ public class BuildMetadataProtoFromXml extends Command { for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { String regionCode = metadata.getId(); + // For non-geographical country calling codes (e.g. +800), use the country calling codes + // instead of the region code to form the file name. + if (regionCode.equals("001")) { + regionCode = Integer.toString(metadata.getCountryCode()); + } PhoneMetadataCollection outMetadataCollection = new PhoneMetadataCollection(); outMetadataCollection.addMetadata(metadata); FileOutputStream outputForRegion = new FileOutputStream(filePrefix + "_" + regionCode); diff --git a/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar b/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar index 08e7e8e3a..7a19ac668 100644 Binary files a/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar and b/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar differ