Browse Source

JAVA/CPP: Release 5.2. Metadata updates and bug fixes. See release notes for more details.

pull/567/head
David Beaumont 13 years ago
committed by Mihaela Rosca
parent
commit
18d6eae899
33 changed files with 21871 additions and 21581 deletions
  1. +1
    -1
      cpp/CMakeLists.txt
  2. +9976
    -9984
      cpp/src/phonenumbers/lite_metadata.cc
  3. +11213
    -11221
      cpp/src/phonenumbers/metadata.cc
  4. +75
    -43
      cpp/src/phonenumbers/phonenumberutil.cc
  5. +17
    -4
      cpp/src/phonenumbers/phonenumberutil.h
  6. +23
    -23
      cpp/src/phonenumbers/test_metadata.cc
  7. +93
    -4
      cpp/test/phonenumbers/phonenumberutil_test.cc
  8. +8
    -0
      debian/changelog
  9. +5
    -0
      java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java
  10. BIN
      java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/30_el
  11. BIN
      java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/30_en
  12. +1
    -2
      java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
  13. +128
    -49
      java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
  14. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN
  15. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE
  16. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR
  17. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR
  18. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM
  19. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB
  20. BIN
      java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA
  21. +39
    -5
      java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
  22. BIN
      java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800
  23. +15
    -0
      java/release_notes.txt
  24. +55
    -79
      resources/PhoneNumberMetaData.xml
  25. +1
    -1
      resources/PhoneNumberMetaDataForTesting.xml
  26. +7
    -4
      resources/geocoding/el/30.txt
  27. +89
    -83
      resources/geocoding/en/30.txt
  28. BIN
      tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar
  29. +62
    -0
      tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/AbstractAreaCodeDataIOHandler.java
  30. +59
    -0
      tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/AreaCodeDataIOHandler.java
  31. +3
    -38
      tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/GenerateAreaCodeData.java
  32. +1
    -40
      tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/GenerateAreaCodeDataEntryPoint.java
  33. BIN
      tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar

+ 1
- 1
cpp/CMakeLists.txt View File

@ -18,7 +18,7 @@ cmake_minimum_required (VERSION 2.8)
project (libphonenumber)
set (libphonenumber_VERSION_MAJOR 5)
set (libphonenumber_VERSION_MINOR 1)
set (libphonenumber_VERSION_MINOR 2)
# Helper functions dealing with finding libraries and programs this library
# depends on.


+ 9976
- 9984
cpp/src/phonenumbers/lite_metadata.cc
File diff suppressed because it is too large
View File


+ 11213
- 11221
cpp/src/phonenumbers/metadata.cc
File diff suppressed because it is too large
View File


+ 75
- 43
cpp/src/phonenumbers/phonenumberutil.cc View File

@ -811,12 +811,12 @@ void PhoneNumberUtil::GetNddPrefixForRegion(const string& region_code,
bool strip_non_digits,
string* national_prefix) const {
DCHECK(national_prefix);
if (!IsValidRegionCode(region_code)) {
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
if (!metadata) {
LOG(WARNING) << "Invalid or unknown region code (" << region_code
<< ") provided.";
return;
}
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
national_prefix->assign(metadata->national_prefix());
if (strip_non_digits) {
// Note: if any other non-numeric symbols are ever used in national
@ -841,7 +841,8 @@ bool PhoneNumberUtil::HasValidCountryCallingCode(
target_pair, OrderByFirst()));
}
// Returns a pointer to the phone metadata for the appropriate region.
// Returns a pointer to the phone metadata for the appropriate region or NULL
// if the region code is invalid or unknown.
const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegion(
const string& region_code) const {
map<string, PhoneMetadata>::const_iterator it =
@ -870,6 +871,11 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
if (number.national_number() == 0) {
const string& raw_input = number.raw_input();
if (!raw_input.empty()) {
// Unparseable numbers that kept their raw input just use that.
// This is the only case where a number can be formatted as E164 without a
// leading '+' symbol (but the original number wasn't parseable anyway).
// TODO: Consider removing the 'if' above so that unparseable
// strings without raw input format to the empty string instead of "+00".
formatted_number->assign(raw_input);
return;
}
@ -878,23 +884,27 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
if (number_format == E164) {
// Early exit for E164 case since no formatting of the national number needs
// to be applied. Extensions are not formatted.
// Early exit for E164 case (even if the country calling code is invalid)
// since no formatting of the national number needs to be applied.
// Extensions are not formatted.
formatted_number->assign(national_significant_number);
PrefixNumberWithCountryCallingCode(country_calling_code, E164,
formatted_number);
return;
}
if (!HasValidCountryCallingCode(country_calling_code)) {
formatted_number->assign(national_significant_number);
return;
}
// Note here that all NANPA formatting rules are contained by US, so we use
// that to format NANPA numbers. The same applies to Russian Fed regions -
// rules are contained by Russia. French Indian Ocean country rules are
// contained by Réunion.
string region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code);
if (!HasValidCountryCallingCode(country_calling_code)) {
formatted_number->assign(national_significant_number);
return;
}
// Metadata cannot be NULL because the country calling code is valid (which
// means that the region code cannot be ZZ and must be one of our supported
// region codes).
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
FormatNsn(national_significant_number, *metadata, number_format,
@ -916,14 +926,15 @@ void PhoneNumberUtil::FormatByPattern(
// for regions which 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 region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code);
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
if (!HasValidCountryCallingCode(country_calling_code)) {
formatted_number->assign(national_significant_number);
return;
}
string region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code);
// Metadata cannot be NULL because the country calling code is valid.
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
const NumberFormat* formatting_pattern =
@ -971,15 +982,18 @@ void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
int country_calling_code = number.country_code();
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
if (!HasValidCountryCallingCode(country_calling_code)) {
formatted_number->assign(national_significant_number);
return;
}
// Note GetRegionCodeForCountryCode() is used because formatting information
// for regions which 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 region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code);
if (!HasValidCountryCallingCode(country_calling_code)) {
formatted_number->assign(national_significant_number);
}
// Metadata cannot be NULL because the country calling code is valid.
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
FormatNsnWithCarrier(national_significant_number, *metadata, NATIONAL,
@ -1111,10 +1125,7 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
Format(number, NATIONAL, formatted_number);
return;
}
string region_code;
GetRegionCodeForCountryCode(country_code, &region_code);
const PhoneMetadata* metadata_for_region =
GetMetadataForRegionOrCallingCode(country_code, region_code);
// Metadata cannot be NULL because we checked 'IsValidRegionCode()' above.
const PhoneMetadata* metadata_calling_from =
GetMetadataForRegion(calling_from);
const string& international_prefix =
@ -1126,6 +1137,12 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
reg_exps_->unique_international_prefix_->FullMatch(international_prefix)
? international_prefix
: metadata_calling_from->preferred_international_prefix());
string region_code;
GetRegionCodeForCountryCode(country_code, &region_code);
// Metadata cannot be NULL because the country_code is valid.
const PhoneMetadata* metadata_for_region =
GetMetadataForRegionOrCallingCode(country_code, region_code);
FormatNsn(national_significant_number, *metadata_for_region, INTERNATIONAL,
formatted_number);
MaybeAppendFormattedExtension(number, *metadata_for_region, INTERNATIONAL,
@ -1193,6 +1210,8 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
Format(number, NATIONAL, formatted_number);
break;
}
// Metadata cannot be NULL here because GetNddPrefixForRegion() (above)
// leaves the prefix empty if there is no metadata for the region.
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
string national_number;
GetNationalSignificantNumber(number, &national_number);
@ -1201,6 +1220,14 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
const NumberFormat* format_rule =
ChooseFormattingPatternForNumber(metadata->number_format(),
national_number);
// The format rule could still be NULL here if the national number was 0
// and there was no raw input (this should not be possible for numbers
// generated by the phonenumber library as they would also not have a
// country calling code and we would have exited earlier).
if (!format_rule) {
Format(number, NATIONAL, formatted_number);
break;
}
// 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
@ -1230,14 +1257,15 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
// 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.
if (!formatted_number->empty()) {
string formatted_number_copy(*formatted_number);
if (!formatted_number->empty() && !number.raw_input().empty()) {
string normalized_formatted_number(*formatted_number);
NormalizeHelper(reg_exps_->diallable_char_mappings_,
true /* remove non matches */, &formatted_number_copy);
string raw_input_copy(number.raw_input());
true /* remove non matches */,
&normalized_formatted_number);
string normalized_raw_input(number.raw_input());
NormalizeHelper(reg_exps_->diallable_char_mappings_,
true /* remove non matches */, &raw_input_copy);
if (formatted_number_copy != raw_input_copy) {
true /* remove non matches */, &normalized_raw_input);
if (normalized_formatted_number != normalized_raw_input) {
formatted_number->assign(number.raw_input());
}
}
@ -1331,7 +1359,7 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
StrAppend(formatted_number, country_code, " ", raw_input_copy);
return;
}
} else if (IsValidRegionCode(calling_from) &&
} else if (metadata &&
country_code == GetCountryCodeForValidRegion(calling_from)) {
const NumberFormat* formatting_pattern =
ChooseFormattingPatternForNumber(metadata->number_format(),
@ -1603,6 +1631,8 @@ void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList(
GetNationalSignificantNumber(number, &national_number);
for (list<string>::const_iterator it = region_codes.begin();
it != region_codes.end(); ++it) {
// Metadata cannot be NULL because the region codes come from the country
// calling code map.
const PhoneMetadata* metadata = GetMetadataForRegion(*it);
if (metadata->has_leading_digits()) {
const scoped_ptr<RegExpInput> number(
@ -1966,6 +1996,7 @@ PhoneNumberUtil::ValidationResult PhoneNumberUtil::IsPossibleNumberWithReason(
}
string region_code;
GetRegionCodeForCountryCode(country_code, &region_code);
// Metadata cannot be NULL because the country calling code is valid.
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_code, region_code);
const PhoneNumberDesc& general_num_desc = metadata->general_desc();
@ -2008,14 +2039,13 @@ PhoneNumberUtil::PhoneNumberType PhoneNumberUtil::GetNumberType(
const PhoneNumber& number) const {
string region_code;
GetRegionCodeForNumber(number, &region_code);
if (!IsValidRegionCode(region_code) &&
kRegionCodeForNonGeoEntity != region_code) {
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(number.country_code(), region_code);
if (!metadata) {
return UNKNOWN;
}
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(number.country_code(), region_code);
return GetNumberTypeHelper(national_significant_number,
*metadata,
reg_exps_->regexp_cache_.get());
@ -2057,11 +2087,20 @@ bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number,
reg_exps_->regexp_cache_.get()) != UNKNOWN;
}
bool PhoneNumberUtil::IsNumberGeographical(
const PhoneNumber& phone_number) const {
PhoneNumberType number_type = GetNumberType(phone_number);
// TODO: Include mobile phone numbers from countries like
// Indonesia, which has some mobile numbers that are geographical.
return number_type == PhoneNumberUtil::FIXED_LINE ||
number_type == PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
}
bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const {
string region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code);
const PhoneMetadata* main_metadata_for_calling_code = GetMetadataForRegion(
region_code);
const PhoneMetadata* main_metadata_for_calling_code =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
if (!main_metadata_for_calling_code) return false;
return main_metadata_for_calling_code->leading_zero_possible();
}
@ -2080,11 +2119,10 @@ int PhoneNumberUtil::GetLengthOfGeographicalAreaCode(
const PhoneNumber& number) const {
string region_code;
GetRegionCodeForNumber(number, &region_code);
if (!IsValidRegionCode(region_code)) {
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
if (!metadata) {
return 0;
}
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
DCHECK(metadata);
// If a country doesn't use a national prefix, and this number doesn't have an
// Italian leading zero, we assume it is a closed dialling plan with no area
// codes.
@ -2092,13 +2130,7 @@ int PhoneNumberUtil::GetLengthOfGeographicalAreaCode(
return 0;
}
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
PhoneNumberType type = GetNumberTypeHelper(national_significant_number,
*metadata,
reg_exps_->regexp_cache_.get());
// Most numbers other than the two types below have to be dialled in full.
if (type != FIXED_LINE && type != FIXED_LINE_OR_MOBILE) {
if (!IsNumberGeographical(number)) {
return 0;
}
@ -2657,12 +2689,12 @@ bool PhoneNumberUtil::CanBeInternationallyDialled(
const PhoneNumber& number) const {
string region_code;
GetRegionCodeForNumber(number, &region_code);
if (!IsValidRegionCode(region_code)) {
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
if (!metadata) {
// Note numbers belonging to non-geographical entities (e.g. +800 numbers)
// are always internationally diallable, and will be caught here.
return true;
}
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
string national_significant_number;
GetNationalSignificantNumber(number, &national_significant_number);
return !IsNumberMatchingDesc(


+ 17
- 4
cpp/src/phonenumbers/phonenumberutil.h View File

@ -157,6 +157,14 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// for.
void GetSupportedRegions(set<string>* regions) const;
// Populates a list with the region codes that match the specific country
// calling code. For non-geographical country calling codes, the region code
// 001 is returned. Also, in the case of no region code being found, the list
// is left unchanged.
void GetRegionCodesForCountryCallingCode(
int country_calling_code,
list<string>* region_codes) const;
// Gets a PhoneNumberUtil instance to carry out international phone number
// formatting, parsing, or validation. The instance is loaded with phone
// number metadata for a number of most commonly used regions, as specified by
@ -383,6 +391,10 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// are examined.
// This is useful for determining for example whether a particular number is
// valid for Canada, rather than just a valid NANPA number.
// Warning: In most cases, you want to use IsValidNumber instead. For
// example, this method will mark numbers from British Crown dependencies
// such as the Isle of Man as invalid for the region "GB" (United Kingdom),
// since it has its own region code, "IM", which may be undesirable.
bool IsValidNumberForRegion(
const PhoneNumber& number,
const string& region_code) const;
@ -645,6 +657,11 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// Trims unwanted end characters from a phone number string.
void TrimUnwantedEndChars(string* number) const;
// Tests whether a phone number has a geographical association. It checks if
// the number is associated to a certain region in the country where it
// belongs to. Note that this doesn't verify if the number is actually in use.
bool IsNumberGeographical(const PhoneNumber& phone_number) const;
// Helper function to check region code is not unknown or null.
bool IsValidRegionCode(const string& region_code) const;
@ -665,10 +682,6 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// has already been checked.
int GetCountryCodeForValidRegion(const string& region_code) const;
void GetRegionCodesForCountryCallingCode(
int country_calling_code,
list<string>* region_codes) const;
const NumberFormat* ChooseFormattingPatternForNumber(
const RepeatedPtrField<NumberFormat>& available_formats,
const string& national_number) const;


+ 23
- 23
cpp/src/phonenumbers/test_metadata.cc View File

@ -756,7 +756,7 @@ static const unsigned char data[] = {
0x33, 0x39, 0xC2, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41,
0xCA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xDA, 0x01,
0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xE2, 0x01, 0x08, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x0A, 0xE8, 0x01, 0x0A, 0x18, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x0A, 0xEB, 0x01, 0x0A, 0x18, 0x12,
0x05, 0x5C, 0x64, 0x7B, 0x38, 0x7D, 0x1A, 0x05, 0x5C, 0x64, 0x7B, 0x38, 0x7D,
0x32, 0x08, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x12, 0x12, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x32, 0x08, 0x31, 0x32, 0x33, 0x34,
@ -772,28 +772,28 @@ static const unsigned char data[] = {
0x64, 0x7B, 0x34, 0x7D, 0x29, 0x12, 0x05, 0x24, 0x31, 0x20, 0x24, 0x32, 0x22,
0x00, 0x2A, 0x00, 0x30, 0x00, 0xAA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A,
0x02, 0x4E, 0x41, 0xC2, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E,
0x41, 0xCA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xDA,
0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xE2, 0x01, 0x08,
0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x0A, 0xF3, 0x01, 0x0A, 0x19,
0x12, 0x05, 0x5C, 0x64, 0x7B, 0x39, 0x7D, 0x1A, 0x05, 0x5C, 0x64, 0x7B, 0x39,
0x7D, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x12,
0x13, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x32, 0x09, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x1A, 0x13, 0x12, 0x02, 0x4E, 0x41,
0x1A, 0x02, 0x4E, 0x41, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x22, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x2A,
0x19, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x39, 0x7D, 0x1A, 0x05, 0x5C, 0x64, 0x7B,
0x39, 0x7D, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x32, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x3A, 0x08, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x42, 0x08, 0x12, 0x02, 0x4E, 0x41,
0x1A, 0x02, 0x4E, 0x41, 0x4A, 0x03, 0x30, 0x30, 0x31, 0x50, 0xD3, 0x07, 0x5A,
0x00, 0x90, 0x01, 0x01, 0x9A, 0x01, 0x24, 0x0A, 0x12, 0x28, 0x5C, 0x64, 0x29,
0x28, 0x5C, 0x64, 0x7B, 0x34, 0x7D, 0x29, 0x28, 0x5C, 0x64, 0x7B, 0x34, 0x7D,
0x29, 0x12, 0x08, 0x24, 0x31, 0x20, 0x24, 0x32, 0x20, 0x24, 0x33, 0x22, 0x00,
0x2A, 0x00, 0x30, 0x00, 0xAA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02,
0x4E, 0x41, 0xC2, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41,
0xCA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xDA, 0x01,
0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xE2, 0x01, 0x08, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41
0x41, 0xCA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xD0,
0x01, 0x01, 0xDA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41,
0xE2, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x0A, 0xF3,
0x01, 0x0A, 0x19, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x39, 0x7D, 0x1A, 0x05, 0x5C,
0x64, 0x7B, 0x39, 0x7D, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x12, 0x13, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x32,
0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x1A, 0x13, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38, 0x39, 0x22, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02,
0x4E, 0x41, 0x2A, 0x19, 0x12, 0x05, 0x5C, 0x64, 0x7B, 0x39, 0x7D, 0x1A, 0x05,
0x5C, 0x64, 0x7B, 0x39, 0x7D, 0x32, 0x09, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x32, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41,
0x3A, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x42, 0x08, 0x12,
0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0x4A, 0x03, 0x30, 0x30, 0x31, 0x50,
0xD3, 0x07, 0x5A, 0x00, 0x90, 0x01, 0x01, 0x9A, 0x01, 0x24, 0x0A, 0x12, 0x28,
0x5C, 0x64, 0x29, 0x28, 0x5C, 0x64, 0x7B, 0x34, 0x7D, 0x29, 0x28, 0x5C, 0x64,
0x7B, 0x34, 0x7D, 0x29, 0x12, 0x08, 0x24, 0x31, 0x20, 0x24, 0x32, 0x20, 0x24,
0x33, 0x22, 0x00, 0x2A, 0x00, 0x30, 0x00, 0xAA, 0x01, 0x08, 0x12, 0x02, 0x4E,
0x41, 0x1A, 0x02, 0x4E, 0x41, 0xC2, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A,
0x02, 0x4E, 0x41, 0xCA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E,
0x41, 0xDA, 0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41, 0xE2,
0x01, 0x08, 0x12, 0x02, 0x4E, 0x41, 0x1A, 0x02, 0x4E, 0x41
};
} // namespace


+ 93
- 4
cpp/test/phonenumbers/phonenumberutil_test.cc View File

@ -22,7 +22,9 @@
#include "phonenumbers/phonenumberutil.h"
#include <algorithm>
#include <iostream>
#include <list>
#include <set>
#include <string>
@ -37,11 +39,14 @@ namespace i18n {
namespace phonenumbers {
using std::endl;
using std::find;
using std::make_pair;
using std::ostream;
using google::protobuf::RepeatedPtrField;
static const int kInvalidCountryCode = 2;
class PhoneNumberUtilTest : public testing::Test {
protected:
PhoneNumberUtilTest() : phone_util_(*PhoneNumberUtil::GetInstance()) {
@ -61,6 +66,13 @@ class PhoneNumberUtilTest : public testing::Test {
phone_util_.GetSupportedRegions(regions);
}
void GetRegionCodesForCountryCallingCode(
int country_calling_code,
list<string>* regions) {
phone_util_.GetRegionCodesForCountryCallingCode(country_calling_code,
regions);
}
void ExtractPossibleNumber(const string& number,
string* extracted_number) const {
phone_util_.ExtractPossibleNumber(number, extracted_number);
@ -78,6 +90,10 @@ class PhoneNumberUtilTest : public testing::Test {
phone_util_.Normalize(number);
}
bool IsNumberGeographical(const PhoneNumber& phone_number) const {
return phone_util_.IsNumberGeographical(phone_number);
}
bool IsLeadingZeroPossible(int country_calling_code) const {
return phone_util_.IsLeadingZeroPossible(country_calling_code);
}
@ -148,6 +164,35 @@ TEST_F(PhoneNumberUtilTest, GetSupportedRegions) {
EXPECT_GT(regions.size(), 0U);
}
TEST_F(PhoneNumberUtilTest, GetRegionCodesForCountryCallingCode) {
list<string> regions;
GetRegionCodesForCountryCallingCode(1, &regions);
EXPECT_TRUE(find(regions.begin(), regions.end(), RegionCode::US())
!= regions.end());
EXPECT_TRUE(find(regions.begin(), regions.end(), RegionCode::BS())
!= regions.end());
regions.clear();
GetRegionCodesForCountryCallingCode(44, &regions);
EXPECT_TRUE(find(regions.begin(), regions.end(), RegionCode::GB())
!= regions.end());
regions.clear();
GetRegionCodesForCountryCallingCode(49, &regions);
EXPECT_TRUE(find(regions.begin(), regions.end(), RegionCode::DE())
!= regions.end());
regions.clear();
GetRegionCodesForCountryCallingCode(800, &regions);
EXPECT_TRUE(find(regions.begin(), regions.end(), RegionCode::UN001())
!= regions.end());
regions.clear();
GetRegionCodesForCountryCallingCode(kInvalidCountryCode, &regions);
EXPECT_TRUE(regions.empty());
}
TEST_F(PhoneNumberUtilTest, GetInstanceLoadUSMetadata) {
const PhoneMetadata* metadata = GetPhoneMetadata(RegionCode::US());
EXPECT_EQ("US", metadata->id());
@ -847,6 +892,14 @@ TEST_F(PhoneNumberUtilTest, FormatWithCarrierCode) {
phone_util_.FormatNationalNumberWithCarrierCode(us_number, "15",
&formatted_number);
EXPECT_EQ("424 123 1234", formatted_number);
// Invalid country code should just get the NSN.
PhoneNumber invalid_number;
invalid_number.set_country_code(kInvalidCountryCode);
invalid_number.set_national_number(12345ULL);
phone_util_.FormatNationalNumberWithCarrierCode(invalid_number, "89",
&formatted_number);
EXPECT_EQ("12345", formatted_number);
}
TEST_F(PhoneNumberUtilTest, FormatWithPreferredCarrierCode) {
@ -1638,10 +1691,27 @@ TEST_F(PhoneNumberUtilTest, TruncateTooLongNumber) {
EXPECT_EQ(too_short_number_copy, too_short_number);
}
TEST_F(PhoneNumberUtilTest, IsNumberGeographical) {
PhoneNumber number;
number.set_country_code(1);
number.set_national_number(2423570000ULL);
EXPECT_FALSE(IsNumberGeographical(number)); // Bahamas, mobile phone number.
number.set_country_code(61);
number.set_national_number(236618300ULL);
EXPECT_TRUE(IsNumberGeographical(number)); // Australian fixed line number.
number.set_country_code(800);
number.set_national_number(12345678ULL);
EXPECT_FALSE(IsNumberGeographical(number)); // Internation toll free number.
}
TEST_F(PhoneNumberUtilTest, IsLeadingZeroPossible) {
EXPECT_TRUE(IsLeadingZeroPossible(39)); // Italy
EXPECT_FALSE(IsLeadingZeroPossible(1)); // USA
EXPECT_FALSE(IsLeadingZeroPossible(800)); // International toll free numbers
EXPECT_TRUE(IsLeadingZeroPossible(800)); // International toll free
EXPECT_FALSE(IsLeadingZeroPossible(979)); // International premium-rate
EXPECT_FALSE(IsLeadingZeroPossible(888)); // Not in metadata file, should
// return default value of false.
}
@ -1912,6 +1982,17 @@ TEST_F(PhoneNumberUtilTest, FormatInOriginalFormat) {
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::JP(),
&formatted_number);
EXPECT_EQ("1234", formatted_number);
// Test that an invalid national number without raw input is just formatted
// as the national number.
phone_number.Clear();
formatted_number.clear();
phone_number.set_country_code_source(PhoneNumber::FROM_DEFAULT_COUNTRY);
phone_number.set_country_code(1);
phone_number.set_national_number(650253000ULL);
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::US(),
&formatted_number);
EXPECT_EQ("650253000", formatted_number);
}
TEST_F(PhoneNumberUtilTest, IsPremiumRate) {
@ -2457,11 +2538,19 @@ TEST_F(PhoneNumberUtilTest, CountryWithNoNumberDesc) {
EXPECT_EQ("00 1 650 253 0000", formatted_number);
}
TEST_F(PhoneNumberUtilTest, UnknownCountryCallingCodeForValidation) {
TEST_F(PhoneNumberUtilTest, UnknownCountryCallingCode) {
PhoneNumber invalid_number;
invalid_number.set_country_code(0);
invalid_number.set_national_number(1234ULL);
invalid_number.set_country_code(kInvalidCountryCode);
invalid_number.set_national_number(12345ULL);
EXPECT_FALSE(phone_util_.IsValidNumber(invalid_number));
// It's not very well defined as to what the E164 representation for a number
// with an invalid country calling code is, but just prefixing the country
// code and national number is about the best we can do.
string formatted_number;
phone_util_.Format(invalid_number, PhoneNumberUtil::E164, &formatted_number);
EXPECT_EQ("+212345", formatted_number);
}
TEST_F(PhoneNumberUtilTest, IsNumberMatchMatches) {


+ 8
- 0
debian/changelog View File

@ -1,3 +1,11 @@
libphonenumber (5.2) lucid; urgency=low
* Metadata changes:
- Updated metadata for region code(s): DE, GR, HR, OM, SB, ZA
- Updated geocoding data for country calling code(s): 30 (el, en)
-- David Beaumont <dbeaumont@google.com> Wed, 10 Oct 2012 17:42:28 +0200
libphonenumber (5.1) lucid; urgency=low
* Version update.


+ 5
- 0
java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java View File

@ -246,6 +246,11 @@ public class PhoneNumberOfflineGeocoder {
return getDescriptionForValidNumber(number, languageCode, userRegion);
}
/**
* A similar method is implemented as PhoneNumberUtil.isNumberGeographical, which performs a
* stricter check, as it determines if a number has a geographical association. Also, if new
* phone number types were added, we should check if this other method should be updated too.
*/
private boolean canBeGeocoded(PhoneNumberType numberType) {
return (numberType == PhoneNumberType.FIXED_LINE ||
numberType == PhoneNumberType.MOBILE ||


BIN
java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/30_el View File


BIN
java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/30_en View File


+ 1
- 2
java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java View File

@ -689,9 +689,8 @@ public class CountryCodeToRegionCodeMap {
listWithRegionCode.add("UY");
countryCodeToRegionCodeMap.put(598, listWithRegionCode);
listWithRegionCode = new ArrayList<String>(3);
listWithRegionCode = new ArrayList<String>(2);
listWithRegionCode.add("CW");
listWithRegionCode.add("AN");
listWithRegionCode.add("BQ");
countryCodeToRegionCodeMap.put(599, listWithRegionCode);


+ 128
- 49
java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java View File

@ -107,8 +107,8 @@ public class PhoneNumberUtil {
private static final String RFC3966_ISDN_SUBADDRESS = ";isub=";
// A map that contains characters that are essential when dialling. That means any of the
// characters in this map must not be removed from a number when dialing, otherwise the call will
// not reach the intended destination.
// characters in this map must not be removed from a number when dialling, otherwise the call
// will not reach the intended destination.
private static final Map<Character, Character> DIALLABLE_CHAR_MAPPINGS;
// Only upper-case variants of alpha characters are stored.
@ -365,6 +365,10 @@ public class PhoneNumberUtil {
private final Map<Integer, PhoneMetadata> countryCodeToNonGeographicalMetadataMap =
Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
// The set of county calling codes that map to the non-geo entity region ("001"). This set
// currently contains < 12 elements so the default capacity of 16 (load factor=0.75) is fine.
private final Set<Integer> countryCodesForNonGeographicalRegion = new HashSet<Integer>();
// 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.
@ -551,10 +555,25 @@ public class PhoneNumberUtil {
private void init(String filePrefix) {
currentFilePrefix = filePrefix;
for (List<String> regionCodes : countryCallingCodeToRegionCodeMap.values()) {
supportedRegions.addAll(regionCodes);
for (Map.Entry<Integer, List<String>> entry : countryCallingCodeToRegionCodeMap.entrySet()) {
List<String> regionCodes = entry.getValue();
// We can assume that if the county calling code maps to the non-geo entity region code then
// that's the only region code it maps to.
if (regionCodes.size() == 1 && REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCodes.get(0))) {
// This is the subset of all country codes that map to the non-geo entity region code.
countryCodesForNonGeographicalRegion.add(entry.getKey());
} else {
// The supported regions set does not include the "001" non-geo entity region code.
supportedRegions.addAll(regionCodes);
}
}
// If the non-geo entity still got added to the set of supported regions it must be because
// there are entries that list the non-geo entity alongside normal regions (which is wrong).
// If we discover this, remove the non-geo entity from the set of supported regions and log.
if (supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY)) {
LOGGER.log(Level.WARNING, "invalid metadata " +
"(country calling code was mapped to the non-geo entity as well as specific region(s))");
}
supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY);
nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE));
}
@ -770,21 +789,17 @@ public class PhoneNumberUtil {
* @return the length of area code of the PhoneNumber object passed in.
*/
public int getLengthOfGeographicalAreaCode(PhoneNumber number) {
String regionCode = getRegionCodeForNumber(number);
if (!isValidRegionCode(regionCode)) {
PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number));
if (metadata == null) {
return 0;
}
PhoneMetadata metadata = getMetadataForRegion(regionCode);
// If a country doesn't use a national prefix, and this number doesn't have an Italian leading
// zero, we assume it is a closed dialling plan with no area codes.
if (!metadata.hasNationalPrefix() && !number.isItalianLeadingZero()) {
return 0;
}
PhoneNumberType type = getNumberTypeHelper(getNationalSignificantNumber(number),
metadata);
// Most numbers other than the two types below have to be dialled in full.
if (type != PhoneNumberType.FIXED_LINE && type != PhoneNumberType.FIXED_LINE_OR_MOBILE) {
if (!isNumberGeographical(number)) {
return 0;
}
@ -874,8 +889,8 @@ public class PhoneNumberUtil {
Map<Character, Character> normalizationReplacements,
boolean removeNonMatches) {
StringBuilder normalizedNumber = new StringBuilder(number.length());
char[] numberAsCharArray = number.toCharArray();
for (char character : numberAsCharArray) {
for (int i = 0; i < number.length(); i++) {
char character = number.charAt(i);
Character newDigit = normalizationReplacements.get(Character.toUpperCase(character));
if (newDigit != null) {
normalizedNumber.append(newDigit);
@ -911,7 +926,7 @@ public class PhoneNumberUtil {
* Convenience method to get a list of what regions the library has metadata for.
*/
public Set<String> getSupportedRegions() {
return supportedRegions;
return Collections.unmodifiableSet(supportedRegions);
}
/**
@ -919,7 +934,7 @@ public class PhoneNumberUtil {
* for.
*/
public Set<Integer> getSupportedGlobalNetworkCallingCodes() {
return countryCodeToNonGeographicalMetadataMap.keySet();
return Collections.unmodifiableSet(countryCodesForNonGeographicalRegion);
}
/**
@ -948,6 +963,19 @@ public class PhoneNumberUtil {
return FIRST_GROUP_ONLY_PREFIX_PATTERN.matcher(nationalPrefixFormattingRule).matches();
}
/**
* Tests whether a phone number has a geographical association. It checks if the number is
* associated to a certain region in the country where it belongs to. Note that this doesn't
* verify if the number is actually in use.
*/
boolean isNumberGeographical(PhoneNumber phoneNumber) {
PhoneNumberType numberType = getNumberType(phoneNumber);
// TODO: Include mobile phone numbers from countries like Indonesia, which has some
// mobile numbers that are geographical.
return numberType == PhoneNumberType.FIXED_LINE ||
numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE;
}
/**
* Helper function to check region code is not unknown or null.
*/
@ -978,6 +1006,11 @@ public class PhoneNumberUtil {
*/
public String format(PhoneNumber number, PhoneNumberFormat numberFormat) {
if (number.getNationalNumber() == 0 && number.hasRawInput()) {
// Unparseable numbers that kept their raw input just use that.
// This is the only case where a number can be formatted as E164 without a
// leading '+' symbol (but the original number wasn't parseable anyway).
// TODO: Consider removing the 'if' above so that unparseable
// strings without raw input format to the empty string instead of "+00"
String rawInput = number.getRawInput();
if (rawInput.length() > 0) {
return rawInput;
@ -999,22 +1032,23 @@ public class PhoneNumberUtil {
int countryCallingCode = number.getCountryCode();
String nationalSignificantNumber = getNationalSignificantNumber(number);
if (numberFormat == PhoneNumberFormat.E164) {
// Early exit for E164 case since no formatting of the national number needs to be applied.
// Extensions are not formatted.
// Early exit for E164 case (even if the country calling code is invalid) since no formatting
// of the national number needs to be applied. Extensions are not formatted.
formattedNumber.append(nationalSignificantNumber);
prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.E164,
formattedNumber);
return;
}
// Note getRegionCodeForCountryCode() is used because formatting information for regions which
// 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 (!hasValidCountryCallingCode(countryCallingCode)) {
formattedNumber.append(nationalSignificantNumber);
return;
}
// Note getRegionCodeForCountryCode() is used because formatting information for regions which
// share a country calling code is contained by only one region for performance reasons. For
// example, for NANPA regions it will be contained in the metadata for US.
String regionCode = getRegionCodeForCountryCode(countryCallingCode);
// Metadata cannot be null because the country calling code is valid (which means that the
// region code cannot be ZZ and must be one of our supported region codes).
PhoneMetadata metadata =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, numberFormat));
@ -1038,13 +1072,14 @@ public class PhoneNumberUtil {
List<NumberFormat> userDefinedFormats) {
int countryCallingCode = number.getCountryCode();
String nationalSignificantNumber = getNationalSignificantNumber(number);
if (!hasValidCountryCallingCode(countryCallingCode)) {
return nationalSignificantNumber;
}
// Note getRegionCodeForCountryCode() is used because formatting information for regions which
// 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 (!hasValidCountryCallingCode(countryCallingCode)) {
return nationalSignificantNumber;
}
// Metadata cannot be null because the country calling code is valid
PhoneMetadata metadata =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
@ -1098,16 +1133,18 @@ public class PhoneNumberUtil {
public String formatNationalNumberWithCarrierCode(PhoneNumber number, String carrierCode) {
int countryCallingCode = number.getCountryCode();
String nationalSignificantNumber = getNationalSignificantNumber(number);
if (!hasValidCountryCallingCode(countryCallingCode)) {
return nationalSignificantNumber;
}
// Note getRegionCodeForCountryCode() is used because formatting information for regions which
// 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 (!hasValidCountryCallingCode(countryCallingCode)) {
return nationalSignificantNumber;
}
// Metadata cannot be null because the country calling code is valid.
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
StringBuilder formattedNumber = new StringBuilder(20);
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
formattedNumber.append(formatNsn(nationalSignificantNumber, metadata,
PhoneNumberFormat.NATIONAL, carrierCode));
maybeAppendFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber);
@ -1242,7 +1279,7 @@ public class PhoneNumberUtil {
return countryCallingCode + " " + format(number, PhoneNumberFormat.NATIONAL);
}
} else if (countryCallingCode == getCountryCodeForValidRegion(regionCallingFrom)) {
// For regions that share a country calling code, the country calling code need not be dialled.
// If regions share a country calling code, the country calling code need not be dialled.
// This also applies when dialling within a region, so this if clause covers both these cases.
// Technically this is the case for dialling from La Reunion to other overseas departments of
// France (French Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover this
@ -1250,6 +1287,7 @@ public class PhoneNumberUtil {
// Details here: http://www.petitfute.com/voyage/225-info-pratiques-reunion
return format(number, PhoneNumberFormat.NATIONAL);
}
// Metadata cannot be null because we checked 'isValidRegionCode()' above.
PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom);
String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix();
@ -1264,6 +1302,7 @@ public class PhoneNumberUtil {
}
String regionCode = getRegionCodeForCountryCode(countryCallingCode);
// Metadata cannot be null because the country calling code is valid.
PhoneMetadata metadataForRegion =
getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
String formattedNationalNumber =
@ -1340,10 +1379,19 @@ public class PhoneNumberUtil {
formattedNumber = nationalFormat;
break;
}
// Metadata cannot be null here because getNddPrefixForRegion() (above) returns null if
// there is no metadata for the region.
PhoneMetadata metadata = getMetadataForRegion(regionCode);
String nationalNumber = getNationalSignificantNumber(number);
NumberFormat formatRule =
chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber);
// The format rule could still be null here if the national number was 0 and there was no
// raw input (this should not be possible for numbers generated by the phonenumber library
// as they would also not have a country calling code and we would have exited earlier).
if (formatRule == null) {
formattedNumber = nationalFormat;
break;
}
// 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.
@ -1374,12 +1422,16 @@ public class PhoneNumberUtil {
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 &&
normalizeHelper(formattedNumber, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */)
.equals(normalizeHelper(
rawInput, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */)))
? formattedNumber
: rawInput;
if (formattedNumber != null && rawInput.length() > 0) {
String normalizedFormattedNumber =
normalizeHelper(formattedNumber, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */);
String normalizedRawInput =
normalizeHelper(rawInput, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */);
if (!normalizedFormattedNumber.equals(normalizedRawInput)) {
formattedNumber = rawInput;
}
}
return formattedNumber;
}
// Check if rawInput, which is assumed to be in the national format, has a national prefix. The
@ -1481,7 +1533,7 @@ public class PhoneNumberUtil {
if (isNANPACountry(regionCallingFrom)) {
return countryCode + " " + rawInput;
}
} else if (isValidRegionCode(regionCallingFrom) &&
} else if (metadataForRegionCallingFrom != null &&
countryCode == getCountryCodeForValidRegion(regionCallingFrom)) {
NumberFormat formattingPattern =
chooseFormattingPatternForNumber(metadataForRegionCallingFrom.numberFormats(),
@ -1516,6 +1568,7 @@ public class PhoneNumberUtil {
}
StringBuilder formattedNumber = new StringBuilder(rawInput);
String regionCode = getRegionCodeForCountryCode(countryCode);
// Metadata cannot be null because the country calling code is valid.
PhoneMetadata metadataForRegion = getMetadataForRegionOrCallingCode(countryCode, regionCode);
maybeAppendFormattedExtension(number, metadataForRegion,
PhoneNumberFormat.INTERNATIONAL, formattedNumber);
@ -1622,7 +1675,7 @@ public class PhoneNumberUtil {
return formatNsnUsingPattern(nationalNumber, formattingPattern, numberFormat, null);
}
// Note that carrierCode is optional - if NULL or an empty string, no carrier code replacement
// Note that carrierCode is optional - if null or an empty string, no carrier code replacement
// will take place.
private String formatNsnUsingPattern(String nationalNumber,
NumberFormat formattingPattern,
@ -1790,11 +1843,11 @@ public class PhoneNumberUtil {
*/
public PhoneNumberType getNumberType(PhoneNumber number) {
String regionCode = getRegionCodeForNumber(number);
if (!isValidRegionCode(regionCode) && !REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode)) {
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode);
if (metadata == null) {
return PhoneNumberType.UNKNOWN;
}
String nationalSignificantNumber = getNationalSignificantNumber(number);
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode);
return getNumberTypeHelper(nationalSignificantNumber, metadata);
}
@ -1848,6 +1901,10 @@ public class PhoneNumberUtil {
return PhoneNumberType.UNKNOWN;
}
/**
* Returns the metadata for the given region code or {@code null} if the region code is invalid
* or unknown.
*/
PhoneMetadata getMetadataForRegion(String regionCode) {
if (!isValidRegionCode(regionCode)) {
return null;
@ -1903,6 +1960,10 @@ public class PhoneNumberUtil {
* immediately exits with false. After this, the specific number pattern rules for the region are
* examined. This is useful for determining for example whether a particular number is valid for
* Canada, rather than just a valid NANPA number.
* Warning: In most cases, you want to use {@link #isValidNumber} instead. For example, this
* method will mark numbers from British Crown dependencies such as the Isle of Man as invalid for
* the region "GB" (United Kingdom), since it has its own region code, "IM", which may be
* undesirable.
*
* @param number the phone number that we want to validate
* @param regionCode the region that we want to validate the phone number for
@ -1960,6 +2021,7 @@ public class PhoneNumberUtil {
String nationalNumber = getNationalSignificantNumber(number);
for (String regionCode : regionCodes) {
// If leadingDigits is present, use this. Otherwise, do full validation.
// Metadata cannot be null because the region codes come from the country calling code map.
PhoneMetadata metadata = getMetadataForRegion(regionCode);
if (metadata.hasLeadingDigits()) {
if (regexCache.getPatternForRegex(metadata.getLeadingDigits())
@ -1983,6 +2045,17 @@ public class PhoneNumberUtil {
return regionCodes == null ? UNKNOWN_REGION : regionCodes.get(0);
}
/**
* Returns a list with the region codes that match the specific country calling code. For
* non-geographical country calling codes, the region code 001 is returned. Also, in the case
* of no region code being found, an empty list is returned.
*/
public List<String> getRegionCodesForCountryCode(int countryCallingCode) {
List<String> regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode);
return Collections.unmodifiableList(regionCodes == null ? new ArrayList<String>(0)
: regionCodes);
}
/**
* Returns the country calling code for a specific region. For example, this would be 1 for the
* United States, and 64 for New Zealand.
@ -2007,9 +2080,13 @@ public class PhoneNumberUtil {
*
* @param regionCode the region that we want to get the country calling code for
* @return the country calling code for the region denoted by regionCode
* @throws IllegalArgumentException if the region is invalid
*/
private int getCountryCodeForValidRegion(String regionCode) {
PhoneMetadata metadata = getMetadataForRegion(regionCode);
if (metadata == null) {
throw new IllegalArgumentException("Invalid region code: " + regionCode);
}
return metadata.getCountryCode();
}
@ -2028,14 +2105,14 @@ public class PhoneNumberUtil {
* @return the dialling prefix for the region denoted by regionCode
*/
public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) {
if (!isValidRegionCode(regionCode)) {
PhoneMetadata metadata = getMetadataForRegion(regionCode);
if (metadata == null) {
LOGGER.log(Level.WARNING,
"Invalid or missing region code ("
+ ((regionCode == null) ? "null" : regionCode)
+ ") provided.");
return null;
}
PhoneMetadata metadata = getMetadataForRegion(regionCode);
String nationalPrefix = metadata.getNationalPrefix();
// If no national prefix was found, we return null.
if (nationalPrefix.length() == 0) {
@ -2064,8 +2141,9 @@ public class PhoneNumberUtil {
* metadata for the country is found.
*/
boolean isLeadingZeroPossible(int countryCallingCode) {
PhoneMetadata mainMetadataForCallingCode = getMetadataForRegion(
getRegionCodeForCountryCode(countryCallingCode));
PhoneMetadata mainMetadataForCallingCode =
getMetadataForRegionOrCallingCode(countryCallingCode,
getRegionCodeForCountryCode(countryCallingCode));
if (mainMetadataForCallingCode == null) {
return false;
}
@ -2137,7 +2215,7 @@ public class PhoneNumberUtil {
* numbers, that would most likely be area codes) and length (obviously includes the
* length of area codes for fixed line numbers), it will return false for the
* subscriber-number-only version.
* </ol
* </ol>
* @param number the number that needs to be checked
* @return a ValidationResult object which indicates whether the number is possible
*/
@ -2152,6 +2230,7 @@ public class PhoneNumberUtil {
return ValidationResult.INVALID_COUNTRY_CODE;
}
String regionCode = getRegionCodeForCountryCode(countryCode);
// Metadata cannot be null because the country calling code is valid.
PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode);
PhoneNumberDesc generalNumDesc = metadata.getGeneralDesc();
// Handling case of numbers with no metadata.
@ -2705,6 +2784,7 @@ public class PhoneNumberUtil {
if (countryCode != 0) {
String phoneNumberRegion = getRegionCodeForCountryCode(countryCode);
if (!phoneNumberRegion.equals(defaultRegion)) {
// Metadata cannot be null because the country calling code is valid.
regionMetadata = getMetadataForRegionOrCallingCode(countryCode, phoneNumberRegion);
}
} else {
@ -2971,13 +3051,12 @@ public class PhoneNumberUtil {
*/
// @VisibleForTesting
boolean canBeInternationallyDialled(PhoneNumber number) {
String regionCode = getRegionCodeForNumber(number);
if (!isValidRegionCode(regionCode)) {
PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number));
if (metadata == null) {
// 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());
}


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB View File


BIN
java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA View File


+ 39
- 5
java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java View File

@ -37,6 +37,8 @@ import java.util.List;
*/
public class PhoneNumberUtilTest extends TestMetadataTestCase {
// Set up some test numbers to re-use.
// TODO: Rewrite this as static functions that return new numbers each time to avoid
// any risk of accidental changes to mutable static state affecting many tests.
private static final PhoneNumber ALPHA_NUMERIC_NUMBER =
new PhoneNumber().setCountryCode(1).setNationalNumber(80074935247L);
private static final PhoneNumber AR_MOBILE =
@ -106,6 +108,8 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
new PhoneNumber().setCountryCode(800).setNationalNumber(123456789L);
private static final PhoneNumber UNIVERSAL_PREMIUM_RATE =
new PhoneNumber().setCountryCode(979).setNationalNumber(123456789L);
private static final PhoneNumber UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT =
new PhoneNumber().setCountryCode(2).setNationalNumber(12345L);
public void testGetSupportedRegions() {
assertTrue(phoneUtil.getSupportedRegions().size() > 0);
@ -202,10 +206,18 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
assertEquals("12345678", metadata.getTollFree().getExampleNumber());
}
public void testIsNumberGeographical() {
assertFalse(phoneUtil.isNumberGeographical(BS_MOBILE)); // Bahamas, mobile phone number.
assertTrue(phoneUtil.isNumberGeographical(AU_NUMBER)); // Australian fixed line number.
assertFalse(phoneUtil.isNumberGeographical(INTERNATIONAL_TOLL_FREE)); // International toll
// free number.
}
public void testIsLeadingZeroPossible() {
assertTrue(phoneUtil.isLeadingZeroPossible(39)); // Italy
assertFalse(phoneUtil.isLeadingZeroPossible(1)); // USA
assertFalse(phoneUtil.isLeadingZeroPossible(800)); // International toll free numbers
assertTrue(phoneUtil.isLeadingZeroPossible(800)); // International toll free
assertFalse(phoneUtil.isLeadingZeroPossible(979)); // International premium-rate
assertFalse(phoneUtil.isLeadingZeroPossible(888)); // Not in metadata file, just default to
// false.
}
@ -639,6 +651,10 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
assertEquals("+5492234654321", phoneUtil.format(arMobile, PhoneNumberFormat.E164));
// We don't support this for the US so there should be no change.
assertEquals("650 253 0000", phoneUtil.formatNationalNumberWithCarrierCode(US_NUMBER, "15"));
// Invalid country code should just get the NSN.
assertEquals("12345",
phoneUtil.formatNationalNumberWithCarrierCode(UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT, "89"));
}
public void testFormatWithPreferredCarrierCode() {
@ -904,6 +920,10 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
assertEquals("*1234", phoneUtil.formatInOriginalFormat(starNumber, RegionCode.JP));
PhoneNumber numberWithoutStar = phoneUtil.parseAndKeepRawInput("1234", RegionCode.JP);
assertEquals("1234", phoneUtil.formatInOriginalFormat(numberWithoutStar, RegionCode.JP));
// Test an invalid national number without raw input is just formatted as the national number.
assertEquals("650253000",
phoneUtil.formatInOriginalFormat(US_SHORT_BY_ONE_NUMBER, RegionCode.US));
}
public void testIsPremiumRate() {
@ -1112,6 +1132,17 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForNumber(UNIVERSAL_PREMIUM_RATE));
}
public void testGetRegionCodesForCountryCode() {
List<String> regionCodesForNANPA = phoneUtil.getRegionCodesForCountryCode(1);
assertTrue(regionCodesForNANPA.contains(RegionCode.US));
assertTrue(regionCodesForNANPA.contains(RegionCode.BS));
assertTrue(phoneUtil.getRegionCodesForCountryCode(44).contains(RegionCode.GB));
assertTrue(phoneUtil.getRegionCodesForCountryCode(49).contains(RegionCode.DE));
assertTrue(phoneUtil.getRegionCodesForCountryCode(800).contains(RegionCode.UN001));
// Test with invalid country calling code.
assertTrue(phoneUtil.getRegionCodesForCountryCode(-1).isEmpty());
}
public void testGetCountryCodeForRegion() {
assertEquals(1, phoneUtil.getCountryCodeForRegion(RegionCode.US));
assertEquals(64, phoneUtil.getCountryCodeForRegion(RegionCode.NZ));
@ -2189,10 +2220,13 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.AD));
}
public void testUnknownCountryCallingCodeForValidation() {
PhoneNumber invalidNumber = new PhoneNumber();
invalidNumber.setCountryCode(0).setNationalNumber(1234L);
assertFalse(phoneUtil.isValidNumber(invalidNumber));
public void testUnknownCountryCallingCode() {
assertFalse(phoneUtil.isValidNumber(UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT));
// It's not very well defined as to what the E164 representation for a number with an invalid
// country calling code is, but just prefixing the country code and national number is about
// the best we can do.
assertEquals("+212345",
phoneUtil.format(UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT, PhoneNumberFormat.E164));
}
public void testIsNumberMatchMatches() throws Exception {


BIN
java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800 View File


+ 15
- 0
java/release_notes.txt View File

@ -1,3 +1,18 @@
Oct 10, 2012: libphonenumber-5.2
* Code changes:
- Adds isNumberGeographical() method.
- Adds getRegionCodesForCountryCode() method.
- Fixing issue with getSupportedGlobalNetworkCallingCodes()
[http://code.google.com/p/libphonenumber/issues/detail?id=202]
- Ensures that returned collections are unmodifiable where necessary
[there is a very slight risk that this may break existing users who were relying on being able
to modify these collections, but doing so would be breaking lots of other assumptions that this
library makes - if you need to modify any affected collections you must copy them first]
* Metadata changes:
- Updated metadata for region code(s): DE, GR, HR, OM, SB, ZA
- Removed metadata for region code: AN (Netherlands Antilles)
- Updated geocoding data for country calling code(s): 30 (el, en)
Sep 27, 2012: libphonenumber-5.1.4
* Metadata changes:
- Updated metadata for region code(s): AU, EC, KH, LB, TN, US


+ 55
- 79
resources/PhoneNumberMetaData.xml View File

@ -679,56 +679,6 @@
</emergency>
</territory>
<!-- Netherlands Antilles -->
<!-- Note this country no longer exists. This metadata exists only to validate old Sint Maarten
numbers through their parallel running period (which ends Sep 2012). New number ranges
added to Sint Maarten during this time will be added to the new territory only and not
here. -->
<!-- The link below no longer works, since ITU deleted this document since this country no
longer exists. We keep it here as a record of the last place we found information on this
country. -->
<!-- http://www.itu.int/oth/T0202000097/en -->
<territory id="AN" countryCode="599" internationalPrefix="00">
<!-- Shares formatting patterns with "CW". -->
<generalDesc>
<nationalNumberPattern>5\d{6}</nationalNumberPattern>
<possibleNumberPattern>\d{7}</possibleNumberPattern>
</generalDesc>
<fixedLine>
<nationalNumberPattern>
5(?:
4[2-8]|
8[239]
)\d{4}
</nationalNumberPattern>
<exampleNumber>5451234</exampleNumber>
</fixedLine>
<mobile>
<!-- The code 555 was NOT migrated when the new country calling code (+1 721) was assigned
for Sint Maarten, so it is supported here but not there. The codes 55[12] also seem
to not have been migrated: although they were not explicitly mentioned in the migration
instructions, they are not in the new plan for SX. -->
<nationalNumberPattern>
5(?:
1[02]|
2\d|
5[0-79]|
8[016-8]
)\d{4}
</nationalNumberPattern>
<exampleNumber>5101234</exampleNumber>
</mobile>
<emergency>
<!-- http://www.rijksdienstcn.com/index.php?view=pagina&id=126&set_language=EN -->
<nationalNumberPattern>
112|
911
</nationalNumberPattern>
<possibleNumberPattern>\d{3}</possibleNumberPattern>
<exampleNumber>112</exampleNumber>
</emergency>
</territory>
<!-- Angola -->
<!-- http://www.itu.int/oth/T0202000006/en -->
<territory id="AO" countryCode="244" internationalPrefix="00">
@ -5353,7 +5303,7 @@
40|
[68]9
</leadingDigits>
<format>$1/$2</format>
<format>$1 $2</format>
</numberFormat>
<!-- The order of the rules on 3-5 digits area code matter as fallback is used here. -->
<!-- 3 digit area codes. -->
@ -5376,7 +5326,7 @@
[1-9]1
)
</leadingDigits>
<format>$1/$2</format>
<format>$1 $2</format>
</numberFormat>
<!-- 4 digit area codes. -->
<numberFormat pattern="(\d{4})(\d{2,11})">
@ -5464,12 +5414,12 @@
)
)
</leadingDigits>
<format>$1/$2</format>
<format>$1 $2</format>
</numberFormat>
<!-- 5 digit area codes. -->
<numberFormat pattern="(\d{5})(\d{1,10})">
<leadingDigits>3</leadingDigits>
<format>$1/$2</format>
<format>$1 $2</format>
</numberFormat>
<numberFormat pattern="(1\d{2})(\d{7,8})">
<leadingDigits>1[5-7]</leadingDigits>
@ -8699,7 +8649,7 @@
)|
3(?:
1\d|
2[1-5]|
2[1-57]|
3[1-4]|
[45][1-3]|
7[1-7]|
@ -9301,8 +9251,12 @@
<leadingDigits>1</leadingDigits>
<format>$1 $2 $3</format>
</numberFormat>
<numberFormat pattern="(6[029])(\d{4})(\d{3})">
<leadingDigits>6[029]</leadingDigits>
<numberFormat pattern="(6[09])(\d{4})(\d{3})">
<leadingDigits>6[09]</leadingDigits>
<format>$1 $2 $3</format>
</numberFormat>
<numberFormat pattern="(62)(\d{3})(\d{3,4})">
<leadingDigits>62</leadingDigits>
<format>$1 $2 $3</format>
</numberFormat>
<numberFormat pattern="([2-5]\d)(\d{3})(\d{3})">
@ -9352,13 +9306,8 @@
<possibleNumberPattern>\d{6,12}</possibleNumberPattern>
</generalDesc>
<fixedLine>
<!-- Supporting 060 (general service), 062 (universal access), 069 (children service)
numbers here too. -->
<nationalNumberPattern>
(?:
1|
6[029]
)\d{7}|
1\d{7}|
(?:
2[0-3]|
3[1-5]|
@ -9366,9 +9315,16 @@
5[1-3]
)\d{6}
</nationalNumberPattern>
<possibleNumberPattern>\d{6,9}</possibleNumberPattern>
<possibleNumberPattern>\d{6,8}</possibleNumberPattern>
<exampleNumber>12345678</exampleNumber>
</fixedLine>
<uan>
<!-- ITU numbering plan doesn't specify the length of the numbers with prefix 62, but there
are numbers on the internet with 6 or 7 digits after the prefix. -->
<nationalNumberPattern>62\d{6,7}</nationalNumberPattern>
<possibleNumberPattern>\d{8,9}</possibleNumberPattern>
<exampleNumber>62123456</exampleNumber>
</uan>
<mobile>
<nationalNumberPattern>9[1257-9]\d{6,10}</nationalNumberPattern>
<possibleNumberPattern>\d{8,12}</possibleNumberPattern>
@ -9380,9 +9336,15 @@
<exampleNumber>8001234567</exampleNumber>
</tollFree>
<premiumRate>
<!-- 061 is for TeleVoting numbers - but these are charged at similar rates to premium rate
so we include them here. -->
<nationalNumberPattern>6[145]\d{4,7}</nationalNumberPattern>
<!-- The prefixes 060, 061, 064, 065 and 069 are named as premium rate numbers by
http://www.vipnet.hr/en/poslovni-korisnici/telefon-internet/vip-adsl-usluga#panel_4.
-->
<nationalNumberPattern>
6(?:
[09]\d{7}|
[145]\d{4,7}
)
</nationalNumberPattern>
<possibleNumberPattern>\d{6,9}</possibleNumberPattern>
<exampleNumber>611234</exampleNumber>
</premiumRate>
@ -18212,21 +18174,21 @@
<generalDesc>
<nationalNumberPattern>
(?:
2[3-6]|
2[2-6]|
5|
9[2-9]
9[1-9]
)\d{6}|
800\d{5,6}
</nationalNumberPattern>
<possibleNumberPattern>\d{7,9}</possibleNumberPattern>
</generalDesc>
<fixedLine>
<nationalNumberPattern>2[3-6]\d{6}</nationalNumberPattern>
<nationalNumberPattern>2[2-6]\d{6}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
<exampleNumber>23123456</exampleNumber>
</fixedLine>
<mobile>
<nationalNumberPattern>9[2-9]\d{6}</nationalNumberPattern>
<nationalNumberPattern>9[1-9]\d{6}</nationalNumberPattern>
<possibleNumberPattern>\d{8}</possibleNumberPattern>
<exampleNumber>92123456</exampleNumber>
</mobile>
@ -20281,12 +20243,12 @@
<!-- A single group is used to format 5-digit numbers. -->
<availableFormats>
<numberFormat pattern="(\d{3})(\d{4})">
<leadingDigits>[78]</leadingDigits>
<leadingDigits>[7-9]</leadingDigits>
<format>$1 $2</format>
</numberFormat>
</availableFormats>
<generalDesc>
<nationalNumberPattern>[1-8]\d{4,6}</nationalNumberPattern>
<nationalNumberPattern>[1-9]\d{4,6}</nationalNumberPattern>
<possibleNumberPattern>\d{5,7}</possibleNumberPattern>
</generalDesc>
<fixedLine>
@ -20308,11 +20270,18 @@
<nationalNumberPattern>
48\d{3}|
7(?:
4\d|
5[025-8]|
6[0-6]
[46-8]\d|
5[025-9]|
90
)\d{4}|
8[4-8]\d{5}
8[4-8]\d{5}|
9(?:
[46]\d|
5[0-46-9]|
7[0-689]|
8[0-79]|
9[0-8]
)\d{4}
</nationalNumberPattern>
<exampleNumber>7421234</exampleNumber>
</mobile>
@ -24645,9 +24614,9 @@
<exampleNumber>801234567</exampleNumber>
</tollFree>
<premiumRate>
<nationalNumberPattern>86[1-9]\d{6}</nationalNumberPattern>
<nationalNumberPattern>86[2-9]\d{6}</nationalNumberPattern>
<possibleNumberPattern>\d{9}</possibleNumberPattern>
<exampleNumber>861234567</exampleNumber>
<exampleNumber>862345678</exampleNumber>
</premiumRate>
<sharedCost>
<nationalNumberPattern>860\d{6}</nationalNumberPattern>
@ -24659,6 +24628,13 @@
<possibleNumberPattern>\d{9}</possibleNumberPattern>
<exampleNumber>871234567</exampleNumber>
</voip>
<uan>
<!-- MaxiCall numbers cost as much as national long distance, so they are classified as UAN
numbers. -->
<nationalNumberPattern>861\d{6}</nationalNumberPattern>
<possibleNumberPattern>\d{9}</possibleNumberPattern>
<exampleNumber>861123456</exampleNumber>
</uan>
<emergency>
<nationalNumberPattern>
1(?:


+ 1
- 1
resources/PhoneNumberMetaDataForTesting.xml View File

@ -800,7 +800,7 @@
</territory>
<!-- International Toll Free numbers -->
<territory id="001" countryCode="800">
<territory id="001" countryCode="800" leadingZeroPossible="true">
<availableFormats>
<numberFormat pattern="(\d{4})(\d{4})">
<format>$1 $2</format>


+ 7
- 4
resources/geocoding/el/30.txt View File

@ -14,6 +14,8 @@
# Generated from:
# http://el.wikipedia.org/wiki/Τηλεφωνικοί_κωδικοί_της_Ελλάδας [2667046]
# Prefixes 302736 and 302893 were translated from the English equivalent
# wikipedia page.
3021|Αθήνα/Πειραιάς/Σαλαμίνα
302221|Χαλκίδα
@ -79,8 +81,8 @@
302322|Νιγρίτα
302323|Σιδηρόκαστρο
302324|Νέα Ζίχνη
3023250|Ηράκλεια
302327|Ροδόπολη Σερρών
302325|Ηράκλεια, Σερρών
302327|Ροδόπολη, Σερρών
302331|Βέροια
302332|Νάουσα
302333|Αλεξάνδρεια
@ -132,7 +134,7 @@
302465|Σιάτιστα
302467|Καστοριά
302468|Νεάπολη
3024910|Φάρσαλα
302491|Φάρσαλα
302492|Τύρναβος
302493|Ελασσόνα
302494|Αγιά
@ -214,6 +216,7 @@
302733|Γύθειο
302734|Νεάπολη
302735|Σκάλα
302736|Κύθηρα
302741|Κόρινθος
302742|Κιάτο
302743|Ξυλόκαστρο
@ -250,7 +253,7 @@
302844|Τζερμιάδο
302891|Αρκαλοχώρι
302892|Μοίρες, Ηράκλειο
302893|Πύργος, Μονοφάτσι
302893|Πύργος, Κρήτη
302894|Αγία Βαρβάρα, Ηράκλειο Κρήτης
302895|Άνω Βιάννος
302897|Λιμένας Χερσονήσου

+ 89
- 83
resources/geocoding/en/30.txt View File

@ -12,48 +12,53 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Translated from el/30.txt using Freebase and Wikipedia.
# Translated from el/30.txt using Freebase and Wikipedia, with names that
# couldn't be auto-translated filled in from
# http://en.wikipedia.org/wiki/Telephone_numbers_in_Greece. For small places,
# the surrounding province, muncipality or island was included if the wikipedia
# page had that as part of the title, or if the Greek numbering plan from ITU
# added that to its description.
3021|Athens/Piraeus/Salamina
302221|Chalcis
302222|
302222|Kymi
302223|Aliveri
302224|Karystos
302226|
302227|
302228|
302226|Aidipsos
302227|Kireas
302228|Messapia
302229|Eretria
302231|Lamia
302232|Domokos
302233|
302233|Atalanta
302234|Amfikleia
302235|
302235|Kamena Vourla
302236|Makrakomi
302237|Karpenisi
302238|Stylida
302241|Rhodes
302242|Kos
302243|Kalymnos
302244|
302244|Archangelos, Rhodes
302245|Karpathos
302246|
302246|Salakos, Rhodes
302247|Leros
302251|Mytilene
302252|Agiasos/Plomari
302253|
302254|
302253|Kalloni, Lesbos
302254|Agios Efstratios
302261|Livadeia
302262|
302262|Thebes
302263|Vilia
302264|
302264|Thisvi
302265|Amfissa
302266|
302266|Lidoriki
302267|Distomo
302268|
302268|Aliartos
302271|Chios
302272|Kardamyla
302273|Samos
302274|
302274|Psara, Chios
302275|Agios Kirykos
302281|Ano Syros
302282|Andros
@ -65,45 +70,45 @@
302288|Kea
302289|Mykonos
302291|Lagonisi
302292|
302293|
302292|Lavrio
302293|Agia Sotira
302294|Rafina
302295|
302296|
302295|Afidnes
302296|Megara
302297|Aegina
302298|
302299|
302298|Troezen/Poros/Hydra/Spetses
302299|Markopoulo Mesogaias
30231|Thessaloniki
302321|Serres
302322|Nigrita
302323|
302324|
3023250|
302327|
302323|Sidirokastro
302324|Nea Zichni
302325|Irakleia, Serres
302327|Rodopoli
302331|Veria
302332|
302333|
302341|
302332|Naousa, Imathia
302333|Alexandria
302341|Kilkis
302343|Polykastro
302351|Korinos
302352|Litochoro
302353|Aiginio
302371|Polygyros
302372|Arnaia
302373|
302373|Nea Moudania
302374|Kassandreia
302375|
302375|Nikiti
302376|Stratoni
302377|
302381|
302377|Ierissos/Mount Athos
302381|Edessa
302382|Giannitsa
302384|Aridaia
302385|
302385|Florina
302386|Amyntaio
302391|
302391|Chalkidona
302392|Peraia, Thessaloniki
302393|Lagkadikia
302394|
302394|Lagkadas
302395|Sochos
302396|Vasilika
302397|Asprovalta
@ -111,30 +116,30 @@
30241|Larissa
302421|Volos
302422|Almyros
302423|
302424|
302423|Kala Nera
302424|Skopelos
302425|Feres, Magnesia
302426|Zagora
302427|Skiathos
302431|Trikala
302432|Kalabaka
302433|
302434|
302433|Farkadona
302434|Pyli
302441|Karditsa
302443|Sofades
302444|
302444|Palamas
302445|Mouzaki
302461|Kozani
302462|Grevena
302463|Ptolemaida
302464|
302464|Servia
302465|Siatista
302467|
302468|
3024910|Farsala
302467|Kastoria
302468|Neapoli
302491|Farsala
302492|Tyrnavos
302493|Elassona
302494|
302494|Agia
302495|Gonnoi/Makrychori
30251|Kavala
302521|Drama
@ -143,49 +148,49 @@
302524|Paranesti
302531|Komotini
302532|Sapes
302533|
302534|
302535|
302533|Xylagani
302534|Iasmos
302535|Nea Kallisti
302541|Xanthi
302542|
302544|
302542|Stavroupoli
302544|Echinos
302551|Alexandroupoli
302552|Orestiada
302553|Didymoteicho
302554|Soufli
302555|Feres, Evros
302556|
302556|Kyprinos
302591|Chrysoupoli
302592|Eleftheroupoli
302593|Thasos
302594|
302594|Nea Peramos, Kavala
30261|Patras
302621|Burgas
302622|Amaliada
302623|Lechaina
302624|
302624|Olympia
302625|Krestena
302626|Andritsaina
302631|Messolonghi
302632|Aitoliko
302634|
302634|Nafpaktos
302635|Mataranga
302641|Agrinio
302642|Amfilochia
302643|Vonitsa
302644|
302644|Thermo
302645|Lefkada
302647|
302647|Fyteies
302651|Ioannina
302653|
302655|
302653|Asprangeli
302655|Konitsa
302656|Metsovo
302657|Delvinaki
302658|Zitsa
302659|
302659|Kalentzi
302661|Corfu
302662|
302663|
302662|Lefkimmi
302663|Corfu Island
302664|Filiates
302665|Igoumenitsa
302666|Paramythia
@ -194,34 +199,35 @@
302681|Arta
302682|Preveza
302683|Filippiada
302684|
302685|
302684|Kanalaki
302685|Athamania
302691|Aigio
302692|Kalavryta
302693|Kato Achaia
302694|
302694|Chalandritsa
302695|Zakynthos
302696|Akrata
30271|Tripoli
302721|Kalamata
302722|
302722|Messene
302723|Pylos
302724|Meligalas
302725|
302725|Koroni
302731|Sparti
302732|Molaoi
302733|Gytheio
302734|
302735|
302741|
302734|Neapoli, Voies
302735|Molaoi
302736|Kythera
302741|Corinth
302742|Kiato
302743|Xylokastro
302744|Loutraki
302746|Nemea
302747|
302751|
302747|Stymfalia
302751|Argos
302752|Nafplio
302753|
302753|Lygourio
302754|Kranidi
302755|Astros
302757|Leonidio
@ -229,10 +235,10 @@
302763|Gargalianoi
302765|Kopanaki
302791|Megalopolis
302792|
302792|Kastri Kynourias
302795|Vytina
302796|Levidi
302797|
302797|Tropaia
30281|Heraklion
302821|Chania
302822|Kissamos
@ -240,16 +246,16 @@
302824|Kolymvari
302825|Vamos
302831|Rethymno
302832|
302833|
302834|
302832|Spyli
302833|Amari, Rethymno
302834|Perama Mylopotamou
302841|Agios Nikolaos
302842|Ierapetra
302843|Sitia
302844|
302844|Tzermadio
302891|Arkalochori
302892|Moires, Heraklion
302893|Pyrgos, Tinos
302894|
302895|
302897|
302893|Pyrgos, Crete
302894|Agia Varvara
302895|Ano Viannos
302897|Limenas Chersonisou

BIN
tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar View File


+ 62
- 0
tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/AbstractAreaCodeDataIOHandler.java View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2012 The Libphonenumber Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.i18n.phonenumbers.geocoding;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Abstracts the way GenerateAreaCodeDataEntryPoint creates files and writes the area code data to
* them.
*/
public abstract class AbstractAreaCodeDataIOHandler {
private static final Logger LOGGER = Logger.getLogger(
AbstractAreaCodeDataIOHandler.class.getName());
/**
* Adds the provided file to a global output that can be for example a JAR.
*
* @throws IOException
*/
abstract void addFileToOutput(File file) throws IOException;
/**
* Creates a new file from the provided path.
*/
abstract File createFile(String path);
/**
* Releases the resources used by the underlying implementation if any.
*/
abstract void close();
/**
* Closes the provided file and logs any potential IOException.
*/
void closeFile(Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException e) {
LOGGER.log(Level.WARNING, e.getMessage());
}
}
}

+ 59
- 0
tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/AreaCodeDataIOHandler.java View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2012 The Libphonenumber Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.i18n.phonenumbers.geocoding;
import java.io.File;
import java.io.IOException;
/**
* Implementation of the IOHandler required by the GenerateAreaCodeData class used here to create
* the output files.
*/
class AreaCodeDataIOHandler extends AbstractAreaCodeDataIOHandler {
// The path to the output directory.
private final File outputPath;
public AreaCodeDataIOHandler(File outputPath) throws IOException {
if (outputPath.exists()) {
if (!outputPath.isDirectory()) {
throw new IOException("Expected directory: " + outputPath.getAbsolutePath());
}
} else {
if (!outputPath.mkdirs()) {
throw new IOException("Could not create directory " + outputPath.getAbsolutePath());
}
}
this.outputPath = outputPath;
}
@Override
public void addFileToOutput(File file) throws IOException {
// Do nothing. This would be the place dealing with the addition of the provided file to the
// resulting JAR if the global output was a JAR instead of a directory containing the binary
// files.
}
@Override
public File createFile(String path) {
return new File(outputPath, path);
}
@Override
public void close() {
// Do nothing as no resource needs to be released.
}
}

+ 3
- 38
tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/GenerateAreaCodeData.java View File

@ -63,47 +63,12 @@ public class GenerateAreaCodeData {
private final Map<Integer /* country code */, SortedMap<Integer, String>> englishMaps =
new HashMap<Integer, SortedMap<Integer, String>>();
// The IO Handler used to output the generated binary files.
private final IOHandler ioHandler;
private final AbstractAreaCodeDataIOHandler ioHandler;
private static final Logger LOGGER = Logger.getLogger(GenerateAreaCodeData.class.getName());
/**
* Abstracts the way the generated binary files are created and written.
*/
abstract static class IOHandler {
/**
* Adds the provided file to the global output that can be for example a JAR.
*
* @throws IOException
*/
abstract void addFileToOutput(File file) throws IOException;
/**
* Creates a new file from the provided path.
*/
abstract File createFile(String path);
/**
* Releases the resources used by the underlying implementation if any.
*/
abstract void close();
/**
* Closes the provided file and logs any potential IOException.
*/
void closeFile(Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException e) {
LOGGER.log(Level.WARNING, e.getMessage());
}
}
}
public GenerateAreaCodeData(File inputPath, IOHandler ioHandler) throws IOException {
public GenerateAreaCodeData(File inputPath, AbstractAreaCodeDataIOHandler ioHandler)
throws IOException {
if (!inputPath.isDirectory()) {
throw new IOException("The provided input path does not exist: " +
inputPath.getAbsolutePath());


+ 1
- 40
tools/java/java-build/src/com/google/i18n/phonenumbers/geocoding/GenerateAreaCodeDataEntryPoint.java View File

@ -31,45 +31,6 @@ import java.util.logging.Logger;
public class GenerateAreaCodeDataEntryPoint extends Command {
private static final Logger LOGGER = Logger.getLogger(GenerateAreaCodeData.class.getName());
/**
* Implementation of the IOHandler required by the GenerateAreaCodeData class used here to create
* the output files.
*/
private static class IOHandler extends GenerateAreaCodeData.IOHandler {
// The path to the output directory.
private final File outputPath;
public IOHandler(File outputPath) throws IOException {
if (outputPath.exists()) {
if (!outputPath.isDirectory()) {
throw new IOException("Expected directory: " + outputPath.getAbsolutePath());
}
} else {
if (!outputPath.mkdirs()) {
throw new IOException("Could not create directory " + outputPath.getAbsolutePath());
}
}
this.outputPath = outputPath;
}
@Override
public void addFileToOutput(File file) throws IOException {
// Do nothing. This would be the place dealing with the addition of the provided file to the
// resulting JAR if the global output was a JAR instead of a directory containing the binary
// files.
}
@Override
public File createFile(String path) {
return new File(outputPath, path);
}
@Override
public void close() {
// Do nothing as no resource needs to be released.
}
}
@Override
public String getCommandName() {
return "GenerateAreaCodeData";
@ -86,7 +47,7 @@ public class GenerateAreaCodeDataEntryPoint extends Command {
}
try {
GenerateAreaCodeData generateAreaCodeData =
new GenerateAreaCodeData(new File(args[1]), new IOHandler(new File(args[2])));
new GenerateAreaCodeData(new File(args[1]), new AreaCodeDataIOHandler(new File(args[2])));
generateAreaCodeData.run();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage());


BIN
tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar View File


Loading…
Cancel
Save