summaryrefslogtreecommitdiff
path: root/libphonenumber
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-12-18 11:56:40 +0000
committerNarayan Kamath <narayan@google.com>2014-12-23 12:32:44 +0000
commita77faddfc3b3e4cca8f585c82d669054aec221f4 (patch)
treeb3ca5eaf70be2df2a1a9cfc684532d1563d759a7 /libphonenumber
parenteec8af34d3129d0f37c45ff8a82b4212724a6d79 (diff)
downloadlibphonenumber-a77faddfc3b3e4cca8f585c82d669054aec221f4.tar.gz
Update libphonenumber to an unmodified copy of v7.0.1
Copied from upstream commit eb7f783d2fd7d222a10283a72d9e7 with no local modifications and a cherry-pick of commit 5b00cb5b2dc0582c29 (JAVA/JS: Documentation fix and added missing licences.) from upstream master. Added Android.mk to build the code for platform and unbundled use. Note that while we rename packages, we don't rename resources to make sure they're found. Change-Id: Idb886f1b5d7bca491b9f7f8d18574a88f08593ba
Diffstat (limited to 'libphonenumber')
-rw-r--r--libphonenumber/pom.xml33
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java79
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java656
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java941
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/MetadataLoader.java34
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java138
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java62
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java123
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java725
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java3232
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java1053
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java285
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java78
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java587
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java80
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java268
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255bin0 -> 154 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27bin0 -> 104 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30bin0 -> 100 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31bin0 -> 251 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34bin0 -> 153 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350bin0 -> 89 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351bin0 -> 212 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352bin0 -> 96 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358bin0 -> 176 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359bin0 -> 238 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36bin0 -> 146 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372bin0 -> 335 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373bin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_375bin0 -> 113 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380bin0 -> 307 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381bin0 -> 405 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385bin0 -> 251 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43bin0 -> 853 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44bin0 -> 342 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49bin0 -> 5277 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505bin0 -> 96 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506bin0 -> 111 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54bin0 -> 159 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55bin0 -> 98 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58bin0 -> 96 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595bin0 -> 139 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61bin0 -> 301 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62bin0 -> 113 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_63bin0 -> 89 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66bin0 -> 90 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675bin0 -> 100 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676bin0 -> 102 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679bin0 -> 97 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7bin0 -> 347 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81bin0 -> 239 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84bin0 -> 159 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855bin0 -> 108 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90bin0 -> 139 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91bin0 -> 1366 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94bin0 -> 99 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95bin0 -> 97 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971bin0 -> 101 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972bin0 -> 119 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995bin0 -> 120 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800bin0 -> 276 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808bin0 -> 276 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870bin0 -> 303 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878bin0 -> 309 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881bin0 -> 290 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882bin0 -> 767 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883bin0 -> 467 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888bin0 -> 302 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979bin0 -> 287 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ACbin0 -> 256 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ADbin0 -> 371 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AEbin0 -> 601 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AFbin0 -> 415 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AGbin0 -> 517 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AIbin0 -> 451 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ALbin0 -> 728 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AMbin0 -> 629 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AObin0 -> 310 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ARbin0 -> 3535 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ASbin0 -> 448 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ATbin0 -> 1218 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AUbin0 -> 1132 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AWbin0 -> 419 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AXbin0 -> 641 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZbin0 -> 580 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BAbin0 -> 551 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BBbin0 -> 429 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BDbin0 -> 2195 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BEbin0 -> 697 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BFbin0 -> 388 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BGbin0 -> 882 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BHbin0 -> 511 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BIbin0 -> 324 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJbin0 -> 403 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BLbin0 -> 284 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BMbin0 -> 467 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BNbin0 -> 323 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BObin0 -> 550 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQbin0 -> 320 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BRbin0 -> 1295 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BSbin0 -> 615 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BTbin0 -> 412 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BWbin0 -> 592 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BYbin0 -> 1195 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZbin0 -> 386 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CAbin0 -> 737 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CCbin0 -> 521 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CDbin0 -> 530 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CFbin0 -> 320 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CGbin0 -> 367 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CHbin0 -> 679 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CIbin0 -> 414 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CKbin0 -> 300 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CLbin0 -> 1465 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CMbin0 -> 518 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CNbin0 -> 3719 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CObin0 -> 888 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CRbin0 -> 700 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CUbin0 -> 456 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CVbin0 -> 335 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CWbin0 -> 473 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CXbin0 -> 521 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CYbin0 -> 391 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZbin0 -> 714 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DEbin0 -> 2239 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJbin0 -> 311 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DKbin0 -> 384 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DMbin0 -> 486 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DObin0 -> 750 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZbin0 -> 631 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ECbin0 -> 678 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EEbin0 -> 938 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EGbin0 -> 714 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EHbin0 -> 333 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ERbin0 -> 336 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ESbin0 -> 689 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ETbin0 -> 964 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FIbin0 -> 868 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJbin0 -> 423 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FKbin0 -> 235 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FMbin0 -> 315 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FObin0 -> 418 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FRbin0 -> 683 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GAbin0 -> 362 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GBbin0 -> 2846 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GDbin0 -> 547 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GEbin0 -> 597 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GFbin0 -> 394 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GGbin0 -> 599 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GHbin0 -> 549 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GIbin0 -> 388 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GLbin0 -> 356 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GMbin0 -> 385 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GNbin0 -> 435 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GPbin0 -> 384 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQbin0 -> 437 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GRbin0 -> 865 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GTbin0 -> 406 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GUbin0 -> 811 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GWbin0 -> 347 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GYbin0 -> 415 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HKbin0 -> 626 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HNbin0 -> 504 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HRbin0 -> 1021 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HTbin0 -> 354 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HUbin0 -> 533 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IDbin0 -> 1526 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IEbin0 -> 1224 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ILbin0 -> 1065 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IMbin0 -> 518 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_INbin0 -> 3714 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IObin0 -> 266 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQbin0 -> 460 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IRbin0 -> 681 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ISbin0 -> 711 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ITbin0 -> 1627 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JEbin0 -> 697 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JMbin0 -> 675 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JObin0 -> 1013 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JPbin0 -> 9446 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KEbin0 -> 593 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KGbin0 -> 669 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KHbin0 -> 627 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KIbin0 -> 327 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KMbin0 -> 338 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KNbin0 -> 464 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KPbin0 -> 482 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KRbin0 -> 1454 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KWbin0 -> 510 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KYbin0 -> 591 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZbin0 -> 850 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LAbin0 -> 515 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LBbin0 -> 542 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LCbin0 -> 507 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LIbin0 -> 924 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LKbin0 -> 415 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LRbin0 -> 573 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LSbin0 -> 298 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LTbin0 -> 634 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LUbin0 -> 1511 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LVbin0 -> 343 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LYbin0 -> 327 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MAbin0 -> 740 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MCbin0 -> 537 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MDbin0 -> 703 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MEbin0 -> 665 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MFbin0 -> 295 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MGbin0 -> 404 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MHbin0 -> 328 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MKbin0 -> 627 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MLbin0 -> 499 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MMbin0 -> 1362 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MNbin0 -> 708 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MObin0 -> 305 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MPbin0 -> 597 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQbin0 -> 383 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MRbin0 -> 417 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MSbin0 -> 404 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MTbin0 -> 537 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MUbin0 -> 583 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MVbin0 -> 497 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MWbin0 -> 469 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MXbin0 -> 1809 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MYbin0 -> 742 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZbin0 -> 402 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NAbin0 -> 860 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NCbin0 -> 363 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NEbin0 -> 477 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NFbin0 -> 337 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NGbin0 -> 1301 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NIbin0 -> 331 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NLbin0 -> 922 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NObin0 -> 646 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NPbin0 -> 608 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NRbin0 -> 284 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NUbin0 -> 232 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZbin0 -> 857 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OMbin0 -> 422 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PAbin0 -> 875 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PEbin0 -> 585 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PFbin0 -> 415 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PGbin0 -> 475 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PHbin0 -> 1093 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PKbin0 -> 1749 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PLbin0 -> 811 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PMbin0 -> 287 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PRbin0 -> 433 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PSbin0 -> 556 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PTbin0 -> 628 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PWbin0 -> 370 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PYbin0 -> 852 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QAbin0 -> 392 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_REbin0 -> 421 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RObin0 -> 648 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RSbin0 -> 841 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RUbin0 -> 773 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RWbin0 -> 474 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SAbin0 -> 718 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SBbin0 -> 457 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SCbin0 -> 398 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SDbin0 -> 317 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SEbin0 -> 2903 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SGbin0 -> 577 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SHbin0 -> 298 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SIbin0 -> 681 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJbin0 -> 479 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SKbin0 -> 641 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SLbin0 -> 341 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SMbin0 -> 605 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SNbin0 -> 538 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SObin0 -> 552 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SRbin0 -> 466 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SSbin0 -> 304 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_STbin0 -> 272 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SVbin0 -> 480 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SXbin0 -> 452 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SYbin0 -> 465 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZbin0 -> 435 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TAbin0 -> 208 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TCbin0 -> 495 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TDbin0 -> 357 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TGbin0 -> 324 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_THbin0 -> 579 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJbin0 -> 649 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TKbin0 -> 233 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TLbin0 -> 407 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TMbin0 -> 529 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TNbin0 -> 385 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TObin0 -> 454 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TRbin0 -> 715 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TTbin0 -> 557 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TVbin0 -> 238 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TWbin0 -> 516 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZbin0 -> 528 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UAbin0 -> 1141 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UGbin0 -> 607 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_USbin0 -> 1654 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UYbin0 -> 473 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZbin0 -> 1809 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VAbin0 -> 265 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VCbin0 -> 528 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VEbin0 -> 410 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VGbin0 -> 521 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VIbin0 -> 637 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VNbin0 -> 1106 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VUbin0 -> 388 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WFbin0 -> 298 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WSbin0 -> 370 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YEbin0 -> 442 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YTbin0 -> 281 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZAbin0 -> 689 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZMbin0 -> 382 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZWbin0 -> 1690 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ACbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ADbin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AEbin0 -> 175 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AFbin0 -> 193 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AGbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AIbin0 -> 163 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ALbin0 -> 221 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AMbin0 -> 198 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AObin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ARbin0 -> 268 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ASbin0 -> 171 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ATbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AUbin0 -> 425 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AWbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AXbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZbin0 -> 208 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BAbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BBbin0 -> 168 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BDbin0 -> 311 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BEbin0 -> 413 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BFbin0 -> 155 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BGbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BHbin0 -> 192 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BIbin0 -> 243 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BLbin0 -> 149 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BMbin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BNbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BObin0 -> 173 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BRbin0 -> 292 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BSbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BTbin0 -> 179 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BWbin0 -> 185 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BYbin0 -> 220 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZbin0 -> 176 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CAbin0 -> 180 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CCbin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CDbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CHbin0 -> 415 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CIbin0 -> 201 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CKbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CLbin0 -> 822 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CMbin0 -> 185 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CNbin0 -> 231 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CObin0 -> 253 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CRbin0 -> 371 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CUbin0 -> 189 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CVbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CWbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CXbin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CYbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZbin0 -> 230 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DEbin0 -> 163 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJbin0 -> 155 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DKbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DMbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DObin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZbin0 -> 175 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ECbin0 -> 187 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EEbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EGbin0 -> 204 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EHbin0 -> 180 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ESbin0 -> 590 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ETbin0 -> 196 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FIbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJbin0 -> 238 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FKbin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FMbin0 -> 207 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FObin0 -> 193 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FRbin0 -> 616 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GAbin0 -> 194 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GBbin0 -> 336 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GDbin0 -> 163 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GEbin0 -> 228 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GFbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GGbin0 -> 226 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GHbin0 -> 228 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GIbin0 -> 388 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GLbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GMbin0 -> 174 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GNbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GPbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GRbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GTbin0 -> 205 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GUbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GWbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GYbin0 -> 230 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HKbin0 -> 173 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HNbin0 -> 177 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HRbin0 -> 193 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HTbin0 -> 183 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HUbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IDbin0 -> 209 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IEbin0 -> 186 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ILbin0 -> 231 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IMbin0 -> 198 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_INbin0 -> 222 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQbin0 -> 228 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IRbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ISbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ITbin0 -> 460 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JEbin0 -> 256 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JMbin0 -> 186 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JObin0 -> 235 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JPbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KEbin0 -> 252 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KGbin0 -> 183 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KHbin0 -> 194 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KIbin0 -> 210 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KMbin0 -> 155 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KNbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KRbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KWbin0 -> 180 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KYbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZbin0 -> 219 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LAbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LBbin0 -> 187 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LCbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LIbin0 -> 244 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LKbin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LRbin0 -> 217 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LSbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LTbin0 -> 223 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LUbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LVbin0 -> 320 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LYbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MAbin0 -> 180 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MCbin0 -> 187 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MDbin0 -> 272 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MEbin0 -> 238 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MFbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MGbin0 -> 172 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MHbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MKbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MLbin0 -> 546 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MMbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MNbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MObin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MPbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MRbin0 -> 155 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MSbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MTbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MUbin0 -> 193 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MVbin0 -> 179 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MWbin0 -> 201 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MXbin0 -> 250 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MYbin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZbin0 -> 201 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NAbin0 -> 199 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NCbin0 -> 308 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NFbin0 -> 176 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NGbin0 -> 184 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NIbin0 -> 250 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NLbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NObin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NPbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NRbin0 -> 174 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NUbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OMbin0 -> 160 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PAbin0 -> 167 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PEbin0 -> 176 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PFbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PGbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PHbin0 -> 173 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PKbin0 -> 198 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PLbin0 -> 228 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PMbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PRbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PTbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PWbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PYbin0 -> 172 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QAbin0 -> 189 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_REbin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RObin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RSbin0 -> 188 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RUbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RWbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SAbin0 -> 342 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SBbin0 -> 222 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SCbin0 -> 244 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SDbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SEbin0 -> 491 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SGbin0 -> 227 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SHbin0 -> 189 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SIbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SKbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SLbin0 -> 199 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SMbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SNbin0 -> 153 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SRbin0 -> 168 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_STbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SVbin0 -> 177 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SXbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SYbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TCbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TDbin0 -> 155 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TGbin0 -> 188 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_THbin0 -> 300 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TLbin0 -> 189 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TMbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TNbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TObin0 -> 182 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TRbin0 -> 176 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TTbin0 -> 162 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TVbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TWbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZbin0 -> 199 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UAbin0 -> 178 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UGbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_USbin0 -> 667 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UYbin0 -> 193 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZbin0 -> 218 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VAbin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VCbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VEbin0 -> 181 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VGbin0 -> 170 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VIbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VNbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VUbin0 -> 156 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WFbin0 -> 157 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WSbin0 -> 164 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YEbin0 -> 166 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YTbin0 -> 175 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZAbin0 -> 200 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZMbin0 -> 183 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZWbin0 -> 185 bytes
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/internal/MatcherApi.java38
-rw-r--r--libphonenumber/src/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java52
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java1173
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java142
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java256
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java51
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java70
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java1090
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java2570
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java112
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java55
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java61
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java344
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java140
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java46
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800bin0 -> 276 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_979bin0 -> 287 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_ADbin0 -> 164 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AEbin0 -> 241 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AObin0 -> 319 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_ARbin0 -> 878 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AUbin0 -> 378 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BBbin0 -> 165 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BRbin0 -> 162 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BSbin0 -> 389 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BYbin0 -> 371 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CAbin0 -> 165 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CCbin0 -> 162 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CNbin0 -> 250 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CXbin0 -> 164 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DEbin0 -> 741 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_FRbin0 -> 275 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GBbin0 -> 549 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GGbin0 -> 162 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_HUbin0 -> 218 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_ITbin0 -> 476 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JPbin0 -> 754 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KRbin0 -> 1587 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MXbin0 -> 1007 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZbin0 -> 555 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PLbin0 -> 325 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_REbin0 -> 408 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SGbin0 -> 428 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_USbin0 -> 561 bytes
-rw-r--r--libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YTbin0 -> 282 bytes
590 files changed, 14574 insertions, 0 deletions
diff --git a/libphonenumber/pom.xml b/libphonenumber/pom.xml
new file mode 100644
index 00000000..dd4eea97
--- /dev/null
+++ b/libphonenumber/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.googlecode.libphonenumber</groupId>
+ <artifactId>libphonenumber</artifactId>
+ <version>7.0.1</version>
+ <packaging>jar</packaging>
+ <url>http://code.google.com/p/libphonenumber/</url>
+
+ <parent>
+ <groupId>com.googlecode.libphonenumber</groupId>
+ <artifactId>libphonenumber-parent</artifactId>
+ <version>7.0.1</version>
+ </parent>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <testSourceDirectory>test</testSourceDirectory>
+ <resources>
+ <resource>
+ <directory>src/com/google/i18n/phonenumbers/data</directory>
+ <targetPath>com/google/i18n/phonenumbers/data</targetPath>
+ </resource>
+ </resources>
+ <testResources>
+ <testResource>
+ <directory>test/com/google/i18n/phonenumbers/data</directory>
+ <targetPath>com/google/i18n/phonenumbers/data</targetPath>
+ </testResource>
+ </testResources>
+ </build>
+
+</project>
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java b/libphonenumber/src/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java
new file mode 100644
index 00000000..c07a1739
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+/* This file is automatically generated by {@link BuildMetadataProtoFromXml}.
+ * Please don't modify it directly.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class AlternateFormatsCountryCodeSet {
+ // A set of all country codes for which data is available.
+ static Set<Integer> getCountryCodeSet() {
+ // The capacity is set to 57 as there are 43 different entries,
+ // and this offers a load factor of roughly 0.75.
+ Set<Integer> countryCodeSet = new HashSet<Integer>(57);
+
+ countryCodeSet.add(7);
+ countryCodeSet.add(27);
+ countryCodeSet.add(30);
+ countryCodeSet.add(31);
+ countryCodeSet.add(34);
+ countryCodeSet.add(36);
+ countryCodeSet.add(43);
+ countryCodeSet.add(44);
+ countryCodeSet.add(49);
+ countryCodeSet.add(54);
+ countryCodeSet.add(55);
+ countryCodeSet.add(58);
+ countryCodeSet.add(61);
+ countryCodeSet.add(62);
+ countryCodeSet.add(63);
+ countryCodeSet.add(66);
+ countryCodeSet.add(81);
+ countryCodeSet.add(84);
+ countryCodeSet.add(90);
+ countryCodeSet.add(91);
+ countryCodeSet.add(94);
+ countryCodeSet.add(95);
+ countryCodeSet.add(255);
+ countryCodeSet.add(350);
+ countryCodeSet.add(351);
+ countryCodeSet.add(352);
+ countryCodeSet.add(358);
+ countryCodeSet.add(359);
+ countryCodeSet.add(372);
+ countryCodeSet.add(373);
+ countryCodeSet.add(380);
+ countryCodeSet.add(381);
+ countryCodeSet.add(385);
+ countryCodeSet.add(505);
+ countryCodeSet.add(506);
+ countryCodeSet.add(595);
+ countryCodeSet.add(675);
+ countryCodeSet.add(676);
+ countryCodeSet.add(679);
+ countryCodeSet.add(855);
+ countryCodeSet.add(971);
+ countryCodeSet.add(972);
+ countryCodeSet.add(995);
+
+ return countryCodeSet;
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java
new file mode 100644
index 00000000..ad63a40a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A formatter which formats phone numbers as they are entered.
+ *
+ * <p>An AsYouTypeFormatter can be created by invoking
+ * {@link PhoneNumberUtil#getAsYouTypeFormatter}. After that, digits can be added by invoking
+ * {@link #inputDigit} on the formatter instance, and the partially formatted phone number will be
+ * returned each time a digit is added. {@link #clear} can be invoked before formatting a new
+ * number.
+ *
+ * <p>See the unittests for more details on how the formatter is to be used.
+ *
+ * @author Shaopeng Jia
+ */
+public class AsYouTypeFormatter {
+ private String currentOutput = "";
+ private StringBuilder formattingTemplate = new StringBuilder();
+ // The pattern from numberFormat that is currently used to create formattingTemplate.
+ private String currentFormattingPattern = "";
+ private StringBuilder accruedInput = new StringBuilder();
+ private StringBuilder accruedInputWithoutFormatting = new StringBuilder();
+ // This indicates whether AsYouTypeFormatter is currently doing the formatting.
+ private boolean ableToFormat = true;
+ // Set to true when users enter their own formatting. AsYouTypeFormatter will do no formatting at
+ // all when this is set to true.
+ private boolean inputHasFormatting = false;
+ // This is set to true when we know the user is entering a full national significant number, since
+ // we have either detected a national prefix or an international dialing prefix. When this is
+ // true, we will no longer use local number formatting patterns.
+ private boolean isCompleteNumber = false;
+ private boolean isExpectingCountryCallingCode = false;
+ private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+ private String defaultCountry;
+
+ // Character used when appropriate to separate a prefix, such as a long NDD or a country calling
+ // code, from the national number.
+ private static final char SEPARATOR_BEFORE_NATIONAL_NUMBER = ' ';
+ private static final PhoneMetadata EMPTY_METADATA =
+ new PhoneMetadata().setInternationalPrefix("NA");
+ private PhoneMetadata defaultMetadata;
+ private PhoneMetadata currentMetadata;
+
+ // A pattern that is used to match character classes in regular expressions. An example of a
+ // character class is [1-4].
+ private static final Pattern CHARACTER_CLASS_PATTERN = Pattern.compile("\\[([^\\[\\]])*\\]");
+ // Any digit in a regular expression that actually denotes a digit. For example, in the regular
+ // expression 80[0-2]\d{6,10}, the first 2 digits (8 and 0) are standalone digits, but the rest
+ // are not.
+ // Two look-aheads are needed because the number following \\d could be a two-digit number, since
+ // the phone number can be as long as 15 digits.
+ private static final Pattern STANDALONE_DIGIT_PATTERN = Pattern.compile("\\d(?=[^,}][^,}])");
+
+ // A pattern that is used to determine if a numberFormat under availableFormats is eligible to be
+ // used by the AYTF. It is eligible when the format element under numberFormat contains groups of
+ // the dollar sign followed by a single digit, separated by valid phone number punctuation. This
+ // prevents invalid punctuation (such as the star sign in Israeli star numbers) getting into the
+ // output of the AYTF.
+ private static final Pattern ELIGIBLE_FORMAT_PATTERN =
+ Pattern.compile("[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*" +
+ "(\\$\\d" + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*)+");
+ // A set of characters that, if found in a national prefix formatting rules, are an indicator to
+ // us that we should separate the national prefix from the number when formatting.
+ private static final Pattern NATIONAL_PREFIX_SEPARATORS_PATTERN = Pattern.compile("[- ]");
+
+ // This is the minimum length of national number accrued that is required to trigger the
+ // formatter. The first element of the leadingDigitsPattern of each numberFormat contains a
+ // regular expression that matches up to this number of digits.
+ private static final int MIN_LEADING_DIGITS_LENGTH = 3;
+
+ // The digits that have not been entered yet will be represented by a \u2008, the punctuation
+ // space.
+ private static final String DIGIT_PLACEHOLDER = "\u2008";
+ private static final Pattern DIGIT_PATTERN = Pattern.compile(DIGIT_PLACEHOLDER);
+ private int lastMatchPosition = 0;
+ // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as
+ // found in the original sequence of characters the user entered.
+ private int originalPosition = 0;
+ // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as
+ // found in accruedInputWithoutFormatting.
+ private int positionToRemember = 0;
+ // This contains anything that has been entered so far preceding the national significant number,
+ // and it is formatted (e.g. with space inserted). For example, this can contain IDD, country
+ // code, and/or NDD, etc.
+ private StringBuilder prefixBeforeNationalNumber = new StringBuilder();
+ private boolean shouldAddSpaceAfterNationalPrefix = false;
+ // This contains the national prefix that has been extracted. It contains only digits without
+ // formatting.
+ private String extractedNationalPrefix = "";
+ private StringBuilder nationalNumber = new StringBuilder();
+ private List<NumberFormat> possibleFormats = new ArrayList<NumberFormat>();
+
+ // A cache for frequently used country-specific regular expressions.
+ private RegexCache regexCache = new RegexCache(64);
+
+ /**
+ * Constructs an as-you-type formatter. Should be obtained from {@link
+ * PhoneNumberUtil#getAsYouTypeFormatter}.
+ *
+ * @param regionCode the country/region where the phone number is being entered
+ */
+ AsYouTypeFormatter(String regionCode) {
+ defaultCountry = regionCode;
+ currentMetadata = getMetadataForRegion(defaultCountry);
+ defaultMetadata = currentMetadata;
+ }
+
+ // The metadata needed by this class is the same for all regions sharing the same country calling
+ // code. Therefore, we return the metadata for "main" region for this country calling code.
+ private PhoneMetadata getMetadataForRegion(String regionCode) {
+ int countryCallingCode = phoneUtil.getCountryCodeForRegion(regionCode);
+ String mainCountry = phoneUtil.getRegionCodeForCountryCode(countryCallingCode);
+ PhoneMetadata metadata = phoneUtil.getMetadataForRegion(mainCountry);
+ if (metadata != null) {
+ return metadata;
+ }
+ // Set to a default instance of the metadata. This allows us to function with an incorrect
+ // region code, even if formatting only works for numbers specified with "+".
+ return EMPTY_METADATA;
+ }
+
+ // Returns true if a new template is created as opposed to reusing the existing template.
+ private boolean maybeCreateNewTemplate() {
+ // When there are multiple available formats, the formatter uses the first format where a
+ // formatting template could be created.
+ Iterator<NumberFormat> it = possibleFormats.iterator();
+ while (it.hasNext()) {
+ NumberFormat numberFormat = it.next();
+ String pattern = numberFormat.getPattern();
+ if (currentFormattingPattern.equals(pattern)) {
+ return false;
+ }
+ if (createFormattingTemplate(numberFormat)) {
+ currentFormattingPattern = pattern;
+ shouldAddSpaceAfterNationalPrefix =
+ NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher(
+ numberFormat.getNationalPrefixFormattingRule()).find();
+ // With a new formatting template, the matched position using the old template needs to be
+ // reset.
+ lastMatchPosition = 0;
+ return true;
+ } else { // Remove the current number format from possibleFormats.
+ it.remove();
+ }
+ }
+ ableToFormat = false;
+ return false;
+ }
+
+ private void getAvailableFormats(String leadingDigits) {
+ List<NumberFormat> formatList =
+ (isCompleteNumber && currentMetadata.intlNumberFormatSize() > 0)
+ ? currentMetadata.intlNumberFormats()
+ : currentMetadata.numberFormats();
+ boolean nationalPrefixIsUsedByCountry = currentMetadata.hasNationalPrefix();
+ for (NumberFormat format : formatList) {
+ if (!nationalPrefixIsUsedByCountry || isCompleteNumber ||
+ format.isNationalPrefixOptionalWhenFormatting() ||
+ PhoneNumberUtil.formattingRuleHasFirstGroupOnly(
+ format.getNationalPrefixFormattingRule())) {
+ if (isFormatEligible(format.getFormat())) {
+ possibleFormats.add(format);
+ }
+ }
+ }
+ narrowDownPossibleFormats(leadingDigits);
+ }
+
+ private boolean isFormatEligible(String format) {
+ return ELIGIBLE_FORMAT_PATTERN.matcher(format).matches();
+ }
+
+ private void narrowDownPossibleFormats(String leadingDigits) {
+ int indexOfLeadingDigitsPattern = leadingDigits.length() - MIN_LEADING_DIGITS_LENGTH;
+ Iterator<NumberFormat> it = possibleFormats.iterator();
+ while (it.hasNext()) {
+ NumberFormat format = it.next();
+ if (format.leadingDigitsPatternSize() == 0) {
+ // Keep everything that isn't restricted by leading digits.
+ continue;
+ }
+ int lastLeadingDigitsPattern =
+ Math.min(indexOfLeadingDigitsPattern, format.leadingDigitsPatternSize() - 1);
+ Pattern leadingDigitsPattern = regexCache.getPatternForRegex(
+ format.getLeadingDigitsPattern(lastLeadingDigitsPattern));
+ Matcher m = leadingDigitsPattern.matcher(leadingDigits);
+ if (!m.lookingAt()) {
+ it.remove();
+ }
+ }
+ }
+
+ private boolean createFormattingTemplate(NumberFormat format) {
+ String numberPattern = format.getPattern();
+
+ // The formatter doesn't format numbers when numberPattern contains "|", e.g.
+ // (20|3)\d{4}. In those cases we quickly return.
+ if (numberPattern.indexOf('|') != -1) {
+ return false;
+ }
+
+ // Replace anything in the form of [..] with \d
+ numberPattern = CHARACTER_CLASS_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
+
+ // Replace any standalone digit (not the one in d{}) with \d
+ numberPattern = STANDALONE_DIGIT_PATTERN.matcher(numberPattern).replaceAll("\\\\d");
+ formattingTemplate.setLength(0);
+ String tempTemplate = getFormattingTemplate(numberPattern, format.getFormat());
+ if (tempTemplate.length() > 0) {
+ formattingTemplate.append(tempTemplate);
+ return true;
+ }
+ return false;
+ }
+
+ // Gets a formatting template which can be used to efficiently format a partial number where
+ // digits are added one by one.
+ private String getFormattingTemplate(String numberPattern, String numberFormat) {
+ // Creates a phone number consisting only of the digit 9 that matches the
+ // numberPattern by applying the pattern to the longestPhoneNumber string.
+ String longestPhoneNumber = "999999999999999";
+ Matcher m = regexCache.getPatternForRegex(numberPattern).matcher(longestPhoneNumber);
+ m.find(); // this will always succeed
+ String aPhoneNumber = m.group();
+ // No formatting template can be created if the number of digits entered so far is longer than
+ // the maximum the current formatting rule can accommodate.
+ if (aPhoneNumber.length() < nationalNumber.length()) {
+ return "";
+ }
+ // Formats the number according to numberFormat
+ String template = aPhoneNumber.replaceAll(numberPattern, numberFormat);
+ // Replaces each digit with character DIGIT_PLACEHOLDER
+ template = template.replaceAll("9", DIGIT_PLACEHOLDER);
+ return template;
+ }
+
+ /**
+ * Clears the internal state of the formatter, so it can be reused.
+ */
+ public void clear() {
+ currentOutput = "";
+ accruedInput.setLength(0);
+ accruedInputWithoutFormatting.setLength(0);
+ formattingTemplate.setLength(0);
+ lastMatchPosition = 0;
+ currentFormattingPattern = "";
+ prefixBeforeNationalNumber.setLength(0);
+ extractedNationalPrefix = "";
+ nationalNumber.setLength(0);
+ ableToFormat = true;
+ inputHasFormatting = false;
+ positionToRemember = 0;
+ originalPosition = 0;
+ isCompleteNumber = false;
+ isExpectingCountryCallingCode = false;
+ possibleFormats.clear();
+ shouldAddSpaceAfterNationalPrefix = false;
+ if (!currentMetadata.equals(defaultMetadata)) {
+ currentMetadata = getMetadataForRegion(defaultCountry);
+ }
+ }
+
+ /**
+ * Formats a phone number on-the-fly as each digit is entered.
+ *
+ * @param nextChar the most recently entered digit of a phone number. Formatting characters are
+ * allowed, but as soon as they are encountered this method formats the number as entered and
+ * not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will
+ * be shown as they are.
+ * @return the partially formatted phone number.
+ */
+ public String inputDigit(char nextChar) {
+ currentOutput = inputDigitWithOptionToRememberPosition(nextChar, false);
+ return currentOutput;
+ }
+
+ /**
+ * Same as {@link #inputDigit}, but remembers the position where {@code nextChar} is inserted, so
+ * that it can be retrieved later by using {@link #getRememberedPosition}. The remembered
+ * position will be automatically adjusted if additional formatting characters are later
+ * inserted/removed in front of {@code nextChar}.
+ */
+ public String inputDigitAndRememberPosition(char nextChar) {
+ currentOutput = inputDigitWithOptionToRememberPosition(nextChar, true);
+ return currentOutput;
+ }
+
+ @SuppressWarnings("fallthrough")
+ private String inputDigitWithOptionToRememberPosition(char nextChar, boolean rememberPosition) {
+ accruedInput.append(nextChar);
+ if (rememberPosition) {
+ originalPosition = accruedInput.length();
+ }
+ // We do formatting on-the-fly only when each character entered is either a digit, or a plus
+ // sign (accepted at the start of the number only).
+ if (!isDigitOrLeadingPlusSign(nextChar)) {
+ ableToFormat = false;
+ inputHasFormatting = true;
+ } else {
+ nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar, rememberPosition);
+ }
+ if (!ableToFormat) {
+ // When we are unable to format because of reasons other than that formatting chars have been
+ // entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able
+ // to do formatting again after extracting them.
+ if (inputHasFormatting) {
+ return accruedInput.toString();
+ } else if (attemptToExtractIdd()) {
+ if (attemptToExtractCountryCallingCode()) {
+ return attemptToChoosePatternWithPrefixExtracted();
+ }
+ } else if (ableToExtractLongerNdd()) {
+ // Add an additional space to separate long NDD and national significant number for
+ // readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want
+ // this to change later when we choose formatting templates.
+ prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
+ return attemptToChoosePatternWithPrefixExtracted();
+ }
+ return accruedInput.toString();
+ }
+
+ // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus
+ // sign is counted as a digit as well for this purpose) have been entered.
+ switch (accruedInputWithoutFormatting.length()) {
+ case 0:
+ case 1:
+ case 2:
+ return accruedInput.toString();
+ case 3:
+ if (attemptToExtractIdd()) {
+ isExpectingCountryCallingCode = true;
+ } else { // No IDD or plus sign is found, might be entering in national format.
+ extractedNationalPrefix = removeNationalPrefixFromNationalNumber();
+ return attemptToChooseFormattingPattern();
+ }
+ default:
+ if (isExpectingCountryCallingCode) {
+ if (attemptToExtractCountryCallingCode()) {
+ isExpectingCountryCallingCode = false;
+ }
+ return prefixBeforeNationalNumber + nationalNumber.toString();
+ }
+ if (possibleFormats.size() > 0) { // The formatting patterns are already chosen.
+ String tempNationalNumber = inputDigitHelper(nextChar);
+ // See if the accrued digits can be formatted properly already. If not, use the results
+ // from inputDigitHelper, which does formatting based on the formatting pattern chosen.
+ String formattedNumber = attemptToFormatAccruedDigits();
+ if (formattedNumber.length() > 0) {
+ return formattedNumber;
+ }
+ narrowDownPossibleFormats(nationalNumber.toString());
+ if (maybeCreateNewTemplate()) {
+ return inputAccruedNationalNumber();
+ }
+ return ableToFormat
+ ? appendNationalNumber(tempNationalNumber)
+ : accruedInput.toString();
+ } else {
+ return attemptToChooseFormattingPattern();
+ }
+ }
+ }
+
+ private String attemptToChoosePatternWithPrefixExtracted() {
+ ableToFormat = true;
+ isExpectingCountryCallingCode = false;
+ possibleFormats.clear();
+ return attemptToChooseFormattingPattern();
+ }
+
+ // @VisibleForTesting
+ String getExtractedNationalPrefix() {
+ return extractedNationalPrefix;
+ }
+
+ // Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result
+ // in a number we can format, we try to see if we can extract a longer version here.
+ private boolean ableToExtractLongerNdd() {
+ if (extractedNationalPrefix.length() > 0) {
+ // Put the extracted NDD back to the national number before attempting to extract a new NDD.
+ nationalNumber.insert(0, extractedNationalPrefix);
+ // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set
+ // it to empty string because people sometimes incorrectly enter national prefix after the
+ // country code, e.g. +44 (0)20-1234-5678.
+ int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(extractedNationalPrefix);
+ prefixBeforeNationalNumber.setLength(indexOfPreviousNdd);
+ }
+ return !extractedNationalPrefix.equals(removeNationalPrefixFromNationalNumber());
+ }
+
+ private boolean isDigitOrLeadingPlusSign(char nextChar) {
+ return Character.isDigit(nextChar) ||
+ (accruedInput.length() == 1 &&
+ PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches());
+ }
+
+ /**
+ * Check to see if there is an exact pattern match for these digits. If so, we should use this
+ * instead of any other formatting template whose leadingDigitsPattern also matches the input.
+ */
+ String attemptToFormatAccruedDigits() {
+ for (NumberFormat numberFormat : possibleFormats) {
+ Matcher m = regexCache.getPatternForRegex(numberFormat.getPattern()).matcher(nationalNumber);
+ if (m.matches()) {
+ shouldAddSpaceAfterNationalPrefix =
+ NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher(
+ numberFormat.getNationalPrefixFormattingRule()).find();
+ String formattedNumber = m.replaceAll(numberFormat.getFormat());
+ return appendNationalNumber(formattedNumber);
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Returns the current position in the partially formatted phone number of the character which was
+ * previously passed in as the parameter of {@link #inputDigitAndRememberPosition}.
+ */
+ public int getRememberedPosition() {
+ if (!ableToFormat) {
+ return originalPosition;
+ }
+ int accruedInputIndex = 0, currentOutputIndex = 0;
+ while (accruedInputIndex < positionToRemember && currentOutputIndex < currentOutput.length()) {
+ if (accruedInputWithoutFormatting.charAt(accruedInputIndex) ==
+ currentOutput.charAt(currentOutputIndex)) {
+ accruedInputIndex++;
+ }
+ currentOutputIndex++;
+ }
+ return currentOutputIndex;
+ }
+
+ /**
+ * Combines the national number with any prefix (IDD/+ and country code or national prefix) that
+ * was collected. A space will be inserted between them if the current formatting template
+ * indicates this to be suitable.
+ */
+ private String appendNationalNumber(String nationalNumber) {
+ int prefixBeforeNationalNumberLength = prefixBeforeNationalNumber.length();
+ if (shouldAddSpaceAfterNationalPrefix && prefixBeforeNationalNumberLength > 0 &&
+ prefixBeforeNationalNumber.charAt(prefixBeforeNationalNumberLength - 1)
+ != SEPARATOR_BEFORE_NATIONAL_NUMBER) {
+ // We want to add a space after the national prefix if the national prefix formatting rule
+ // indicates that this would normally be done, with the exception of the case where we already
+ // appended a space because the NDD was surprisingly long.
+ return new String(prefixBeforeNationalNumber) + SEPARATOR_BEFORE_NATIONAL_NUMBER
+ + nationalNumber;
+ } else {
+ return prefixBeforeNationalNumber + nationalNumber;
+ }
+ }
+
+ /**
+ * Attempts to set the formatting template and returns a string which contains the formatted
+ * version of the digits entered so far.
+ */
+ private String attemptToChooseFormattingPattern() {
+ // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits of national
+ // number (excluding national prefix) have been entered.
+ if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) {
+
+ getAvailableFormats(nationalNumber.toString());
+ // See if the accrued digits can be formatted properly already.
+ String formattedNumber = attemptToFormatAccruedDigits();
+ if (formattedNumber.length() > 0) {
+ return formattedNumber;
+ }
+ return maybeCreateNewTemplate() ? inputAccruedNationalNumber() : accruedInput.toString();
+ } else {
+ return appendNationalNumber(nationalNumber.toString());
+ }
+ }
+
+ /**
+ * Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted
+ * string in the end.
+ */
+ private String inputAccruedNationalNumber() {
+ int lengthOfNationalNumber = nationalNumber.length();
+ if (lengthOfNationalNumber > 0) {
+ String tempNationalNumber = "";
+ for (int i = 0; i < lengthOfNationalNumber; i++) {
+ tempNationalNumber = inputDigitHelper(nationalNumber.charAt(i));
+ }
+ return ableToFormat ? appendNationalNumber(tempNationalNumber) : accruedInput.toString();
+ } else {
+ return prefixBeforeNationalNumber.toString();
+ }
+ }
+
+ /**
+ * Returns true if the current country is a NANPA country and the national number begins with
+ * the national prefix.
+ */
+ private boolean isNanpaNumberWithNationalPrefix() {
+ // For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is
+ // that national significant numbers in NANPA always start with [2-9] after the national prefix.
+ // Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the
+ // national prefix.
+ return (currentMetadata.getCountryCode() == 1) && (nationalNumber.charAt(0) == '1') &&
+ (nationalNumber.charAt(1) != '0') && (nationalNumber.charAt(1) != '1');
+ }
+
+ // Returns the national prefix extracted, or an empty string if it is not present.
+ private String removeNationalPrefixFromNationalNumber() {
+ int startOfNationalNumber = 0;
+ if (isNanpaNumberWithNationalPrefix()) {
+ startOfNationalNumber = 1;
+ prefixBeforeNationalNumber.append('1').append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
+ isCompleteNumber = true;
+ } else if (currentMetadata.hasNationalPrefixForParsing()) {
+ Pattern nationalPrefixForParsing =
+ regexCache.getPatternForRegex(currentMetadata.getNationalPrefixForParsing());
+ Matcher m = nationalPrefixForParsing.matcher(nationalNumber);
+ // Since some national prefix patterns are entirely optional, check that a national prefix
+ // could actually be extracted.
+ if (m.lookingAt() && m.end() > 0) {
+ // When the national prefix is detected, we use international formatting rules instead of
+ // national ones, because national formatting rules could contain local formatting rules
+ // for numbers entered without area code.
+ isCompleteNumber = true;
+ startOfNationalNumber = m.end();
+ prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber));
+ }
+ }
+ String nationalPrefix = nationalNumber.substring(0, startOfNationalNumber);
+ nationalNumber.delete(0, startOfNationalNumber);
+ return nationalPrefix;
+ }
+
+ /**
+ * Extracts IDD and plus sign to prefixBeforeNationalNumber when they are available, and places
+ * the remaining input into nationalNumber.
+ *
+ * @return true when accruedInputWithoutFormatting begins with the plus sign or valid IDD for
+ * defaultCountry.
+ */
+ private boolean attemptToExtractIdd() {
+ Pattern internationalPrefix =
+ regexCache.getPatternForRegex("\\" + PhoneNumberUtil.PLUS_SIGN + "|" +
+ currentMetadata.getInternationalPrefix());
+ Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting);
+ if (iddMatcher.lookingAt()) {
+ isCompleteNumber = true;
+ int startOfCountryCallingCode = iddMatcher.end();
+ nationalNumber.setLength(0);
+ nationalNumber.append(accruedInputWithoutFormatting.substring(startOfCountryCallingCode));
+ prefixBeforeNationalNumber.setLength(0);
+ prefixBeforeNationalNumber.append(
+ accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode));
+ if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN) {
+ prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Extracts the country calling code from the beginning of nationalNumber to
+ * prefixBeforeNationalNumber when they are available, and places the remaining input into
+ * nationalNumber.
+ *
+ * @return true when a valid country calling code can be found.
+ */
+ private boolean attemptToExtractCountryCallingCode() {
+ if (nationalNumber.length() == 0) {
+ return false;
+ }
+ StringBuilder numberWithoutCountryCallingCode = new StringBuilder();
+ int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode);
+ if (countryCode == 0) {
+ return false;
+ }
+ nationalNumber.setLength(0);
+ nationalNumber.append(numberWithoutCountryCallingCode);
+ String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode);
+ 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);
+ prefixBeforeNationalNumber.append(countryCodeString).append(SEPARATOR_BEFORE_NATIONAL_NUMBER);
+ // When we have successfully extracted the IDD, the previously extracted NDD should be cleared
+ // because it is no longer valid.
+ extractedNationalPrefix = "";
+ return true;
+ }
+
+ // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar
+ // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first
+ // normalized to the ASCII version. The return value is nextChar itself, or its normalized
+ // version, if nextChar is a digit in non-ASCII format. This method assumes its input is either a
+ // digit or the plus sign.
+ private char normalizeAndAccrueDigitsAndPlusSign(char nextChar, boolean rememberPosition) {
+ char normalizedChar;
+ if (nextChar == PhoneNumberUtil.PLUS_SIGN) {
+ normalizedChar = nextChar;
+ accruedInputWithoutFormatting.append(nextChar);
+ } else {
+ int radix = 10;
+ normalizedChar = Character.forDigit(Character.digit(nextChar, radix), radix);
+ accruedInputWithoutFormatting.append(normalizedChar);
+ nationalNumber.append(normalizedChar);
+ }
+ if (rememberPosition) {
+ positionToRemember = accruedInputWithoutFormatting.length();
+ }
+ return normalizedChar;
+ }
+
+ private String inputDigitHelper(char nextChar) {
+ Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate);
+ if (digitMatcher.find(lastMatchPosition)) {
+ String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar));
+ formattingTemplate.replace(0, tempTemplate.length(), tempTemplate);
+ lastMatchPosition = digitMatcher.start();
+ return formattingTemplate.substring(0, lastMatchPosition + 1);
+ } else {
+ if (possibleFormats.size() == 1) {
+ // More digits are entered than we could handle, and there are no other valid patterns to
+ // try.
+ ableToFormat = false;
+ } // else, we just reset the formatting pattern.
+ currentFormattingPattern = "";
+ return accruedInput.toString();
+ }
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
new file mode 100644
index 00000000..5f3e269e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/* This file is automatically generated by {@link BuildMetadataProtoFromXml}.
+ * Please don't modify it directly.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CountryCodeToRegionCodeMap {
+ // A mapping from a country code to the region codes which denote the
+ // country/region represented by that country code. In the case of multiple
+ // countries sharing a calling code, such as the NANPA countries, the one
+ // indicated with "isMainCountryForCode" in the metadata should be first.
+ static Map<Integer, List<String>> getCountryCodeToRegionCodeMap() {
+ // The capacity is set to 286 as there are 215 different entries,
+ // and this offers a load factor of roughly 0.75.
+ Map<Integer, List<String>> countryCodeToRegionCodeMap =
+ new HashMap<Integer, List<String>>(286);
+
+ ArrayList<String> listWithRegionCode;
+
+ listWithRegionCode = new ArrayList<String>(25);
+ listWithRegionCode.add("US");
+ listWithRegionCode.add("AG");
+ listWithRegionCode.add("AI");
+ listWithRegionCode.add("AS");
+ listWithRegionCode.add("BB");
+ listWithRegionCode.add("BM");
+ listWithRegionCode.add("BS");
+ listWithRegionCode.add("CA");
+ listWithRegionCode.add("DM");
+ listWithRegionCode.add("DO");
+ listWithRegionCode.add("GD");
+ listWithRegionCode.add("GU");
+ listWithRegionCode.add("JM");
+ listWithRegionCode.add("KN");
+ listWithRegionCode.add("KY");
+ listWithRegionCode.add("LC");
+ listWithRegionCode.add("MP");
+ listWithRegionCode.add("MS");
+ listWithRegionCode.add("PR");
+ listWithRegionCode.add("SX");
+ listWithRegionCode.add("TC");
+ listWithRegionCode.add("TT");
+ listWithRegionCode.add("VC");
+ listWithRegionCode.add("VG");
+ listWithRegionCode.add("VI");
+ countryCodeToRegionCodeMap.put(1, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("RU");
+ listWithRegionCode.add("KZ");
+ countryCodeToRegionCodeMap.put(7, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("EG");
+ countryCodeToRegionCodeMap.put(20, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ZA");
+ countryCodeToRegionCodeMap.put(27, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GR");
+ countryCodeToRegionCodeMap.put(30, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NL");
+ countryCodeToRegionCodeMap.put(31, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BE");
+ countryCodeToRegionCodeMap.put(32, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FR");
+ countryCodeToRegionCodeMap.put(33, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ES");
+ countryCodeToRegionCodeMap.put(34, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HU");
+ countryCodeToRegionCodeMap.put(36, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IT");
+ countryCodeToRegionCodeMap.put(39, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("RO");
+ countryCodeToRegionCodeMap.put(40, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CH");
+ countryCodeToRegionCodeMap.put(41, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AT");
+ countryCodeToRegionCodeMap.put(43, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(4);
+ listWithRegionCode.add("GB");
+ listWithRegionCode.add("GG");
+ listWithRegionCode.add("IM");
+ listWithRegionCode.add("JE");
+ countryCodeToRegionCodeMap.put(44, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("DK");
+ countryCodeToRegionCodeMap.put(45, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SE");
+ countryCodeToRegionCodeMap.put(46, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("NO");
+ listWithRegionCode.add("SJ");
+ countryCodeToRegionCodeMap.put(47, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PL");
+ countryCodeToRegionCodeMap.put(48, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("DE");
+ countryCodeToRegionCodeMap.put(49, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PE");
+ countryCodeToRegionCodeMap.put(51, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MX");
+ countryCodeToRegionCodeMap.put(52, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CU");
+ countryCodeToRegionCodeMap.put(53, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AR");
+ countryCodeToRegionCodeMap.put(54, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BR");
+ countryCodeToRegionCodeMap.put(55, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CL");
+ countryCodeToRegionCodeMap.put(56, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CO");
+ countryCodeToRegionCodeMap.put(57, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("VE");
+ countryCodeToRegionCodeMap.put(58, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MY");
+ countryCodeToRegionCodeMap.put(60, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(3);
+ listWithRegionCode.add("AU");
+ listWithRegionCode.add("CC");
+ listWithRegionCode.add("CX");
+ countryCodeToRegionCodeMap.put(61, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ID");
+ countryCodeToRegionCodeMap.put(62, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PH");
+ countryCodeToRegionCodeMap.put(63, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NZ");
+ countryCodeToRegionCodeMap.put(64, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SG");
+ countryCodeToRegionCodeMap.put(65, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TH");
+ countryCodeToRegionCodeMap.put(66, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("JP");
+ countryCodeToRegionCodeMap.put(81, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KR");
+ countryCodeToRegionCodeMap.put(82, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("VN");
+ countryCodeToRegionCodeMap.put(84, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CN");
+ countryCodeToRegionCodeMap.put(86, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TR");
+ countryCodeToRegionCodeMap.put(90, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IN");
+ countryCodeToRegionCodeMap.put(91, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PK");
+ countryCodeToRegionCodeMap.put(92, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AF");
+ countryCodeToRegionCodeMap.put(93, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LK");
+ countryCodeToRegionCodeMap.put(94, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MM");
+ countryCodeToRegionCodeMap.put(95, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IR");
+ countryCodeToRegionCodeMap.put(98, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SS");
+ countryCodeToRegionCodeMap.put(211, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("MA");
+ listWithRegionCode.add("EH");
+ countryCodeToRegionCodeMap.put(212, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("DZ");
+ countryCodeToRegionCodeMap.put(213, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TN");
+ countryCodeToRegionCodeMap.put(216, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LY");
+ countryCodeToRegionCodeMap.put(218, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GM");
+ countryCodeToRegionCodeMap.put(220, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SN");
+ countryCodeToRegionCodeMap.put(221, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MR");
+ countryCodeToRegionCodeMap.put(222, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ML");
+ countryCodeToRegionCodeMap.put(223, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GN");
+ countryCodeToRegionCodeMap.put(224, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CI");
+ countryCodeToRegionCodeMap.put(225, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BF");
+ countryCodeToRegionCodeMap.put(226, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NE");
+ countryCodeToRegionCodeMap.put(227, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TG");
+ countryCodeToRegionCodeMap.put(228, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BJ");
+ countryCodeToRegionCodeMap.put(229, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MU");
+ countryCodeToRegionCodeMap.put(230, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LR");
+ countryCodeToRegionCodeMap.put(231, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SL");
+ countryCodeToRegionCodeMap.put(232, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GH");
+ countryCodeToRegionCodeMap.put(233, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NG");
+ countryCodeToRegionCodeMap.put(234, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TD");
+ countryCodeToRegionCodeMap.put(235, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CF");
+ countryCodeToRegionCodeMap.put(236, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CM");
+ countryCodeToRegionCodeMap.put(237, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CV");
+ countryCodeToRegionCodeMap.put(238, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ST");
+ countryCodeToRegionCodeMap.put(239, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GQ");
+ countryCodeToRegionCodeMap.put(240, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GA");
+ countryCodeToRegionCodeMap.put(241, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CG");
+ countryCodeToRegionCodeMap.put(242, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CD");
+ countryCodeToRegionCodeMap.put(243, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AO");
+ countryCodeToRegionCodeMap.put(244, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GW");
+ countryCodeToRegionCodeMap.put(245, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IO");
+ countryCodeToRegionCodeMap.put(246, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AC");
+ countryCodeToRegionCodeMap.put(247, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SC");
+ countryCodeToRegionCodeMap.put(248, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SD");
+ countryCodeToRegionCodeMap.put(249, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("RW");
+ countryCodeToRegionCodeMap.put(250, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ET");
+ countryCodeToRegionCodeMap.put(251, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SO");
+ countryCodeToRegionCodeMap.put(252, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("DJ");
+ countryCodeToRegionCodeMap.put(253, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KE");
+ countryCodeToRegionCodeMap.put(254, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TZ");
+ countryCodeToRegionCodeMap.put(255, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("UG");
+ countryCodeToRegionCodeMap.put(256, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BI");
+ countryCodeToRegionCodeMap.put(257, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MZ");
+ countryCodeToRegionCodeMap.put(258, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ZM");
+ countryCodeToRegionCodeMap.put(260, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MG");
+ countryCodeToRegionCodeMap.put(261, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("RE");
+ listWithRegionCode.add("YT");
+ countryCodeToRegionCodeMap.put(262, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ZW");
+ countryCodeToRegionCodeMap.put(263, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NA");
+ countryCodeToRegionCodeMap.put(264, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MW");
+ countryCodeToRegionCodeMap.put(265, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LS");
+ countryCodeToRegionCodeMap.put(266, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BW");
+ countryCodeToRegionCodeMap.put(267, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SZ");
+ countryCodeToRegionCodeMap.put(268, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KM");
+ countryCodeToRegionCodeMap.put(269, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("SH");
+ listWithRegionCode.add("TA");
+ countryCodeToRegionCodeMap.put(290, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ER");
+ countryCodeToRegionCodeMap.put(291, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AW");
+ countryCodeToRegionCodeMap.put(297, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FO");
+ countryCodeToRegionCodeMap.put(298, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GL");
+ countryCodeToRegionCodeMap.put(299, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GI");
+ countryCodeToRegionCodeMap.put(350, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PT");
+ countryCodeToRegionCodeMap.put(351, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LU");
+ countryCodeToRegionCodeMap.put(352, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IE");
+ countryCodeToRegionCodeMap.put(353, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IS");
+ countryCodeToRegionCodeMap.put(354, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AL");
+ countryCodeToRegionCodeMap.put(355, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MT");
+ countryCodeToRegionCodeMap.put(356, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CY");
+ countryCodeToRegionCodeMap.put(357, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("FI");
+ listWithRegionCode.add("AX");
+ countryCodeToRegionCodeMap.put(358, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BG");
+ countryCodeToRegionCodeMap.put(359, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LT");
+ countryCodeToRegionCodeMap.put(370, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LV");
+ countryCodeToRegionCodeMap.put(371, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("EE");
+ countryCodeToRegionCodeMap.put(372, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MD");
+ countryCodeToRegionCodeMap.put(373, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AM");
+ countryCodeToRegionCodeMap.put(374, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BY");
+ countryCodeToRegionCodeMap.put(375, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AD");
+ countryCodeToRegionCodeMap.put(376, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MC");
+ countryCodeToRegionCodeMap.put(377, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SM");
+ countryCodeToRegionCodeMap.put(378, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("VA");
+ countryCodeToRegionCodeMap.put(379, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("UA");
+ countryCodeToRegionCodeMap.put(380, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("RS");
+ countryCodeToRegionCodeMap.put(381, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("ME");
+ countryCodeToRegionCodeMap.put(382, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HR");
+ countryCodeToRegionCodeMap.put(385, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SI");
+ countryCodeToRegionCodeMap.put(386, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BA");
+ countryCodeToRegionCodeMap.put(387, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MK");
+ countryCodeToRegionCodeMap.put(389, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CZ");
+ countryCodeToRegionCodeMap.put(420, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SK");
+ countryCodeToRegionCodeMap.put(421, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LI");
+ countryCodeToRegionCodeMap.put(423, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FK");
+ countryCodeToRegionCodeMap.put(500, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BZ");
+ countryCodeToRegionCodeMap.put(501, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GT");
+ countryCodeToRegionCodeMap.put(502, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SV");
+ countryCodeToRegionCodeMap.put(503, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HN");
+ countryCodeToRegionCodeMap.put(504, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NI");
+ countryCodeToRegionCodeMap.put(505, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CR");
+ countryCodeToRegionCodeMap.put(506, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PA");
+ countryCodeToRegionCodeMap.put(507, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PM");
+ countryCodeToRegionCodeMap.put(508, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HT");
+ countryCodeToRegionCodeMap.put(509, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(3);
+ listWithRegionCode.add("GP");
+ listWithRegionCode.add("BL");
+ listWithRegionCode.add("MF");
+ countryCodeToRegionCodeMap.put(590, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BO");
+ countryCodeToRegionCodeMap.put(591, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GY");
+ countryCodeToRegionCodeMap.put(592, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("EC");
+ countryCodeToRegionCodeMap.put(593, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GF");
+ countryCodeToRegionCodeMap.put(594, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PY");
+ countryCodeToRegionCodeMap.put(595, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MQ");
+ countryCodeToRegionCodeMap.put(596, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SR");
+ countryCodeToRegionCodeMap.put(597, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("UY");
+ countryCodeToRegionCodeMap.put(598, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("CW");
+ listWithRegionCode.add("BQ");
+ countryCodeToRegionCodeMap.put(599, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TL");
+ countryCodeToRegionCodeMap.put(670, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NF");
+ countryCodeToRegionCodeMap.put(672, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BN");
+ countryCodeToRegionCodeMap.put(673, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NR");
+ countryCodeToRegionCodeMap.put(674, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PG");
+ countryCodeToRegionCodeMap.put(675, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TO");
+ countryCodeToRegionCodeMap.put(676, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SB");
+ countryCodeToRegionCodeMap.put(677, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("VU");
+ countryCodeToRegionCodeMap.put(678, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FJ");
+ countryCodeToRegionCodeMap.put(679, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PW");
+ countryCodeToRegionCodeMap.put(680, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("WF");
+ countryCodeToRegionCodeMap.put(681, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CK");
+ countryCodeToRegionCodeMap.put(682, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NU");
+ countryCodeToRegionCodeMap.put(683, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("WS");
+ countryCodeToRegionCodeMap.put(685, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KI");
+ countryCodeToRegionCodeMap.put(686, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NC");
+ countryCodeToRegionCodeMap.put(687, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TV");
+ countryCodeToRegionCodeMap.put(688, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PF");
+ countryCodeToRegionCodeMap.put(689, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TK");
+ countryCodeToRegionCodeMap.put(690, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FM");
+ countryCodeToRegionCodeMap.put(691, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MH");
+ countryCodeToRegionCodeMap.put(692, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(800, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(808, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KP");
+ countryCodeToRegionCodeMap.put(850, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HK");
+ countryCodeToRegionCodeMap.put(852, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MO");
+ countryCodeToRegionCodeMap.put(853, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KH");
+ countryCodeToRegionCodeMap.put(855, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LA");
+ countryCodeToRegionCodeMap.put(856, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(870, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(878, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BD");
+ countryCodeToRegionCodeMap.put(880, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(881, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(882, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(883, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TW");
+ countryCodeToRegionCodeMap.put(886, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(888, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MV");
+ countryCodeToRegionCodeMap.put(960, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("LB");
+ countryCodeToRegionCodeMap.put(961, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("JO");
+ countryCodeToRegionCodeMap.put(962, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SY");
+ countryCodeToRegionCodeMap.put(963, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IQ");
+ countryCodeToRegionCodeMap.put(964, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KW");
+ countryCodeToRegionCodeMap.put(965, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SA");
+ countryCodeToRegionCodeMap.put(966, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("YE");
+ countryCodeToRegionCodeMap.put(967, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("OM");
+ countryCodeToRegionCodeMap.put(968, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PS");
+ countryCodeToRegionCodeMap.put(970, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AE");
+ countryCodeToRegionCodeMap.put(971, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IL");
+ countryCodeToRegionCodeMap.put(972, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BH");
+ countryCodeToRegionCodeMap.put(973, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("QA");
+ countryCodeToRegionCodeMap.put(974, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BT");
+ countryCodeToRegionCodeMap.put(975, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MN");
+ countryCodeToRegionCodeMap.put(976, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NP");
+ countryCodeToRegionCodeMap.put(977, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(979, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TJ");
+ countryCodeToRegionCodeMap.put(992, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("TM");
+ countryCodeToRegionCodeMap.put(993, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AZ");
+ countryCodeToRegionCodeMap.put(994, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("GE");
+ countryCodeToRegionCodeMap.put(995, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KG");
+ countryCodeToRegionCodeMap.put(996, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("UZ");
+ countryCodeToRegionCodeMap.put(998, listWithRegionCode);
+
+ return countryCodeToRegionCodeMap;
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/MetadataLoader.java b/libphonenumber/src/com/google/i18n/phonenumbers/MetadataLoader.java
new file mode 100644
index 00000000..1ab3e931
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/MetadataLoader.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.io.InputStream;
+
+/**
+ * Interface for caller to specify a customized phone metadata loader.
+ */
+public interface MetadataLoader {
+ /**
+ * Returns an input stream corresponding to the metadata to load.
+ *
+ * @param metadataFileName File name (including path) of metadata to load. File path is an
+ * absolute class path like /com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto.
+ * @return The input stream for the metadata file. The library will close this stream
+ * after it is done. Return null in case the metadata file could not be found.
+ */
+ public InputStream loadMetadata(String metadataFileName);
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java b/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java
new file mode 100644
index 00000000..e6f44dee
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class encapsulating loading of PhoneNumber Metadata information. Currently this is used only for
+ * additional data files such as PhoneNumberAlternateFormats, but in the future it is envisaged it
+ * would handle the main metadata file (PhoneNumberMetadata.xml) as well.
+ */
+class MetadataManager {
+ private static final String ALTERNATE_FORMATS_FILE_PREFIX =
+ "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto";
+ private static final String SHORT_NUMBER_METADATA_FILE_PREFIX =
+ "/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto";
+
+ private static final Logger LOGGER = Logger.getLogger(MetadataManager.class.getName());
+
+ private static final Map<Integer, PhoneMetadata> callingCodeToAlternateFormatsMap =
+ Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
+ private static final Map<String, PhoneMetadata> regionCodeToShortNumberMetadataMap =
+ Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
+
+ // A set of which country calling codes there are alternate format data for. If the set has an
+ // entry for a code, then there should be data for that code linked into the resources.
+ private static final Set<Integer> countryCodeSet =
+ AlternateFormatsCountryCodeSet.getCountryCodeSet();
+
+ // A set of which region codes there are short number data for. If the set has an entry for a
+ // code, then there should be data for that code linked into the resources.
+ private static final Set<String> regionCodeSet = ShortNumbersRegionCodeSet.getRegionCodeSet();
+
+ private MetadataManager() {
+ }
+
+ private static void close(InputStream in) {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ LOGGER.log(Level.WARNING, e.toString());
+ }
+ }
+ }
+
+ private static void loadAlternateFormatsMetadataFromFile(int countryCallingCode) {
+ InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
+ ALTERNATE_FORMATS_FILE_PREFIX + "_" + countryCallingCode);
+ ObjectInputStream in = null;
+ try {
+ in = new ObjectInputStream(source);
+ PhoneMetadataCollection alternateFormats = new PhoneMetadataCollection();
+ alternateFormats.readExternal(in);
+ for (PhoneMetadata metadata : alternateFormats.getMetadataList()) {
+ callingCodeToAlternateFormatsMap.put(metadata.getCountryCode(), metadata);
+ }
+ } catch (IOException e) {
+ LOGGER.log(Level.WARNING, e.toString());
+ } finally {
+ close(in);
+ }
+ }
+
+ static PhoneMetadata getAlternateFormatsForCountry(int countryCallingCode) {
+ if (!countryCodeSet.contains(countryCallingCode)) {
+ return null;
+ }
+ synchronized (callingCodeToAlternateFormatsMap) {
+ if (!callingCodeToAlternateFormatsMap.containsKey(countryCallingCode)) {
+ loadAlternateFormatsMetadataFromFile(countryCallingCode);
+ }
+ }
+ return callingCodeToAlternateFormatsMap.get(countryCallingCode);
+ }
+
+ private static void loadShortNumberMetadataFromFile(String regionCode) {
+ InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
+ SHORT_NUMBER_METADATA_FILE_PREFIX + "_" + regionCode);
+ ObjectInputStream in = null;
+ try {
+ in = new ObjectInputStream(source);
+ PhoneMetadataCollection shortNumberMetadata = new PhoneMetadataCollection();
+ shortNumberMetadata.readExternal(in);
+ for (PhoneMetadata metadata : shortNumberMetadata.getMetadataList()) {
+ regionCodeToShortNumberMetadataMap.put(regionCode, metadata);
+ }
+ } catch (IOException e) {
+ LOGGER.log(Level.WARNING, e.toString());
+ } finally {
+ close(in);
+ }
+ }
+
+ // @VisibleForTesting
+ static Set<String> getShortNumberMetadataSupportedRegions() {
+ return regionCodeSet;
+ }
+
+ static PhoneMetadata getShortNumberMetadataForRegion(String regionCode) {
+ if (!regionCodeSet.contains(regionCode)) {
+ return null;
+ }
+ synchronized (regionCodeToShortNumberMetadataMap) {
+ if (!regionCodeToShortNumberMetadataMap.containsKey(regionCode)) {
+ loadShortNumberMetadataFromFile(regionCode);
+ }
+ }
+ return regionCodeToShortNumberMetadataMap.get(regionCode);
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java b/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java
new file mode 100644
index 00000000..082fcc81
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 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;
+
+/**
+ * Generic exception class for errors encountered when parsing phone numbers.
+ */
+@SuppressWarnings("serial")
+public class NumberParseException extends Exception {
+
+ public enum ErrorType {
+ INVALID_COUNTRY_CODE,
+ // This generally indicates the string passed in had less than 3 digits in it. More
+ // specifically, the number failed to match the regular expression VALID_PHONE_NUMBER in
+ // PhoneNumberUtil.java.
+ NOT_A_NUMBER,
+ // This indicates the string started with an international dialing prefix, but after this was
+ // stripped from the number, had less digits than any valid phone number (including country
+ // code) could have.
+ TOO_SHORT_AFTER_IDD,
+ // This indicates the string, after any country code has been stripped, had less digits than any
+ // valid phone number could have.
+ TOO_SHORT_NSN,
+ // This indicates the string had more digits than any valid phone number could have.
+ TOO_LONG,
+ }
+
+ private ErrorType errorType;
+ private String message;
+
+ public NumberParseException(ErrorType errorType, String message) {
+ super(message);
+ this.message = message;
+ this.errorType = errorType;
+ }
+
+ /**
+ * Returns the error type of the exception that has been thrown.
+ */
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+
+ @Override
+ public String toString() {
+ return "Error type: " + errorType + ". " + message;
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java
new file mode 100644
index 00000000..4ce3cabd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011 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;
+
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import java.util.Arrays;
+
+/**
+ * The immutable match of a phone number within a piece of text. Matches may be found using
+ * {@link PhoneNumberUtil#findNumbers}.
+ *
+ * <p>A match consists of the {@linkplain #number() phone number} as well as the
+ * {@linkplain #start() start} and {@linkplain #end() end} offsets of the corresponding subsequence
+ * of the searched text. Use {@link #rawString()} to obtain a copy of the matched subsequence.
+ *
+ * <p>The following annotated example clarifies the relationship between the searched text, the
+ * match offsets, and the parsed number:
+
+ * <pre>
+ * CharSequence text = "Call me at +1 425 882-8080 for details.";
+ * RegionCode country = RegionCode.US;
+ * PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ *
+ * // Find the first phone number match:
+ * PhoneNumberMatch m = util.findNumbers(text, country).iterator().next();
+ *
+ * // rawString() contains the phone number as it appears in the text.
+ * "+1 425 882-8080".equals(m.rawString());
+ *
+ * // start() and end() define the range of the matched subsequence.
+ * CharSequence subsequence = text.subSequence(m.start(), m.end());
+ * "+1 425 882-8080".contentEquals(subsequence);
+ *
+ * // number() returns the the same result as PhoneNumberUtil.{@link PhoneNumberUtil#parse parse()}
+ * // invoked on rawString().
+ * util.parse(m.rawString(), country).equals(m.number());
+ * </pre>
+ */
+public final class PhoneNumberMatch {
+ /** The start index into the text. */
+ private final int start;
+ /** The raw substring matched. */
+ private final String rawString;
+ /** The matched phone number. */
+ private final PhoneNumber number;
+
+ /**
+ * Creates a new match.
+ *
+ * @param start the start index into the target text
+ * @param rawString the matched substring of the target text
+ * @param number the matched phone number
+ */
+ PhoneNumberMatch(int start, String rawString, PhoneNumber number) {
+ if (start < 0) {
+ throw new IllegalArgumentException("Start index must be >= 0.");
+ }
+ if (rawString == null || number == null) {
+ throw new NullPointerException();
+ }
+ this.start = start;
+ this.rawString = rawString;
+ this.number = number;
+ }
+
+ /** Returns the phone number matched by the receiver. */
+ public PhoneNumber number() {
+ return number;
+ }
+
+ /** Returns the start index of the matched phone number within the searched text. */
+ public int start() {
+ return start;
+ }
+
+ /** Returns the exclusive end index of the matched phone number within the searched text. */
+ public int end() {
+ return start + rawString.length();
+ }
+
+ /** Returns the raw string matched as a phone number in the searched text. */
+ public String rawString() {
+ return rawString;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(new Object[]{start, rawString, number});
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof PhoneNumberMatch)) {
+ return false;
+ }
+ PhoneNumberMatch other = (PhoneNumberMatch) obj;
+ return rawString.equals(other.rawString) && (start == other.start) &&
+ number.equals(other.number);
+ }
+
+ @Override
+ public String toString() {
+ return "PhoneNumberMatch [" + start() + "," + end() + ") " + rawString;
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java
new file mode 100644
index 00000000..34e8d163
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java
@@ -0,0 +1,725 @@
+/*
+ * Copyright (C) 2011 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;
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil.Leniency;
+import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType;
+import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import java.lang.Character.UnicodeBlock;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A stateful class that finds and extracts telephone numbers from {@linkplain CharSequence text}.
+ * Instances can be created using the {@linkplain PhoneNumberUtil#findNumbers factory methods} in
+ * {@link PhoneNumberUtil}.
+ *
+ * <p>Vanity numbers (phone numbers using alphabetic digits such as <tt>1-800-SIX-FLAGS</tt> are
+ * not found.
+ *
+ * <p>This class is not thread-safe.
+ */
+final class PhoneNumberMatcher implements Iterator<PhoneNumberMatch> {
+ /**
+ * The phone number pattern used by {@link #find}, similar to
+ * {@code PhoneNumberUtil.VALID_PHONE_NUMBER}, but with the following differences:
+ * <ul>
+ * <li>All captures are limited in order to place an upper bound to the text matched by the
+ * pattern.
+ * <ul>
+ * <li>Leading punctuation / plus signs are limited.
+ * <li>Consecutive occurrences of punctuation are limited.
+ * <li>Number of digits is limited.
+ * </ul>
+ * <li>No whitespace is allowed at the start or end.
+ * <li>No alpha digits (vanity numbers such as 1-800-SIX-FLAGS) are currently supported.
+ * </ul>
+ */
+ private static final Pattern PATTERN;
+ /**
+ * Matches strings that look like publication pages. Example:
+ * <pre>Computing Complete Answers to Queries in the Presence of Limited Access Patterns.
+ * Chen Li. VLDB J. 12(3): 211-227 (2003).</pre>
+ *
+ * The string "211-227 (2003)" is not a telephone number.
+ */
+ private static final Pattern PUB_PAGES = Pattern.compile("\\d{1,5}-+\\d{1,5}\\s{0,4}\\(\\d{1,4}");
+
+ /**
+ * Matches strings that look like dates using "/" as a separator. Examples: 3/10/2011, 31/10/96 or
+ * 08/31/95.
+ */
+ private static final Pattern SLASH_SEPARATED_DATES =
+ Pattern.compile("(?:(?:[0-3]?\\d/[01]?\\d)|(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}");
+
+ /**
+ * Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does not include the
+ * trailing ":\d\d" -- that is covered by TIME_STAMPS_SUFFIX.
+ */
+ private static final Pattern TIME_STAMPS =
+ Pattern.compile("[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d +[0-2]\\d$");
+ private static final Pattern TIME_STAMPS_SUFFIX = Pattern.compile(":[0-5]\\d");
+
+ /**
+ * Pattern to check that brackets match. Opening brackets should be closed within a phone number.
+ * This also checks that there is something inside the brackets. Having no brackets at all is also
+ * fine.
+ */
+ private static final Pattern MATCHING_BRACKETS;
+
+ /**
+ * Patterns used to extract phone numbers from a larger phone-number-like pattern. These are
+ * ordered according to specificity. For example, white-space is last since that is frequently
+ * used in numbers, not just to separate two numbers. We have separate patterns since we don't
+ * want to break up the phone-number-like text on more than one different kind of symbol at one
+ * time, although symbols of the same type (e.g. space) can be safely grouped together.
+ *
+ * Note that if there is a match, we will always check any text found up to the first match as
+ * well.
+ */
+ private static final Pattern[] INNER_MATCHES = {
+ // Breaks on the slash - e.g. "651-234-2345/332-445-1234"
+ Pattern.compile("/+(.*)"),
+ // Note that the bracket here is inside the capturing group, since we consider it part of the
+ // phone number. Will match a pattern like "(650) 223 3345 (754) 223 3321".
+ Pattern.compile("(\\([^(]*)"),
+ // Breaks on a hyphen - e.g. "12345 - 332-445-1234 is my number."
+ // We require a space on either side of the hyphen for it to be considered a separator.
+ Pattern.compile("(?:\\p{Z}-|-\\p{Z})\\p{Z}*(.+)"),
+ // Various types of wide hyphens. Note we have decided not to enforce a space here, since it's
+ // possible that it's supposed to be used to break two numbers without spaces, and we haven't
+ // seen many instances of it used within a number.
+ Pattern.compile("[\u2012-\u2015\uFF0D]\\p{Z}*(.+)"),
+ // Breaks on a full stop - e.g. "12345. 332-445-1234 is my number."
+ Pattern.compile("\\.+\\p{Z}*([^.]+)"),
+ // Breaks on space - e.g. "3324451234 8002341234"
+ Pattern.compile("\\p{Z}+(\\P{Z}+)")
+ };
+
+ /**
+ * Punctuation that may be at the start of a phone number - brackets and plus signs.
+ */
+ private static final Pattern LEAD_CLASS;
+
+ static {
+ /* Builds the MATCHING_BRACKETS and PATTERN regular expressions. The building blocks below exist
+ * to make the pattern more easily understood. */
+
+ String openingParens = "(\\[\uFF08\uFF3B";
+ String closingParens = ")\\]\uFF09\uFF3D";
+ String nonParens = "[^" + openingParens + closingParens + "]";
+
+ /* Limit on the number of pairs of brackets in a phone number. */
+ String bracketPairLimit = limit(0, 3);
+ /*
+ * An opening bracket at the beginning may not be closed, but subsequent ones should be. It's
+ * also possible that the leading bracket was dropped, so we shouldn't be surprised if we see a
+ * closing bracket first. We limit the sets of brackets in a phone number to four.
+ */
+ MATCHING_BRACKETS = Pattern.compile(
+ "(?:[" + openingParens + "])?" + "(?:" + nonParens + "+" + "[" + closingParens + "])?" +
+ nonParens + "+" +
+ "(?:[" + openingParens + "]" + nonParens + "+[" + closingParens + "])" + bracketPairLimit +
+ nonParens + "*");
+
+ /* Limit on the number of leading (plus) characters. */
+ String leadLimit = limit(0, 2);
+ /* Limit on the number of consecutive punctuation characters. */
+ String punctuationLimit = limit(0, 4);
+ /* The maximum number of digits allowed in a digit-separated block. As we allow all digits in a
+ * single block, set high enough to accommodate the entire national number and the international
+ * country code. */
+ int digitBlockLimit =
+ PhoneNumberUtil.MAX_LENGTH_FOR_NSN + PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE;
+ /* Limit on the number of blocks separated by punctuation. Uses digitBlockLimit since some
+ * formats use spaces to separate each digit. */
+ String blockLimit = limit(0, digitBlockLimit);
+
+ /* A punctuation sequence allowing white space. */
+ String punctuation = "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]" + punctuationLimit;
+ /* A digits block without punctuation. */
+ String digitSequence = "\\p{Nd}" + limit(1, digitBlockLimit);
+
+ String leadClassChars = openingParens + PhoneNumberUtil.PLUS_CHARS;
+ String leadClass = "[" + leadClassChars + "]";
+ LEAD_CLASS = Pattern.compile(leadClass);
+
+ /* Phone number pattern allowing optional punctuation. */
+ PATTERN = Pattern.compile(
+ "(?:" + leadClass + punctuation + ")" + leadLimit +
+ digitSequence + "(?:" + punctuation + digitSequence + ")" + blockLimit +
+ "(?:" + PhoneNumberUtil.EXTN_PATTERNS_FOR_MATCHING + ")?",
+ PhoneNumberUtil.REGEX_FLAGS);
+ }
+
+ /** Returns a regular expression quantifier with an upper and lower limit. */
+ private static String limit(int lower, int upper) {
+ if ((lower < 0) || (upper <= 0) || (upper < lower)) {
+ throw new IllegalArgumentException();
+ }
+ return "{" + lower + "," + upper + "}";
+ }
+
+ /** The potential states of a PhoneNumberMatcher. */
+ private enum State {
+ NOT_READY, READY, DONE
+ }
+
+ /** The phone number utility. */
+ private final PhoneNumberUtil phoneUtil;
+ /** The text searched for phone numbers. */
+ private final CharSequence text;
+ /**
+ * The region (country) to assume for phone numbers without an international prefix, possibly
+ * null.
+ */
+ private final String preferredRegion;
+ /** The degree of validation requested. */
+ private final Leniency leniency;
+ /** The maximum number of retries after matching an invalid number. */
+ private long maxTries;
+
+ /** The iteration tristate. */
+ private State state = State.NOT_READY;
+ /** The last successful match, null unless in {@link State#READY}. */
+ private PhoneNumberMatch lastMatch = null;
+ /** The next index to start searching at. Undefined in {@link State#DONE}. */
+ private int searchIndex = 0;
+
+ /**
+ * Creates a new instance. See the factory methods in {@link PhoneNumberUtil} on how to obtain a
+ * new instance.
+ *
+ * @param util the phone number util to use
+ * @param text the character sequence that we will search, null for no text
+ * @param country the country to assume for phone numbers not written in international format
+ * (with a leading plus, or with the international dialing prefix of the
+ * specified region). May be null or "ZZ" if only numbers with a
+ * leading plus should be considered.
+ * @param leniency the leniency to use when evaluating candidate phone numbers
+ * @param maxTries the maximum number of invalid numbers to try before giving up on the text.
+ * This is to cover degenerate cases where the text has a lot of false positives
+ * in it. Must be {@code >= 0}.
+ */
+ PhoneNumberMatcher(PhoneNumberUtil util, CharSequence text, String country, Leniency leniency,
+ long maxTries) {
+
+ if ((util == null) || (leniency == null)) {
+ throw new NullPointerException();
+ }
+ if (maxTries < 0) {
+ throw new IllegalArgumentException();
+ }
+ this.phoneUtil = util;
+ this.text = (text != null) ? text : "";
+ this.preferredRegion = country;
+ this.leniency = leniency;
+ this.maxTries = maxTries;
+ }
+
+ /**
+ * Attempts to find the next subsequence in the searched sequence on or after {@code searchIndex}
+ * that represents a phone number. Returns the next match, null if none was found.
+ *
+ * @param index the search index to start searching at
+ * @return the phone number match found, null if none can be found
+ */
+ private PhoneNumberMatch find(int index) {
+ Matcher matcher = PATTERN.matcher(text);
+ while ((maxTries > 0) && matcher.find(index)) {
+ int start = matcher.start();
+ CharSequence candidate = text.subSequence(start, matcher.end());
+
+ // Check for extra numbers at the end.
+ // TODO: This is the place to start when trying to support extraction of multiple phone number
+ // from split notations (+41 79 123 45 67 / 68).
+ candidate = trimAfterFirstMatch(PhoneNumberUtil.SECOND_NUMBER_START_PATTERN, candidate);
+
+ PhoneNumberMatch match = extractMatch(candidate, start);
+ if (match != null) {
+ return match;
+ }
+
+ index = start + candidate.length();
+ maxTries--;
+ }
+
+ return null;
+ }
+
+ /**
+ * Trims away any characters after the first match of {@code pattern} in {@code candidate},
+ * returning the trimmed version.
+ */
+ private static CharSequence trimAfterFirstMatch(Pattern pattern, CharSequence candidate) {
+ Matcher trailingCharsMatcher = pattern.matcher(candidate);
+ if (trailingCharsMatcher.find()) {
+ candidate = candidate.subSequence(0, trailingCharsMatcher.start());
+ }
+ return candidate;
+ }
+
+ /**
+ * Helper method to determine if a character is a Latin-script letter or not. For our purposes,
+ * combining marks should also return true since we assume they have been added to a preceding
+ * Latin character.
+ */
+ // @VisibleForTesting
+ static boolean isLatinLetter(char letter) {
+ // Combining marks are a subset of non-spacing-mark.
+ if (!Character.isLetter(letter) && Character.getType(letter) != Character.NON_SPACING_MARK) {
+ return false;
+ }
+ UnicodeBlock block = UnicodeBlock.of(letter);
+ return block.equals(UnicodeBlock.BASIC_LATIN) ||
+ block.equals(UnicodeBlock.LATIN_1_SUPPLEMENT) ||
+ block.equals(UnicodeBlock.LATIN_EXTENDED_A) ||
+ block.equals(UnicodeBlock.LATIN_EXTENDED_ADDITIONAL) ||
+ block.equals(UnicodeBlock.LATIN_EXTENDED_B) ||
+ block.equals(UnicodeBlock.COMBINING_DIACRITICAL_MARKS);
+ }
+
+ private static boolean isInvalidPunctuationSymbol(char character) {
+ return character == '%' || Character.getType(character) == Character.CURRENCY_SYMBOL;
+ }
+
+ /**
+ * Attempts to extract a match from a {@code candidate} character sequence.
+ *
+ * @param candidate the candidate text that might contain a phone number
+ * @param offset the offset of {@code candidate} within {@link #text}
+ * @return the match found, null if none can be found
+ */
+ private PhoneNumberMatch extractMatch(CharSequence candidate, int offset) {
+ // Skip a match that is more likely to be a date.
+ if (SLASH_SEPARATED_DATES.matcher(candidate).find()) {
+ return null;
+ }
+
+ // Skip potential time-stamps.
+ if (TIME_STAMPS.matcher(candidate).find()) {
+ String followingText = text.toString().substring(offset + candidate.length());
+ if (TIME_STAMPS_SUFFIX.matcher(followingText).lookingAt()) {
+ return null;
+ }
+ }
+
+ // Try to come up with a valid match given the entire candidate.
+ String rawString = candidate.toString();
+ PhoneNumberMatch match = parseAndVerify(rawString, offset);
+ if (match != null) {
+ return match;
+ }
+
+ // If that failed, try to find an "inner match" - there might be a phone number within this
+ // candidate.
+ return extractInnerMatch(rawString, offset);
+ }
+
+ /**
+ * Attempts to extract a match from {@code candidate} if the whole candidate does not qualify as a
+ * match.
+ *
+ * @param candidate the candidate text that might contain a phone number
+ * @param offset the current offset of {@code candidate} within {@link #text}
+ * @return the match found, null if none can be found
+ */
+ private PhoneNumberMatch extractInnerMatch(String candidate, int offset) {
+ for (Pattern possibleInnerMatch : INNER_MATCHES) {
+ int rangeStart = 0;
+ Matcher groupMatcher = possibleInnerMatch.matcher(candidate);
+ boolean isFirstMatch = true;
+ while (groupMatcher.find() && maxTries > 0) {
+ if (isFirstMatch) {
+ // We should handle any group before this one too.
+ CharSequence group = trimAfterFirstMatch(
+ PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN,
+ candidate.substring(0, groupMatcher.start()));
+ PhoneNumberMatch match = parseAndVerify(group.toString(), offset);
+ if (match != null) {
+ return match;
+ }
+ maxTries--;
+ isFirstMatch = false;
+ }
+ CharSequence group = trimAfterFirstMatch(
+ PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, groupMatcher.group(1));
+ PhoneNumberMatch match = parseAndVerify(group.toString(), offset + groupMatcher.start(1));
+ if (match != null) {
+ return match;
+ }
+ maxTries--;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and
+ * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a
+ * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null.
+ *
+ * @param candidate the candidate match
+ * @param offset the offset of {@code candidate} within {@link #text}
+ * @return the parsed and validated phone number match, or null
+ */
+ private PhoneNumberMatch parseAndVerify(String candidate, int offset) {
+ try {
+ // Check the candidate doesn't contain any formatting which would indicate that it really
+ // isn't a phone number.
+ if (!MATCHING_BRACKETS.matcher(candidate).matches() || PUB_PAGES.matcher(candidate).find()) {
+ return null;
+ }
+
+ // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded
+ // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def.
+ if (leniency.compareTo(Leniency.VALID) >= 0) {
+ // If the candidate is not at the start of the text, and does not start with phone-number
+ // punctuation, check the previous character.
+ if (offset > 0 && !LEAD_CLASS.matcher(candidate).lookingAt()) {
+ char previousChar = text.charAt(offset - 1);
+ // We return null if it is a latin letter or an invalid punctuation symbol.
+ if (isInvalidPunctuationSymbol(previousChar) || isLatinLetter(previousChar)) {
+ return null;
+ }
+ }
+ int lastCharIndex = offset + candidate.length();
+ if (lastCharIndex < text.length()) {
+ char nextChar = text.charAt(lastCharIndex);
+ if (isInvalidPunctuationSymbol(nextChar) || isLatinLetter(nextChar)) {
+ return null;
+ }
+ }
+ }
+
+ PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion);
+
+ // Check Israel * numbers: these are a special case in that they are four-digit numbers that
+ // our library supports, but they can only be dialled with a leading *. Since we don't
+ // actually store or detect the * in our phone number library, this means in practice we
+ // detect most four digit numbers as being valid for Israel. We are considering moving these
+ // numbers to ShortNumberInfo instead, in which case this problem would go away, but in the
+ // meantime we want to restrict the false matches so we only allow these numbers if they are
+ // preceded by a star. We enforce this for all leniency levels even though these numbers are
+ // technically accepted by isPossibleNumber and isValidNumber since we consider it to be a
+ // deficiency in those methods that they accept these numbers without the *.
+ // TODO: Remove this or make it significantly less hacky once we've decided how to
+ // handle these short codes going forward in ShortNumberInfo. We could use the formatting
+ // rules for instance, but that would be slower.
+ if (phoneUtil.getRegionCodeForCountryCode(number.getCountryCode()).equals("IL") &&
+ phoneUtil.getNationalSignificantNumber(number).length() == 4 &&
+ (offset == 0 || (offset > 0 && text.charAt(offset - 1) != '*'))) {
+ // No match.
+ return null;
+ }
+
+ if (leniency.verify(number, candidate, phoneUtil)) {
+ // We used parseAndKeepRawInput to create this number, but for now we don't return the extra
+ // values parsed. TODO: stop clearing all values here and switch all users over
+ // to using rawInput() rather than the rawString() of PhoneNumberMatch.
+ number.clearCountryCodeSource();
+ number.clearRawInput();
+ number.clearPreferredDomesticCarrierCode();
+ return new PhoneNumberMatch(offset, candidate, number);
+ }
+ } catch (NumberParseException e) {
+ // ignore and continue
+ }
+ return null;
+ }
+
+ /**
+ * Small helper interface such that the number groups can be checked according to different
+ * criteria, both for our default way of performing formatting and for any alternate formats we
+ * may want to check.
+ */
+ interface NumberGroupingChecker {
+ /**
+ * Returns true if the groups of digits found in our candidate phone number match our
+ * expectations.
+ *
+ * @param number the original number we found when parsing
+ * @param normalizedCandidate the candidate number, normalized to only contain ASCII digits,
+ * but with non-digits (spaces etc) retained
+ * @param expectedNumberGroups the groups of digits that we would expect to see if we
+ * formatted this number
+ */
+ boolean checkGroups(PhoneNumberUtil util, PhoneNumber number,
+ StringBuilder normalizedCandidate, String[] expectedNumberGroups);
+ }
+
+ static boolean allNumberGroupsRemainGrouped(PhoneNumberUtil util,
+ PhoneNumber number,
+ StringBuilder normalizedCandidate,
+ String[] formattedNumberGroups) {
+ int fromIndex = 0;
+ if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) {
+ // First skip the country code if the normalized candidate contained it.
+ String countryCode = Integer.toString(number.getCountryCode());
+ fromIndex = normalizedCandidate.indexOf(countryCode) + countryCode.length();
+ }
+ // Check each group of consecutive digits are not broken into separate groupings in the
+ // {@code normalizedCandidate} string.
+ for (int i = 0; i < formattedNumberGroups.length; i++) {
+ // Fails if the substring of {@code normalizedCandidate} starting from {@code fromIndex}
+ // doesn't contain the consecutive digits in formattedNumberGroups[i].
+ fromIndex = normalizedCandidate.indexOf(formattedNumberGroups[i], fromIndex);
+ if (fromIndex < 0) {
+ return false;
+ }
+ // Moves {@code fromIndex} forward.
+ fromIndex += formattedNumberGroups[i].length();
+ if (i == 0 && fromIndex < normalizedCandidate.length()) {
+ // We are at the position right after the NDC. We get the region used for formatting
+ // information based on the country code in the phone number, rather than the number itself,
+ // as we do not need to distinguish between different countries with the same country
+ // calling code and this is faster.
+ String region = util.getRegionCodeForCountryCode(number.getCountryCode());
+ if (util.getNddPrefixForRegion(region, true) != null &&
+ Character.isDigit(normalizedCandidate.charAt(fromIndex))) {
+ // This means there is no formatting symbol after the NDC. In this case, we only
+ // accept the number if there is no formatting symbol at all in the number, except
+ // for extensions. This is only important for countries with national prefixes.
+ String nationalSignificantNumber = util.getNationalSignificantNumber(number);
+ return normalizedCandidate.substring(fromIndex - formattedNumberGroups[i].length())
+ .startsWith(nationalSignificantNumber);
+ }
+ }
+ }
+ // The check here makes sure that we haven't mistakenly already used the extension to
+ // match the last group of the subscriber number. Note the extension cannot have
+ // formatting in-between digits.
+ return normalizedCandidate.substring(fromIndex).contains(number.getExtension());
+ }
+
+ static boolean allNumberGroupsAreExactlyPresent(PhoneNumberUtil util,
+ PhoneNumber number,
+ StringBuilder normalizedCandidate,
+ String[] formattedNumberGroups) {
+ String[] candidateGroups =
+ PhoneNumberUtil.NON_DIGITS_PATTERN.split(normalizedCandidate.toString());
+ // Set this to the last group, skipping it if the number has an extension.
+ int candidateNumberGroupIndex =
+ number.hasExtension() ? candidateGroups.length - 2 : candidateGroups.length - 1;
+ // First we check if the national significant number is formatted as a block.
+ // We use contains and not equals, since the national significant number may be present with
+ // a prefix such as a national number prefix, or the country code itself.
+ if (candidateGroups.length == 1 ||
+ candidateGroups[candidateNumberGroupIndex].contains(
+ util.getNationalSignificantNumber(number))) {
+ return true;
+ }
+ // Starting from the end, go through in reverse, excluding the first group, and check the
+ // candidate and number groups are the same.
+ for (int formattedNumberGroupIndex = (formattedNumberGroups.length - 1);
+ formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0;
+ formattedNumberGroupIndex--, candidateNumberGroupIndex--) {
+ if (!candidateGroups[candidateNumberGroupIndex].equals(
+ formattedNumberGroups[formattedNumberGroupIndex])) {
+ return false;
+ }
+ }
+ // Now check the first group. There may be a national prefix at the start, so we only check
+ // that the candidate group ends with the formatted number group.
+ return (candidateNumberGroupIndex >= 0 &&
+ candidateGroups[candidateNumberGroupIndex].endsWith(formattedNumberGroups[0]));
+ }
+
+ /**
+ * Helper method to get the national-number part of a number, formatted without any national
+ * prefix, and return it as a set of digit blocks that would be formatted together.
+ */
+ private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number,
+ NumberFormat formattingPattern) {
+ if (formattingPattern == null) {
+ // This will be in the format +CC-DG;ext=EXT where DG represents groups of digits.
+ String rfc3966Format = util.format(number, PhoneNumberFormat.RFC3966);
+ // We remove the extension part from the formatted string before splitting it into different
+ // groups.
+ int endIndex = rfc3966Format.indexOf(';');
+ if (endIndex < 0) {
+ endIndex = rfc3966Format.length();
+ }
+ // The country-code will have a '-' following it.
+ int startIndex = rfc3966Format.indexOf('-') + 1;
+ return rfc3966Format.substring(startIndex, endIndex).split("-");
+ } else {
+ // We format the NSN only, and split that according to the separator.
+ String nationalSignificantNumber = util.getNationalSignificantNumber(number);
+ return util.formatNsnUsingPattern(nationalSignificantNumber,
+ formattingPattern, PhoneNumberFormat.RFC3966).split("-");
+ }
+ }
+
+ static boolean checkNumberGroupingIsValid(
+ PhoneNumber number, String candidate, PhoneNumberUtil util, NumberGroupingChecker checker) {
+ // TODO: Evaluate how this works for other locales (testing has been limited to NANPA regions)
+ // and optimise if necessary.
+ StringBuilder normalizedCandidate =
+ PhoneNumberUtil.normalizeDigits(candidate, true /* keep non-digits */);
+ String[] formattedNumberGroups = getNationalNumberGroups(util, number, null);
+ if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) {
+ return true;
+ }
+ // If this didn't pass, see if there are any alternate formats, and try them instead.
+ PhoneMetadata alternateFormats =
+ MetadataManager.getAlternateFormatsForCountry(number.getCountryCode());
+ if (alternateFormats != null) {
+ for (NumberFormat alternateFormat : alternateFormats.numberFormats()) {
+ formattedNumberGroups = getNationalNumberGroups(util, number, alternateFormat);
+ if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ static boolean containsMoreThanOneSlashInNationalNumber(PhoneNumber number, String candidate) {
+ int firstSlashInBodyIndex = candidate.indexOf('/');
+ if (firstSlashInBodyIndex < 0) {
+ // No slashes, this is okay.
+ return false;
+ }
+ // Now look for a second one.
+ int secondSlashInBodyIndex = candidate.indexOf('/', firstSlashInBodyIndex + 1);
+ if (secondSlashInBodyIndex < 0) {
+ // Only one slash, this is okay.
+ return false;
+ }
+
+ // If the first slash is after the country calling code, this is permitted.
+ boolean candidateHasCountryCode =
+ (number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN ||
+ number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
+ if (candidateHasCountryCode &&
+ PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(0, firstSlashInBodyIndex))
+ .equals(Integer.toString(number.getCountryCode()))) {
+ // Any more slashes and this is illegal.
+ return candidate.substring(secondSlashInBodyIndex + 1).contains("/");
+ }
+ return true;
+ }
+
+ static boolean containsOnlyValidXChars(
+ PhoneNumber number, String candidate, PhoneNumberUtil util) {
+ // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the
+ // national significant number or (2) an extension sign, in which case they always precede the
+ // extension number. We assume a carrier code is more than 1 digit, so the first case has to
+ // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x'
+ // or 'X'. We ignore the character if it appears as the last character of the string.
+ for (int index = 0; index < candidate.length() - 1; index++) {
+ char charAtIndex = candidate.charAt(index);
+ if (charAtIndex == 'x' || charAtIndex == 'X') {
+ char charAtNextIndex = candidate.charAt(index + 1);
+ if (charAtNextIndex == 'x' || charAtNextIndex == 'X') {
+ // This is the carrier code case, in which the 'X's always precede the national
+ // significant number.
+ index++;
+ if (util.isNumberMatch(number, candidate.substring(index)) != MatchType.NSN_MATCH) {
+ return false;
+ }
+ // This is the extension sign case, in which the 'x' or 'X' should always precede the
+ // extension number.
+ } else if (!PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(index)).equals(
+ number.getExtension())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ static boolean isNationalPrefixPresentIfRequired(PhoneNumber number, PhoneNumberUtil util) {
+ // First, check how we deduced the country code. If it was written in international format, then
+ // the national prefix is not required.
+ if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) {
+ return true;
+ }
+ String phoneNumberRegion =
+ util.getRegionCodeForCountryCode(number.getCountryCode());
+ PhoneMetadata metadata = util.getMetadataForRegion(phoneNumberRegion);
+ if (metadata == null) {
+ return true;
+ }
+ // Check if a national prefix should be present when formatting this number.
+ String nationalNumber = util.getNationalSignificantNumber(number);
+ NumberFormat formatRule =
+ util.chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber);
+ // To do this, we check that a national prefix formatting rule was present and that it wasn't
+ // just the first-group symbol ($1) with punctuation.
+ if ((formatRule != null) && formatRule.getNationalPrefixFormattingRule().length() > 0) {
+ if (formatRule.isNationalPrefixOptionalWhenFormatting()) {
+ // The national-prefix is optional in these cases, so we don't need to check if it was
+ // present.
+ return true;
+ }
+ if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly(
+ formatRule.getNationalPrefixFormattingRule())) {
+ // National Prefix not needed for this number.
+ return true;
+ }
+ // Normalize the remainder.
+ String rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput());
+ StringBuilder rawInput = new StringBuilder(rawInputCopy);
+ // Check if we found a national prefix and/or carrier code at the start of the raw input, and
+ // return the result.
+ return util.maybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null);
+ }
+ return true;
+ }
+
+ public boolean hasNext() {
+ if (state == State.NOT_READY) {
+ lastMatch = find(searchIndex);
+ if (lastMatch == null) {
+ state = State.DONE;
+ } else {
+ searchIndex = lastMatch.end();
+ state = State.READY;
+ }
+ }
+ return state == State.READY;
+ }
+
+ public PhoneNumberMatch next() {
+ // Check the state and find the next match as a side-effect if necessary.
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ // Don't retain that memory any longer than necessary.
+ PhoneNumberMatch result = lastMatch;
+ lastMatch = null;
+ state = State.NOT_READY;
+ return result;
+ }
+
+ /**
+ * Always throws {@link UnsupportedOperationException} as removal is not supported.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
new file mode 100644
index 00000000..418164a8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
@@ -0,0 +1,3232 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility for international phone numbers. Functionality includes formatting, parsing and
+ * validation.
+ *
+ * <p>If you use this library, and want to be notified about important changes, please sign up to
+ * our <a href="http://groups.google.com/group/libphonenumber-discuss/about">mailing list</a>.
+ *
+ * NOTE: A lot of methods in this class require Region Code strings. These must be provided using
+ * ISO 3166-1 two-letter country-code format. These should be in upper-case. The list of the codes
+ * can be found here:
+ * http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm
+ *
+ * @author Shaopeng Jia
+ */
+public class PhoneNumberUtil {
+ // @VisibleForTesting
+ static final MetadataLoader DEFAULT_METADATA_LOADER = new MetadataLoader() {
+ public InputStream loadMetadata(String metadataFileName) {
+ return PhoneNumberUtil.class.getResourceAsStream(metadataFileName);
+ }
+ };
+
+ private static final Logger logger = Logger.getLogger(PhoneNumberUtil.class.getName());
+
+ /** Flags to use when compiling regular expressions for phone numbers. */
+ static final int REGEX_FLAGS = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE;
+ // The minimum and maximum length of the national significant number.
+ private static final int MIN_LENGTH_FOR_NSN = 2;
+ // The ITU says the maximum length should be 15, but we have found longer numbers in Germany.
+ static final int MAX_LENGTH_FOR_NSN = 17;
+ // The maximum length of the country calling code.
+ static final int MAX_LENGTH_COUNTRY_CODE = 3;
+ // We don't allow input strings for parsing to be longer than 250 chars. This prevents malicious
+ // input from overflowing the regular-expression engine.
+ private static final int MAX_INPUT_STRING_LENGTH = 250;
+
+ private static final String META_DATA_FILE_PREFIX =
+ "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto";
+
+ // Region-code for the unknown region.
+ private static final String UNKNOWN_REGION = "ZZ";
+
+ private static final int NANPA_COUNTRY_CODE = 1;
+
+ // The prefix that needs to be inserted in front of a Colombian landline number when dialed from
+ // a mobile phone in Colombia.
+ private static final String COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX = "3";
+
+ // Map of country calling codes that use a mobile token before the area code. One example of when
+ // this is relevant is when determining the length of the national destination code, which should
+ // be the length of the area code plus the length of the mobile token.
+ private static final Map<Integer, String> MOBILE_TOKEN_MAPPINGS;
+
+ // The PLUS_SIGN signifies the international prefix.
+ static final char PLUS_SIGN = '+';
+
+ private static final char STAR_SIGN = '*';
+
+ private static final String RFC3966_EXTN_PREFIX = ";ext=";
+ private static final String RFC3966_PREFIX = "tel:";
+ private static final String RFC3966_PHONE_CONTEXT = ";phone-context=";
+ 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 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.
+ private static final Map<Character, Character> ALPHA_MAPPINGS;
+
+ // For performance reasons, amalgamate both into one map.
+ private static final Map<Character, Character> ALPHA_PHONE_MAPPINGS;
+
+ // Separate map of all symbols that we wish to retain when formatting alpha numbers. This
+ // includes digits, ASCII letters and number grouping symbols such as "-" and " ".
+ private static final Map<Character, Character> ALL_PLUS_NUMBER_GROUPING_SYMBOLS;
+
+ static {
+ HashMap<Integer, String> mobileTokenMap = new HashMap<Integer, String>();
+ mobileTokenMap.put(52, "1");
+ mobileTokenMap.put(54, "9");
+ MOBILE_TOKEN_MAPPINGS = Collections.unmodifiableMap(mobileTokenMap);
+
+ // Simple ASCII digits map used to populate ALPHA_PHONE_MAPPINGS and
+ // ALL_PLUS_NUMBER_GROUPING_SYMBOLS.
+ HashMap<Character, Character> asciiDigitMappings = new HashMap<Character, Character>();
+ asciiDigitMappings.put('0', '0');
+ asciiDigitMappings.put('1', '1');
+ asciiDigitMappings.put('2', '2');
+ asciiDigitMappings.put('3', '3');
+ asciiDigitMappings.put('4', '4');
+ asciiDigitMappings.put('5', '5');
+ asciiDigitMappings.put('6', '6');
+ asciiDigitMappings.put('7', '7');
+ asciiDigitMappings.put('8', '8');
+ asciiDigitMappings.put('9', '9');
+
+ HashMap<Character, Character> alphaMap = new HashMap<Character, Character>(40);
+ alphaMap.put('A', '2');
+ alphaMap.put('B', '2');
+ alphaMap.put('C', '2');
+ alphaMap.put('D', '3');
+ alphaMap.put('E', '3');
+ alphaMap.put('F', '3');
+ alphaMap.put('G', '4');
+ alphaMap.put('H', '4');
+ alphaMap.put('I', '4');
+ alphaMap.put('J', '5');
+ alphaMap.put('K', '5');
+ alphaMap.put('L', '5');
+ alphaMap.put('M', '6');
+ alphaMap.put('N', '6');
+ alphaMap.put('O', '6');
+ alphaMap.put('P', '7');
+ alphaMap.put('Q', '7');
+ alphaMap.put('R', '7');
+ alphaMap.put('S', '7');
+ alphaMap.put('T', '8');
+ alphaMap.put('U', '8');
+ alphaMap.put('V', '8');
+ alphaMap.put('W', '9');
+ alphaMap.put('X', '9');
+ alphaMap.put('Y', '9');
+ alphaMap.put('Z', '9');
+ ALPHA_MAPPINGS = Collections.unmodifiableMap(alphaMap);
+
+ HashMap<Character, Character> combinedMap = new HashMap<Character, Character>(100);
+ combinedMap.putAll(ALPHA_MAPPINGS);
+ combinedMap.putAll(asciiDigitMappings);
+ ALPHA_PHONE_MAPPINGS = Collections.unmodifiableMap(combinedMap);
+
+ HashMap<Character, Character> diallableCharMap = new HashMap<Character, Character>();
+ diallableCharMap.putAll(asciiDigitMappings);
+ diallableCharMap.put(PLUS_SIGN, PLUS_SIGN);
+ diallableCharMap.put('*', '*');
+ DIALLABLE_CHAR_MAPPINGS = Collections.unmodifiableMap(diallableCharMap);
+
+ HashMap<Character, Character> allPlusNumberGroupings = new HashMap<Character, Character>();
+ // Put (lower letter -> upper letter) and (upper letter -> upper letter) mappings.
+ for (char c : ALPHA_MAPPINGS.keySet()) {
+ allPlusNumberGroupings.put(Character.toLowerCase(c), c);
+ allPlusNumberGroupings.put(c, c);
+ }
+ allPlusNumberGroupings.putAll(asciiDigitMappings);
+ // Put grouping symbols.
+ allPlusNumberGroupings.put('-', '-');
+ allPlusNumberGroupings.put('\uFF0D', '-');
+ allPlusNumberGroupings.put('\u2010', '-');
+ allPlusNumberGroupings.put('\u2011', '-');
+ allPlusNumberGroupings.put('\u2012', '-');
+ allPlusNumberGroupings.put('\u2013', '-');
+ allPlusNumberGroupings.put('\u2014', '-');
+ allPlusNumberGroupings.put('\u2015', '-');
+ allPlusNumberGroupings.put('\u2212', '-');
+ allPlusNumberGroupings.put('/', '/');
+ allPlusNumberGroupings.put('\uFF0F', '/');
+ allPlusNumberGroupings.put(' ', ' ');
+ allPlusNumberGroupings.put('\u3000', ' ');
+ allPlusNumberGroupings.put('\u2060', ' ');
+ allPlusNumberGroupings.put('.', '.');
+ allPlusNumberGroupings.put('\uFF0E', '.');
+ ALL_PLUS_NUMBER_GROUPING_SYMBOLS = Collections.unmodifiableMap(allPlusNumberGroupings);
+ }
+
+ // Pattern that makes it easy to distinguish whether a region has a unique international dialing
+ // prefix or not. If a region has a unique international prefix (e.g. 011 in USA), it will be
+ // represented as a string that contains a sequence of ASCII digits. If there are multiple
+ // available international prefixes in a region, they will be represented as a regex string that
+ // always contains character(s) other than ASCII digits.
+ // Note this regex also includes tilde, which signals waiting for the tone.
+ private static final Pattern UNIQUE_INTERNATIONAL_PREFIX =
+ Pattern.compile("[\\d]+(?:[~\u2053\u223C\uFF5E][\\d]+)?");
+
+ // Regular expression of acceptable punctuation found in phone numbers. This excludes punctuation
+ // found as a leading character only.
+ // This consists of dash characters, white space characters, full stops, slashes,
+ // square brackets, parentheses and tildes. It also includes the letter 'x' as that is found as a
+ // placeholder for carrier information in some phone numbers. Full-width variants are also
+ // present.
+ static final String VALID_PUNCTUATION = "-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F " +
+ "\u00A0\u00AD\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E";
+
+ private static final String DIGITS = "\\p{Nd}";
+ // We accept alpha characters in phone numbers, ASCII only, upper and lower case.
+ private static final String VALID_ALPHA =
+ Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).replaceAll("[, \\[\\]]", "") +
+ Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).toLowerCase().replaceAll("[, \\[\\]]", "");
+ static final String PLUS_CHARS = "+\uFF0B";
+ static final Pattern PLUS_CHARS_PATTERN = Pattern.compile("[" + PLUS_CHARS + "]+");
+ private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[" + VALID_PUNCTUATION + "]+");
+ private static final Pattern CAPTURING_DIGIT_PATTERN = Pattern.compile("(" + DIGITS + ")");
+
+ // Regular expression of acceptable characters that may start a phone number for the purposes of
+ // parsing. This allows us to strip away meaningless prefixes to phone numbers that may be
+ // mistakenly given to us. This consists of digits, the plus symbol and arabic-indic digits. This
+ // does not contain alpha characters, although they may be used later in the number. It also does
+ // not include other punctuation, as this will be stripped later during parsing and is of no
+ // information value when parsing a number.
+ private static final String VALID_START_CHAR = "[" + PLUS_CHARS + DIGITS + "]";
+ private static final Pattern VALID_START_CHAR_PATTERN = Pattern.compile(VALID_START_CHAR);
+
+ // Regular expression of characters typically used to start a second phone number for the purposes
+ // of parsing. This allows us to strip off parts of the number that are actually the start of
+ // another number, such as for: (530) 583-6985 x302/x2303 -> the second extension here makes this
+ // actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second
+ // extension so that the first number is parsed correctly.
+ private static final String SECOND_NUMBER_START = "[\\\\/] *x";
+ static final Pattern SECOND_NUMBER_START_PATTERN = Pattern.compile(SECOND_NUMBER_START);
+
+ // Regular expression of trailing characters that we want to remove. We remove all characters that
+ // are not alpha or numerical characters. The hash character is retained here, as it may signify
+ // the previous block was an extension.
+ private static final String UNWANTED_END_CHARS = "[[\\P{N}&&\\P{L}]&&[^#]]+$";
+ static final Pattern UNWANTED_END_CHAR_PATTERN = Pattern.compile(UNWANTED_END_CHARS);
+
+ // We use this pattern to check if the phone number has at least three letters in it - if so, then
+ // we treat it as a number where some phone-number digits are represented by letters.
+ private static final Pattern VALID_ALPHA_PHONE_PATTERN = Pattern.compile("(?:.*?[A-Za-z]){3}.*");
+
+ // Regular expression of viable phone numbers. This is location independent. Checks we have at
+ // least three leading digits, and only valid punctuation, alpha characters and
+ // digits in the phone number. Does not include extension data.
+ // The symbol 'x' is allowed here as valid punctuation since it is often used as a placeholder for
+ // carrier codes, for example in Brazilian phone numbers. We also allow multiple "+" characters at
+ // the start.
+ // Corresponds to the following:
+ // [digits]{minLengthNsn}|
+ // plus_sign*(([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
+ //
+ // The first reg-ex is to allow short numbers (two digits long) to be parsed if they are entered
+ // as "15" etc, but only if there is no punctuation in them. The second expression restricts the
+ // number of digits to three or more, but then allows them to be in international form, and to
+ // have alpha-characters and punctuation.
+ //
+ // Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
+ private static final String VALID_PHONE_NUMBER =
+ DIGITS + "{" + MIN_LENGTH_FOR_NSN + "}" + "|" +
+ "[" + PLUS_CHARS + "]*+(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" +
+ VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*";
+
+ // Default extension prefix to use when formatting. This will be put in front of any extension
+ // component of the number, after the main national number is formatted. For example, if you wish
+ // the default extension formatting to be " extn: 3456", then you should specify " extn: " here
+ // as the default extension prefix. This can be overridden by region-specific preferences.
+ private static final String DEFAULT_EXTN_PREFIX = " ext. ";
+
+ // Pattern to capture digits used in an extension. Places a maximum length of "7" for an
+ // extension.
+ private static final String CAPTURING_EXTN_DIGITS = "(" + DIGITS + "{1,7})";
+ // Regexp of all possible ways to write extensions, for use when parsing. This will be run as a
+ // case-insensitive regexp match. Wide character versions are also provided after each ASCII
+ // version.
+ private static final String EXTN_PATTERNS_FOR_PARSING;
+ static final String EXTN_PATTERNS_FOR_MATCHING;
+ static {
+ // One-character symbols that can be used to indicate an extension.
+ String singleExtnSymbolsForMatching = "x\uFF58#\uFF03~\uFF5E";
+ // For parsing, we are slightly more lenient in our interpretation than for matching. Here we
+ // allow a "comma" as a possible extension indicator. When matching, this is hardly ever used to
+ // indicate this.
+ String singleExtnSymbolsForParsing = "," + singleExtnSymbolsForMatching;
+
+ EXTN_PATTERNS_FOR_PARSING = createExtnPattern(singleExtnSymbolsForParsing);
+ EXTN_PATTERNS_FOR_MATCHING = createExtnPattern(singleExtnSymbolsForMatching);
+ }
+
+ /**
+ * Helper initialiser method to create the regular-expression pattern to match extensions,
+ * allowing the one-char extension symbols provided by {@code singleExtnSymbols}.
+ */
+ private static String createExtnPattern(String singleExtnSymbols) {
+ // There are three regular expressions here. The first covers RFC 3966 format, where the
+ // extension is added using ";ext=". The second more generic one starts with optional white
+ // space and ends with an optional full stop (.), followed by zero or more spaces/tabs and then
+ // the numbers themselves. The other one covers the special case of American numbers where the
+ // extension is written with a hash at the end, such as "- 503#".
+ // Note that the only capturing groups should be around the digits that you want to capture as
+ // part of the extension, or else parsing will fail!
+ // Canonical-equivalence doesn't seem to be an option with Android java, so we allow two options
+ // for representing the accented o - the character itself, and one in the unicode decomposed
+ // form with the combining acute accent.
+ return (RFC3966_EXTN_PREFIX + CAPTURING_EXTN_DIGITS + "|" + "[ \u00A0\\t,]*" +
+ "(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|" +
+ "[" + singleExtnSymbols + "]|int|anexo|\uFF49\uFF4E\uFF54)" +
+ "[:\\.\uFF0E]?[ \u00A0\\t,-]*" + CAPTURING_EXTN_DIGITS + "#?|" +
+ "[- ]+(" + DIGITS + "{1,5})#");
+ }
+
+ // Regexp of all known extension prefixes used by different regions followed by 1 or more valid
+ // digits, for use when parsing.
+ private static final Pattern EXTN_PATTERN =
+ Pattern.compile("(?:" + EXTN_PATTERNS_FOR_PARSING + ")$", REGEX_FLAGS);
+
+ // We append optionally the extension pattern to the end here, as a valid phone number may
+ // have an extension prefix appended, followed by 1 or more digits.
+ private static final Pattern VALID_PHONE_NUMBER_PATTERN =
+ Pattern.compile(VALID_PHONE_NUMBER + "(?:" + EXTN_PATTERNS_FOR_PARSING + ")?", REGEX_FLAGS);
+
+ static final Pattern NON_DIGITS_PATTERN = Pattern.compile("(\\D+)");
+
+ // The FIRST_GROUP_PATTERN was originally set to $1 but there are some countries for which the
+ // first group is not used in the national pattern (e.g. Argentina) so the $1 group does not match
+ // correctly. Therefore, we use \d, so that the first group actually used in the pattern will be
+ // matched.
+ private static final Pattern FIRST_GROUP_PATTERN = Pattern.compile("(\\$\\d)");
+ private static final Pattern NP_PATTERN = Pattern.compile("\\$NP");
+ private static final Pattern FG_PATTERN = Pattern.compile("\\$FG");
+ private static final Pattern CC_PATTERN = Pattern.compile("\\$CC");
+
+ // A pattern that is used to determine if the national prefix formatting rule has the first group
+ // only, i.e., does not start with the national prefix. Note that the pattern explicitly allows
+ // for unbalanced parentheses.
+ private static final Pattern FIRST_GROUP_ONLY_PREFIX_PATTERN = Pattern.compile("\\(?\\$1\\)?");
+
+ private static PhoneNumberUtil instance = null;
+
+ 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
+ * "+41 44 668 1800" in INTERNATIONAL format, and as "044 668 1800" in NATIONAL format.
+ * E164 format is as per INTERNATIONAL format but with no formatting applied, e.g.
+ * "+41446681800". RFC3966 is as per INTERNATIONAL format, but with all spaces and other
+ * separating symbols replaced with a hyphen, and with any phone number extension appended with
+ * ";ext=". It also will have a prefix of "tel:" added, e.g. "tel:+41-44-668-1800".
+ *
+ * Note: If you are considering storing the number in a neutral format, you are highly advised to
+ * use the PhoneNumber class.
+ */
+ public enum PhoneNumberFormat {
+ E164,
+ INTERNATIONAL,
+ NATIONAL,
+ RFC3966
+ }
+
+ /**
+ * Type of phone numbers.
+ */
+ public enum PhoneNumberType {
+ FIXED_LINE,
+ MOBILE,
+ // In some regions (e.g. the USA), it is impossible to distinguish between fixed-line and
+ // mobile numbers by looking at the phone number itself.
+ FIXED_LINE_OR_MOBILE,
+ // Freephone lines
+ TOLL_FREE,
+ PREMIUM_RATE,
+ // The cost of this call is shared between the caller and the recipient, and is hence typically
+ // less than PREMIUM_RATE calls. See // http://en.wikipedia.org/wiki/Shared_Cost_Service for
+ // more information.
+ SHARED_COST,
+ // Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
+ VOIP,
+ // A personal number is associated with a particular person, and may be routed to either a
+ // MOBILE or FIXED_LINE number. Some more information can be found here:
+ // http://en.wikipedia.org/wiki/Personal_Numbers
+ PERSONAL_NUMBER,
+ PAGER,
+ // Used for "Universal Access Numbers" or "Company Numbers". They may be further routed to
+ // specific offices, but allow one number to be used for a company.
+ UAN,
+ // Used for "Voice Mail Access Numbers".
+ VOICEMAIL,
+ // A phone number is of type UNKNOWN when it does not fit any of the known patterns for a
+ // specific region.
+ UNKNOWN
+ }
+
+ /**
+ * Types of phone number matches. See detailed description beside the isNumberMatch() method.
+ */
+ public enum MatchType {
+ NOT_A_NUMBER,
+ NO_MATCH,
+ SHORT_NSN_MATCH,
+ NSN_MATCH,
+ EXACT_MATCH,
+ }
+
+ /**
+ * Possible outcomes when testing if a PhoneNumber is possible.
+ */
+ public enum ValidationResult {
+ IS_POSSIBLE,
+ INVALID_COUNTRY_CODE,
+ TOO_SHORT,
+ TOO_LONG,
+ }
+
+ /**
+ * Leniency when {@linkplain PhoneNumberUtil#findNumbers finding} potential phone numbers in text
+ * segments. The levels here are ordered in increasing strictness.
+ */
+ public enum Leniency {
+ /**
+ * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber)
+ * possible}, but not necessarily {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}.
+ */
+ POSSIBLE {
+ @Override
+ boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) {
+ return util.isPossibleNumber(number);
+ }
+ },
+ /**
+ * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber)
+ * possible} and {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}. Numbers written
+ * in national format must have their national-prefix present if it is usually written for a
+ * number of this type.
+ */
+ VALID {
+ @Override
+ boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) {
+ if (!util.isValidNumber(number) ||
+ !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util)) {
+ return false;
+ }
+ return PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util);
+ }
+ },
+ /**
+ * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and
+ * are grouped in a possible way for this locale. For example, a US number written as
+ * "65 02 53 00 00" and "650253 0000" are not accepted at this leniency level, whereas
+ * "650 253 0000", "650 2530000" or "6502530000" are.
+ * Numbers with more than one '/' symbol in the national significant number are also dropped at
+ * this level.
+ * <p>
+ * Warning: This level might result in lower coverage especially for regions outside of country
+ * code "+1". If you are not sure about which level to use, email the discussion group
+ * libphonenumber-discuss@googlegroups.com.
+ */
+ STRICT_GROUPING {
+ @Override
+ boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) {
+ if (!util.isValidNumber(number) ||
+ !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) ||
+ PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) ||
+ !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) {
+ return false;
+ }
+ return PhoneNumberMatcher.checkNumberGroupingIsValid(
+ number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() {
+ public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number,
+ StringBuilder normalizedCandidate,
+ String[] expectedNumberGroups) {
+ return PhoneNumberMatcher.allNumberGroupsRemainGrouped(
+ util, number, normalizedCandidate, expectedNumberGroups);
+ }
+ });
+ }
+ },
+ /**
+ * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and
+ * are grouped in the same way that we would have formatted it, or as a single block. For
+ * example, a US number written as "650 2530000" is not accepted at this leniency level, whereas
+ * "650 253 0000" or "6502530000" are.
+ * Numbers with more than one '/' symbol are also dropped at this level.
+ * <p>
+ * Warning: This level might result in lower coverage especially for regions outside of country
+ * code "+1". If you are not sure about which level to use, email the discussion group
+ * libphonenumber-discuss@googlegroups.com.
+ */
+ EXACT_GROUPING {
+ @Override
+ boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) {
+ if (!util.isValidNumber(number) ||
+ !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate, util) ||
+ PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate) ||
+ !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) {
+ return false;
+ }
+ return PhoneNumberMatcher.checkNumberGroupingIsValid(
+ number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() {
+ public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number,
+ StringBuilder normalizedCandidate,
+ String[] expectedNumberGroups) {
+ return PhoneNumberMatcher.allNumberGroupsAreExactlyPresent(
+ util, number, normalizedCandidate, expectedNumberGroups);
+ }
+ });
+ }
+ };
+
+ /** Returns true if {@code number} is a verified number according to this leniency. */
+ abstract boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util);
+ }
+
+ // A mapping from a country calling code to the region codes which denote the region represented
+ // by that country calling code. In the case of multiple regions sharing a calling code, such as
+ // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be
+ // first.
+ private final Map<Integer, List<String>> countryCallingCodeToRegionCodeMap;
+
+ // The set of regions that share country calling code 1.
+ // There are roughly 26 regions.
+ // We set the initial capacity of the HashSet to 35 to offer a load factor of roughly 0.75.
+ private final Set<String> nanpaRegions = new HashSet<String>(35);
+
+ // A mapping from a region code to the PhoneMetadata for that region.
+ // Note: Synchronization, though only needed for the Android version of the library, is used in
+ // all versions for consistency.
+ private final Map<String, PhoneMetadata> regionToMetadataMap =
+ Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
+
+ // 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).
+ // Note: Synchronization, though only needed for the Android version of the library, is used in
+ // all versions for consistency.
+ private final Map<Integer, PhoneMetadata> countryCodeToNonGeographicalMetadataMap =
+ Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
+
+ // A cache for frequently used region-specific regular expressions.
+ // The initial capacity is set to 100 as this seems to be an optimal value for Android, based on
+ // performance measurements.
+ private final RegexCache regexCache = new RegexCache(100);
+
+ // The set of regions the library supports.
+ // 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<String> supportedRegions = new HashSet<String>(320);
+
+ // 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>();
+
+ // The prefix of the metadata files from which region data is loaded.
+ private final String currentFilePrefix;
+ // The metadata loader used to inject alternative metadata sources.
+ private final MetadataLoader metadataLoader;
+
+ /**
+ * This class implements a singleton, the constructor is only visible to facilitate testing.
+ */
+ // @VisibleForTesting
+ PhoneNumberUtil(String filePrefix, MetadataLoader metadataLoader,
+ Map<Integer, List<String>> countryCallingCodeToRegionCodeMap) {
+ this.currentFilePrefix = filePrefix;
+ this.metadataLoader = metadataLoader;
+ this.countryCallingCodeToRegionCodeMap = countryCallingCodeToRegionCodeMap;
+ 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))");
+ }
+ nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE));
+ }
+
+ // @VisibleForTesting
+ void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode,
+ MetadataLoader metadataLoader) {
+ boolean isNonGeoRegion = REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode);
+ String fileName = filePrefix + "_" +
+ (isNonGeoRegion ? String.valueOf(countryCallingCode) : regionCode);
+ InputStream source = metadataLoader.loadMetadata(fileName);
+ if (source == null) {
+ logger.log(Level.SEVERE, "missing metadata: " + fileName);
+ throw new IllegalStateException("missing metadata: " + fileName);
+ }
+ ObjectInputStream in = null;
+ try {
+ in = new ObjectInputStream(source);
+ PhoneMetadataCollection metadataCollection = loadMetadataAndCloseInput(in);
+ List<PhoneMetadata> metadataList = metadataCollection.getMetadataList();
+ if (metadataList.isEmpty()) {
+ logger.log(Level.SEVERE, "empty metadata: " + fileName);
+ throw new IllegalStateException("empty metadata: " + fileName);
+ }
+ if (metadataList.size() > 1) {
+ logger.log(Level.WARNING, "invalid metadata (too many entries): " + fileName);
+ }
+ PhoneMetadata metadata = metadataList.get(0);
+ if (isNonGeoRegion) {
+ countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata);
+ } else {
+ regionToMetadataMap.put(regionCode, metadata);
+ }
+ } catch (IOException e) {
+ logger.log(Level.SEVERE, "cannot load/parse metadata: " + fileName, e);
+ throw new RuntimeException("cannot load/parse metadata: " + fileName, e);
+ }
+ }
+
+ /**
+ * Loads the metadata protocol buffer from the given stream and closes the stream afterwards. Any
+ * exceptions that occur while reading the stream are propagated (though exceptions that occur
+ * when the stream is closed will be ignored).
+ *
+ * @param source the non-null stream from which metadata is to be read.
+ * @return the loaded metadata protocol buffer.
+ */
+ private static PhoneMetadataCollection loadMetadataAndCloseInput(ObjectInputStream source) {
+ PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection();
+ try {
+ metadataCollection.readExternal(source);
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "error reading input (ignored)", e);
+ } finally {
+ try {
+ source.close();
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "error closing input stream (ignored)", e);
+ } finally {
+ return metadataCollection;
+ }
+ }
+ }
+
+ /**
+ * Attempts to extract a possible number from the string passed in. This currently strips all
+ * leading characters that cannot be used to start a phone number. Characters that can be used to
+ * start a phone number are defined in the VALID_START_CHAR_PATTERN. If none of these characters
+ * are found in the number passed in, an empty string is returned. This function also attempts to
+ * strip off any alternative extensions or endings if two or more are present, such as in the case
+ * of: (530) 583-6985 x302/x2303. The second extension here makes this actually two phone numbers,
+ * (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second extension so that the first
+ * number is parsed correctly.
+ *
+ * @param number the string that might contain a phone number
+ * @return the number, stripped of any non-phone-number prefix (such as "Tel:") or an empty
+ * string if no character used to start phone numbers (such as + or any digit) is
+ * found in the number
+ */
+ static String extractPossibleNumber(String number) {
+ Matcher m = VALID_START_CHAR_PATTERN.matcher(number);
+ if (m.find()) {
+ number = number.substring(m.start());
+ // Remove trailing non-alpha non-numerical characters.
+ Matcher trailingCharsMatcher = UNWANTED_END_CHAR_PATTERN.matcher(number);
+ if (trailingCharsMatcher.find()) {
+ number = number.substring(0, trailingCharsMatcher.start());
+ logger.log(Level.FINER, "Stripped trailing characters: " + number);
+ }
+ // Check for extra numbers at the end.
+ Matcher secondNumber = SECOND_NUMBER_START_PATTERN.matcher(number);
+ if (secondNumber.find()) {
+ number = number.substring(0, secondNumber.start());
+ }
+ return number;
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Checks to see if the string of characters could possibly be a phone number at all. At the
+ * moment, checks to see that the string begins with at least 2 digits, ignoring any punctuation
+ * commonly found in phone numbers.
+ * This method does not require the number to be normalized in advance - but does assume that
+ * leading non-number symbols have been removed, such as by the method extractPossibleNumber.
+ *
+ * @param number string to be checked for viability as a phone number
+ * @return true if the number could be a phone number of some sort, otherwise false
+ */
+ // @VisibleForTesting
+ static boolean isViablePhoneNumber(String number) {
+ if (number.length() < MIN_LENGTH_FOR_NSN) {
+ return false;
+ }
+ Matcher m = VALID_PHONE_NUMBER_PATTERN.matcher(number);
+ return m.matches();
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number. This performs the following
+ * conversions:
+ * Punctuation is stripped.
+ * For ALPHA/VANITY numbers:
+ * Letters are converted to their numeric representation on a telephone keypad. The keypad
+ * used here is the one defined in ITU Recommendation E.161. This is only done if there are
+ * 3 or more letters in the number, to lessen the risk that such letters are typos.
+ * For other numbers:
+ * Wide-ascii digits are converted to normal ASCII (European) digits.
+ * Arabic-Indic numerals are converted to European numerals.
+ * Spurious alpha characters are stripped.
+ *
+ * @param number a string of characters representing a phone number
+ * @return the normalized string version of the phone number
+ */
+ static String normalize(String number) {
+ Matcher m = VALID_ALPHA_PHONE_PATTERN.matcher(number);
+ if (m.matches()) {
+ return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, true);
+ } else {
+ return normalizeDigitsOnly(number);
+ }
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number. This is a wrapper for
+ * normalize(String number) but does in-place normalization of the StringBuilder provided.
+ *
+ * @param number a StringBuilder of characters representing a phone number that will be
+ * normalized in place
+ */
+ static void normalize(StringBuilder number) {
+ String normalizedNumber = normalize(number.toString());
+ number.replace(0, number.length(), normalizedNumber);
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number. This converts wide-ascii and
+ * arabic-indic numerals to European numerals, and strips punctuation and alpha characters.
+ *
+ * @param number a string of characters representing a phone number
+ * @return the normalized string version of the phone number
+ */
+ public static String normalizeDigitsOnly(String number) {
+ return normalizeDigits(number, false /* strip non-digits */).toString();
+ }
+
+ static StringBuilder normalizeDigits(String number, boolean keepNonDigits) {
+ StringBuilder normalizedDigits = new StringBuilder(number.length());
+ for (char c : number.toCharArray()) {
+ int digit = Character.digit(c, 10);
+ if (digit != -1) {
+ normalizedDigits.append(digit);
+ } else if (keepNonDigits) {
+ normalizedDigits.append(c);
+ }
+ }
+ return normalizedDigits;
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number. This strips all characters which
+ * are not diallable on a mobile phone keypad (including all non-ASCII digits).
+ *
+ * @param number a string of characters representing a phone number
+ * @return the normalized string version of the phone number
+ */
+ static String normalizeDiallableCharsOnly(String number) {
+ return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */);
+ }
+
+ /**
+ * Converts all alpha characters in a number to their respective digits on a keypad, but retains
+ * existing formatting.
+ */
+ public static String convertAlphaCharactersInNumber(String number) {
+ return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, false);
+ }
+
+ /**
+ * Gets the length of the geographical area code from the
+ * PhoneNumber object passed in, so that clients could use it
+ * to split a national significant number into geographical area code and subscriber number. It
+ * works in such a way that the resultant subscriber number should be diallable, at least on some
+ * devices. An example of how this could be used:
+ *
+ * <pre>
+ * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+ * PhoneNumber number = phoneUtil.parse("16502530000", "US");
+ * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+ * String areaCode;
+ * String subscriberNumber;
+ *
+ * int areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
+ * if (areaCodeLength > 0) {
+ * areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
+ * subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
+ * } else {
+ * areaCode = "";
+ * subscriberNumber = nationalSignificantNumber;
+ * }
+ * </pre>
+ *
+ * N.B.: area code is a very ambiguous concept, so the I18N team generally recommends against
+ * using it for most purposes, but recommends using the more general {@code national_number}
+ * instead. Read the following carefully before deciding to use this method:
+ * <ul>
+ * <li> geographical area codes change over time, and this method honors those changes;
+ * therefore, it doesn't guarantee the stability of the result it produces.
+ * <li> 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).
+ * <li> most non-geographical numbers have no area codes, including numbers from non-geographical
+ * entities
+ * <li> some geographical numbers have no area codes.
+ * </ul>
+ * @param number the PhoneNumber object for which clients
+ * want to know the length of the area code.
+ * @return the length of area code of the PhoneNumber object
+ * passed in.
+ */
+ public int getLengthOfGeographicalAreaCode(PhoneNumber number) {
+ PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number));
+ if (metadata == null) {
+ return 0;
+ }
+ // 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;
+ }
+
+ if (!isNumberGeographical(number)) {
+ return 0;
+ }
+
+ return getLengthOfNationalDestinationCode(number);
+ }
+
+ /**
+ * Gets the length of the national destination code (NDC) from the
+ * PhoneNumber object passed in, so that clients could use it
+ * to split a national significant number into NDC and subscriber number. The NDC of a phone
+ * number is normally the first group of digit(s) right after the country calling code when the
+ * number is formatted in the international format, if there is a subscriber number part that
+ * follows. An example of how this could be used:
+ *
+ * <pre>
+ * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+ * PhoneNumber number = phoneUtil.parse("18002530000", "US");
+ * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+ * String nationalDestinationCode;
+ * String subscriberNumber;
+ *
+ * int nationalDestinationCodeLength = phoneUtil.getLengthOfNationalDestinationCode(number);
+ * if (nationalDestinationCodeLength > 0) {
+ * nationalDestinationCode = nationalSignificantNumber.substring(0,
+ * nationalDestinationCodeLength);
+ * subscriberNumber = nationalSignificantNumber.substring(nationalDestinationCodeLength);
+ * } else {
+ * nationalDestinationCode = "";
+ * subscriberNumber = nationalSignificantNumber;
+ * }
+ * </pre>
+ *
+ * Refer to the unittests to see the difference between this function and
+ * {@link #getLengthOfGeographicalAreaCode}.
+ *
+ * @param number the PhoneNumber object for which clients
+ * want to know the length of the NDC.
+ * @return the length of NDC of the PhoneNumber object
+ * passed in.
+ */
+ public int getLengthOfNationalDestinationCode(PhoneNumber number) {
+ PhoneNumber copiedProto;
+ if (number.hasExtension()) {
+ // We don't want to alter the proto given to us, but we don't want to include the extension
+ // when we format it, so we copy it and clear the extension here.
+ copiedProto = new PhoneNumber();
+ copiedProto.mergeFrom(number);
+ copiedProto.clearExtension();
+ } else {
+ copiedProto = number;
+ }
+
+ String nationalSignificantNumber = format(copiedProto,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
+ String[] numberGroups = NON_DIGITS_PATTERN.split(nationalSignificantNumber);
+ // The pattern will start with "+COUNTRY_CODE " so the first group will always be the empty
+ // string (before the + symbol) and the second group will be the country calling code. The third
+ // group will be area code if it is not the last group.
+ if (numberGroups.length <= 3) {
+ return 0;
+ }
+
+ if (getNumberType(number) == PhoneNumberType.MOBILE) {
+ // For example Argentinian mobile numbers, when formatted in the international format, are in
+ // the form of +54 9 NDC XXXX.... As a result, we take the length of the third group (NDC) and
+ // add the length of the second group (which is the mobile token), which also forms part of
+ // the national significant number. This assumes that the mobile token is always formatted
+ // separately from the rest of the phone number.
+ String mobileToken = getCountryMobileToken(number.getCountryCode());
+ if (!mobileToken.equals("")) {
+ return numberGroups[2].length() + numberGroups[3].length();
+ }
+ }
+ return numberGroups[2].length();
+ }
+
+ /**
+ * Returns the mobile token for the provided country calling code if it has one, otherwise
+ * returns an empty string. A mobile token is a number inserted before the area code when dialing
+ * a mobile number from that country from abroad.
+ *
+ * @param countryCallingCode the country calling code for which we want the mobile token
+ * @return the mobile token, as a string, for the given country calling code
+ */
+ public static String getCountryMobileToken(int countryCallingCode) {
+ if (MOBILE_TOKEN_MAPPINGS.containsKey(countryCallingCode)) {
+ return MOBILE_TOKEN_MAPPINGS.get(countryCallingCode);
+ }
+ return "";
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number by replacing all characters found
+ * in the accompanying map with the values therein, and stripping all other characters if
+ * removeNonMatches is true.
+ *
+ * @param number a string of characters representing a phone number
+ * @param normalizationReplacements a mapping of characters to what they should be replaced by in
+ * the normalized version of the phone number
+ * @param removeNonMatches indicates whether characters that are not able to be replaced
+ * should be stripped from the number. If this is false, they
+ * will be left unchanged in the number.
+ * @return the normalized string version of the phone number
+ */
+ private static String normalizeHelper(String number,
+ Map<Character, Character> normalizationReplacements,
+ boolean removeNonMatches) {
+ StringBuilder normalizedNumber = new StringBuilder(number.length());
+ 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);
+ } else if (!removeNonMatches) {
+ normalizedNumber.append(character);
+ }
+ // If neither of the above are true, we remove this character.
+ }
+ return normalizedNumber.toString();
+ }
+
+ /**
+ * Sets or resets the PhoneNumberUtil singleton instance. If set to null, the next call to
+ * {@code getInstance()} will load (and return) the default instance.
+ */
+ // @VisibleForTesting
+ static synchronized void setInstance(PhoneNumberUtil util) {
+ instance = util;
+ }
+
+ /**
+ * Convenience method to get a list of what regions the library has metadata for.
+ */
+ public Set<String> getSupportedRegions() {
+ return Collections.unmodifiableSet(supportedRegions);
+ }
+
+ /**
+ * Convenience method to get a list of what global network calling codes the library has metadata
+ * for.
+ */
+ public Set<Integer> getSupportedGlobalNetworkCallingCodes() {
+ return Collections.unmodifiableSet(countryCodesForNonGeographicalRegion);
+ }
+
+ /**
+ * Gets a {@link PhoneNumberUtil} instance to carry out international phone number formatting,
+ * parsing, or validation. The instance is loaded with phone number metadata for a number of most
+ * commonly used regions.
+ *
+ * <p>The {@link PhoneNumberUtil} is implemented as a singleton. Therefore, calling getInstance
+ * multiple times will only result in one instance being created.
+ *
+ * @return a PhoneNumberUtil instance
+ */
+ public static synchronized PhoneNumberUtil getInstance() {
+ if (instance == null) {
+ setInstance(createInstance(DEFAULT_METADATA_LOADER));
+ }
+ return instance;
+ }
+
+ /**
+ * Create a new {@link PhoneNumberUtil} instance to carry out international phone number
+ * formatting, parsing, or validation. The instance is loaded with all metadata by
+ * using the metadataLoader specified.
+ *
+ * This method should only be used in the rare case in which you want to manage your own
+ * metadata loading. Calling this method multiple times is very expensive, as each time
+ * a new instance is created from scratch. When in doubt, use {@link #getInstance}.
+ *
+ * @param metadataLoader Customized metadata loader. If null, default metadata loader will
+ * be used. This should not be null.
+ * @return a PhoneNumberUtil instance
+ */
+ public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) {
+ if (metadataLoader == null) {
+ throw new IllegalArgumentException("metadataLoader could not be null.");
+ }
+ return new PhoneNumberUtil(META_DATA_FILE_PREFIX, metadataLoader,
+ CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap());
+ }
+
+ /**
+ * Helper function to check if the national prefix formatting rule has the first group only, i.e.,
+ * does not start with the national prefix.
+ */
+ static boolean formattingRuleHasFirstGroupOnly(String nationalPrefixFormattingRule) {
+ return nationalPrefixFormattingRule.length() == 0 ||
+ 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.
+ *
+ * A similar method is implemented as PhoneNumberOfflineGeocoder.canBeGeocoded, which performs a
+ * looser check, since it only prevents cases where prefixes overlap for geocodable and
+ * non-geocodable numbers. Also, if new phone number types were added, we should check if this
+ * other method should be updated too.
+ */
+ 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.
+ */
+ private boolean isValidRegionCode(String regionCode) {
+ return regionCode != null && supportedRegions.contains(regionCode);
+ }
+
+ /**
+ * Helper function to check the country calling code is valid.
+ */
+ private boolean hasValidCountryCallingCode(int countryCallingCode) {
+ return countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode);
+ }
+
+ /**
+ * Formats a phone number in the specified format using default rules. Note that this does not
+ * promise to produce a phone number that the user can dial from where they are - although we do
+ * format in either 'national' or 'international' format depending on what the client asks for, we
+ * do not currently support a more abbreviated format, such as for users in the same "area" who
+ * could potentially dial the number without area code. Note that if the phone number has a
+ * country calling code of 0 or an otherwise invalid country calling code, we cannot work out
+ * which formatting rules to apply so we return the national significant number with no formatting
+ * applied.
+ *
+ * @param number the phone number to be formatted
+ * @param numberFormat the format the phone number should be formatted into
+ * @return the formatted phone number
+ */
+ 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;
+ }
+ }
+ StringBuilder formattedNumber = new StringBuilder(20);
+ format(number, numberFormat, formattedNumber);
+ return formattedNumber.toString();
+ }
+
+ /**
+ * Same as {@link #format(PhoneNumber, PhoneNumberFormat)}, but accepts a mutable StringBuilder as
+ * a parameter to decrease object creation when invoked many times.
+ */
+ public void format(PhoneNumber number, PhoneNumberFormat numberFormat,
+ StringBuilder formattedNumber) {
+ // Clear the StringBuilder first.
+ formattedNumber.setLength(0);
+ int countryCallingCode = number.getCountryCode();
+ String nationalSignificantNumber = getNationalSignificantNumber(number);
+
+ if (numberFormat == PhoneNumberFormat.E164) {
+ // 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;
+ }
+ 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));
+ maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber);
+ }
+
+ /**
+ * Formats a phone number in the specified format using client-defined formatting rules. Note that
+ * if the phone number has a country calling code of zero or an otherwise invalid country calling
+ * code, we cannot work out things like whether there should be a national prefix applied, or how
+ * to format extensions, so we return the national significant number with no formatting applied.
+ *
+ * @param number the phone number to be formatted
+ * @param numberFormat the format the phone number should be formatted into
+ * @param userDefinedFormats formatting rules specified by clients
+ * @return the formatted phone number
+ */
+ public String formatByPattern(PhoneNumber number,
+ PhoneNumberFormat numberFormat,
+ 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);
+ // Metadata cannot be null because the country calling code is valid
+ PhoneMetadata metadata =
+ getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
+
+ StringBuilder formattedNumber = new StringBuilder(20);
+
+ NumberFormat formattingPattern =
+ chooseFormattingPatternForNumber(userDefinedFormats, nationalSignificantNumber);
+ if (formattingPattern == null) {
+ // If no pattern above is matched, we format the number as a whole.
+ formattedNumber.append(nationalSignificantNumber);
+ } else {
+ NumberFormat numFormatCopy = new NumberFormat();
+ // Before we do a replacement of the national prefix pattern $NP with the national prefix, we
+ // need to copy the rule so that subsequent replacements for different numbers have the
+ // appropriate national prefix.
+ numFormatCopy.mergeFrom(formattingPattern);
+ String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule();
+ if (nationalPrefixFormattingRule.length() > 0) {
+ String nationalPrefix = metadata.getNationalPrefix();
+ if (nationalPrefix.length() > 0) {
+ // Replace $NP with national prefix and $FG with the first group ($1).
+ nationalPrefixFormattingRule =
+ NP_PATTERN.matcher(nationalPrefixFormattingRule).replaceFirst(nationalPrefix);
+ nationalPrefixFormattingRule =
+ FG_PATTERN.matcher(nationalPrefixFormattingRule).replaceFirst("\\$1");
+ numFormatCopy.setNationalPrefixFormattingRule(nationalPrefixFormattingRule);
+ } else {
+ // We don't want to have a rule for how to format the national prefix if there isn't one.
+ numFormatCopy.clearNationalPrefixFormattingRule();
+ }
+ }
+ formattedNumber.append(
+ formatNsnUsingPattern(nationalSignificantNumber, numFormatCopy, numberFormat));
+ }
+ maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber);
+ return formattedNumber.toString();
+ }
+
+ /**
+ * Formats a phone number in national format for dialing using the carrier as specified in the
+ * {@code carrierCode}. The {@code carrierCode} will always be used regardless of whether the
+ * phone number already has a preferred domestic carrier code stored. If {@code carrierCode}
+ * contains an empty string, returns the number in national format without any carrier code.
+ *
+ * @param number the phone number to be formatted
+ * @param carrierCode the carrier selection code to be used
+ * @return the formatted phone number in national format for dialing using the carrier as
+ * specified in the {@code carrierCode}
+ */
+ 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);
+ // Metadata cannot be null because the country calling code is valid.
+ PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
+
+ StringBuilder formattedNumber = new StringBuilder(20);
+ formattedNumber.append(formatNsn(nationalSignificantNumber, metadata,
+ PhoneNumberFormat.NATIONAL, carrierCode));
+ maybeAppendFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber);
+ prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.NATIONAL,
+ formattedNumber);
+ 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,
+ * use the {@code fallbackCarrierCode} passed in instead. If there is no
+ * {@code preferredDomesticCarrierCode}, and the {@code fallbackCarrierCode} contains an empty
+ * string, return the number in national format without any carrier code.
+ *
+ * <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier code passed in
+ * should take precedence over the number's {@code preferredDomesticCarrierCode} when formatting.
+ *
+ * @param number the phone number to be formatted
+ * @param fallbackCarrierCode the carrier selection code to be used, if none is found in the
+ * phone number itself
+ * @return the formatted phone number in national format for dialing using the number's
+ * {@code preferredDomesticCarrierCode}, or the {@code fallbackCarrierCode} passed in if
+ * none is found
+ */
+ public String formatNationalNumberWithPreferredCarrierCode(PhoneNumber number,
+ String fallbackCarrierCode) {
+ return formatNationalNumberWithCarrierCode(number, number.hasPreferredDomesticCarrierCode()
+ ? number.getPreferredDomesticCarrierCode()
+ : fallbackCarrierCode);
+ }
+
+ /**
+ * Returns a number formatted in such a way that it can be dialed from a mobile phone in a
+ * specific region. If the number cannot be reached from the region (e.g. some countries block
+ * toll-free numbers from being called outside of the country), the method returns an empty
+ * string.
+ *
+ * @param number the phone number to be formatted
+ * @param regionCallingFrom the region where the call is being placed
+ * @param withFormatting whether the number should be returned with formatting symbols, such as
+ * spaces and dashes.
+ * @return the formatted phone number
+ */
+ public String formatNumberForMobileDialing(PhoneNumber number, String regionCallingFrom,
+ boolean withFormatting) {
+ int countryCallingCode = number.getCountryCode();
+ if (!hasValidCountryCallingCode(countryCallingCode)) {
+ return number.hasRawInput() ? number.getRawInput() : "";
+ }
+
+ String formattedNumber = "";
+ // Clear the extension, as that part cannot normally be dialed together with the main number.
+ PhoneNumber numberNoExt = new PhoneNumber().mergeFrom(number).clearExtension();
+ String regionCode = getRegionCodeForCountryCode(countryCallingCode);
+ PhoneNumberType numberType = getNumberType(numberNoExt);
+ boolean isValidNumber = (numberType != PhoneNumberType.UNKNOWN);
+ if (regionCallingFrom.equals(regionCode)) {
+ boolean isFixedLineOrMobile =
+ (numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) ||
+ (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE);
+ // Carrier codes may be needed in some countries. We handle this here.
+ if (regionCode.equals("CO") && numberType == PhoneNumberType.FIXED_LINE) {
+ formattedNumber =
+ formatNationalNumberWithCarrierCode(numberNoExt, COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX);
+ } else if (regionCode.equals("BR") && isFixedLineOrMobile) {
+ formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode()
+ ? formattedNumber = formatNationalNumberWithPreferredCarrierCode(numberNoExt, "")
+ // Brazilian fixed line and mobile numbers need to be dialed with a carrier code when
+ // called within Brazil. Without that, most of the carriers won't connect the call.
+ // Because of that, we return an empty string here.
+ : "";
+ } else if (isValidNumber && regionCode.equals("HU")) {
+ // The national format for HU numbers doesn't contain the national prefix, because that is
+ // how numbers are normally written down. However, the national prefix is obligatory when
+ // dialing from a mobile phone, except for short numbers. As a result, we add it back here
+ // if it is a valid regular length phone number.
+ formattedNumber =
+ getNddPrefixForRegion(regionCode, true /* strip non-digits */) +
+ " " + format(numberNoExt, PhoneNumberFormat.NATIONAL);
+ } else if (countryCallingCode == NANPA_COUNTRY_CODE) {
+ // For NANPA countries, we output international format for numbers that can be dialed
+ // internationally, since that always works, except for numbers which might potentially be
+ // short numbers, which are always dialled in national format.
+ PhoneMetadata regionMetadata = getMetadataForRegion(regionCallingFrom);
+ if (canBeInternationallyDialled(numberNoExt) &&
+ !isShorterThanPossibleNormalNumber(regionMetadata,
+ getNationalSignificantNumber(numberNoExt))) {
+ formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL);
+ } else {
+ formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL);
+ }
+ } else {
+ // For non-geographical countries, and Mexican and Chilean fixed line and mobile numbers, we
+ // output international format for numbers that can be dialed internationally as that always
+ // works.
+ if ((regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITY) ||
+ // MX fixed line and mobile numbers should always be formatted in international format,
+ // even when dialed within MX. For national format to work, a carrier code needs to be
+ // used, and the correct carrier code depends on if the caller and callee are from the
+ // same local area. It is trickier to get that to work correctly than using
+ // international format, which is tested to work fine on all carriers.
+ // CL fixed line numbers need the national prefix when dialing in the national format,
+ // but don't have it when used for display. The reverse is true for mobile numbers.
+ // As a result, we output them in the international format to make it work.
+ ((regionCode.equals("MX") || regionCode.equals("CL")) &&
+ isFixedLineOrMobile)) &&
+ canBeInternationallyDialled(numberNoExt)) {
+ formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL);
+ } else {
+ formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL);
+ }
+ }
+ } else if (isValidNumber && canBeInternationallyDialled(numberNoExt)) {
+ // We assume that short numbers are not diallable from outside their region, so if a number
+ // is not a valid regular length phone number, we treat it as if it cannot be internationally
+ // dialled.
+ return withFormatting ? format(numberNoExt, PhoneNumberFormat.INTERNATIONAL)
+ : format(numberNoExt, PhoneNumberFormat.E164);
+ }
+ return withFormatting ? formattedNumber
+ : normalizeDiallableCharsOnly(formattedNumber);
+ }
+
+ /**
+ * Formats a phone number for out-of-country dialing purposes. If no regionCallingFrom is
+ * supplied, we format the number in its INTERNATIONAL format. If the country calling code is the
+ * same as that of the region where the number is from, then NATIONAL formatting will be applied.
+ *
+ * <p>If the number itself has a country calling code of zero or an otherwise invalid country
+ * calling code, then we return the number with no formatting applied.
+ *
+ * <p>Note this function takes care of the case for calling inside of NANPA and between Russia and
+ * Kazakhstan (who share the same country calling code). In those cases, no international prefix
+ * is used. For regions which have multiple international prefixes, the number in its
+ * INTERNATIONAL format will be returned instead.
+ *
+ * @param number the phone number to be formatted
+ * @param regionCallingFrom the region where the call is being placed
+ * @return the formatted phone number
+ */
+ public String formatOutOfCountryCallingNumber(PhoneNumber number,
+ String regionCallingFrom) {
+ if (!isValidRegionCode(regionCallingFrom)) {
+ logger.log(Level.WARNING,
+ "Trying to format number from invalid region "
+ + regionCallingFrom
+ + ". International formatting applied.");
+ return format(number, PhoneNumberFormat.INTERNATIONAL);
+ }
+ int countryCallingCode = number.getCountryCode();
+ String nationalSignificantNumber = getNationalSignificantNumber(number);
+ if (!hasValidCountryCallingCode(countryCallingCode)) {
+ return nationalSignificantNumber;
+ }
+ if (countryCallingCode == NANPA_COUNTRY_CODE) {
+ if (isNANPACountry(regionCallingFrom)) {
+ // For NANPA regions, return the national format for these regions but prefix it with the
+ // country calling code.
+ return countryCallingCode + " " + format(number, PhoneNumberFormat.NATIONAL);
+ }
+ } else if (countryCallingCode == getCountryCodeForValidRegion(regionCallingFrom)) {
+ // 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
+ // edge case for now and for those cases return the version including country calling code.
+ // 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();
+
+ // For regions that have multiple international prefixes, the international format of the
+ // number is returned, unless there is a preferred international prefix.
+ String internationalPrefixForFormatting = "";
+ if (UNIQUE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches()) {
+ internationalPrefixForFormatting = internationalPrefix;
+ } else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
+ internationalPrefixForFormatting =
+ metadataForRegionCallingFrom.getPreferredInternationalPrefix();
+ }
+
+ String regionCode = getRegionCodeForCountryCode(countryCallingCode);
+ // Metadata cannot be null because the country calling code is valid.
+ PhoneMetadata metadataForRegion =
+ getMetadataForRegionOrCallingCode(countryCallingCode, regionCode);
+ String formattedNationalNumber =
+ formatNsn(nationalSignificantNumber, metadataForRegion, PhoneNumberFormat.INTERNATIONAL);
+ StringBuilder formattedNumber = new StringBuilder(formattedNationalNumber);
+ maybeAppendFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL,
+ formattedNumber);
+ if (internationalPrefixForFormatting.length() > 0) {
+ formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, " ")
+ .insert(0, internationalPrefixForFormatting);
+ } else {
+ prefixNumberWithCountryCallingCode(countryCallingCode,
+ PhoneNumberFormat.INTERNATIONAL,
+ formattedNumber);
+ }
+ return formattedNumber.toString();
+ }
+
+ /**
+ * Formats a phone number using the original phone number format that the number is parsed from.
+ * The original format is embedded in the country_code_source field of the PhoneNumber object
+ * passed in. If such information is missing, the number will be formatted into the NATIONAL
+ * format by default. When the number contains a leading zero and this is unexpected for this
+ * 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
+ * @return the formatted phone number in its original number format
+ */
+ public String formatInOriginalFormat(PhoneNumber number, String regionCallingFrom) {
+ if (number.hasRawInput() &&
+ (hasUnexpectedItalianLeadingZero(number) || !hasFormattingPatternForNumber(number))) {
+ // We check if we have the formatting pattern because without that, we might format the number
+ // as a group without national prefix.
+ return number.getRawInput();
+ }
+ if (!number.hasCountryCodeSource()) {
+ return format(number, PhoneNumberFormat.NATIONAL);
+ }
+ String formattedNumber;
+ switch (number.getCountryCodeSource()) {
+ case FROM_NUMBER_WITH_PLUS_SIGN:
+ formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL);
+ break;
+ case FROM_NUMBER_WITH_IDD:
+ formattedNumber = formatOutOfCountryCallingNumber(number, regionCallingFrom);
+ break;
+ case FROM_NUMBER_WITHOUT_PLUS_SIGN:
+ formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL).substring(1);
+ break;
+ case FROM_DEFAULT_COUNTRY:
+ // Fall-through to default case.
+ default:
+ 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;
+ }
+ // 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.
+ 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.
+ NumberFormat numFormatCopy = new NumberFormat();
+ numFormatCopy.mergeFrom(formatRule);
+ numFormatCopy.clearNationalPrefixFormattingRule();
+ List<NumberFormat> numberFormats = new ArrayList<NumberFormat>(1);
+ numberFormats.add(numFormatCopy);
+ 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.
+ if (formattedNumber != null && rawInput.length() > 0) {
+ String normalizedFormattedNumber = normalizeDiallableCharsOnly(formattedNumber);
+ String normalizedRawInput = normalizeDiallableCharsOnly(rawInput);
+ 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
+ // 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;
+ }
+
+ /**
+ * Returns true if a number is from a region whose national significant number couldn't contain a
+ * leading zero, but has the italian_leading_zero field set to true.
+ */
+ private boolean hasUnexpectedItalianLeadingZero(PhoneNumber number) {
+ return number.isItalianLeadingZero() && !isLeadingZeroPossible(number.getCountryCode());
+ }
+
+ private boolean hasFormattingPatternForNumber(PhoneNumber number) {
+ int countryCallingCode = number.getCountryCode();
+ String phoneNumberRegion = getRegionCodeForCountryCode(countryCallingCode);
+ PhoneMetadata metadata =
+ getMetadataForRegionOrCallingCode(countryCallingCode, phoneNumberRegion);
+ if (metadata == null) {
+ return false;
+ }
+ String nationalNumber = getNationalSignificantNumber(number);
+ NumberFormat formatRule =
+ chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber);
+ return formatRule != null;
+ }
+
+ /**
+ * Formats a phone number for out-of-country dialing purposes.
+ *
+ * Note that in this version, if the number was entered originally using alpha characters and
+ * this version of the number is stored in raw_input, this representation of the number will be
+ * used rather than the digit representation. Grouping information, as specified by characters
+ * such as "-" and " ", will be retained.
+ *
+ * <p><b>Caveats:</b></p>
+ * <ul>
+ * <li> This will not produce good results if the country calling code is both present in the raw
+ * input _and_ is the start of the national number. This is not a problem in the regions
+ * which typically use alpha numbers.
+ * <li> This will also not produce good results if the raw input has any grouping information
+ * within the first three digits of the national number, and if the function needs to strip
+ * preceding digits/words in the raw input before these digits. Normally people group the
+ * first three digits together so this is not a huge problem - and will be fixed if it
+ * proves to be so.
+ * </ul>
+ *
+ * @param number the phone number that needs to be formatted
+ * @param regionCallingFrom the region where the call is being placed
+ * @return the formatted phone number
+ */
+ public String formatOutOfCountryKeepingAlphaChars(PhoneNumber number,
+ String regionCallingFrom) {
+ String rawInput = number.getRawInput();
+ // If there is no raw input, then we can't keep alpha characters because there aren't any.
+ // In this case, we return formatOutOfCountryCallingNumber.
+ if (rawInput.length() == 0) {
+ return formatOutOfCountryCallingNumber(number, regionCallingFrom);
+ }
+ int countryCode = number.getCountryCode();
+ if (!hasValidCountryCallingCode(countryCode)) {
+ return rawInput;
+ }
+ // Strip any prefix such as country calling code, IDD, that was present. We do this by comparing
+ // the number in raw_input with the parsed number.
+ // To do this, first we normalize punctuation. We retain number grouping symbols such as " "
+ // only.
+ rawInput = normalizeHelper(rawInput, ALL_PLUS_NUMBER_GROUPING_SYMBOLS, true);
+ // Now we trim everything before the first three digits in the parsed number. We choose three
+ // because all valid alpha numbers have 3 digits at the start - if it does not, then we don't
+ // trim anything at all. Similarly, if the national number was less than three digits, we don't
+ // trim anything at all.
+ String nationalNumber = getNationalSignificantNumber(number);
+ if (nationalNumber.length() > 3) {
+ int firstNationalNumberDigit = rawInput.indexOf(nationalNumber.substring(0, 3));
+ if (firstNationalNumberDigit != -1) {
+ rawInput = rawInput.substring(firstNationalNumberDigit);
+ }
+ }
+ PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom);
+ if (countryCode == NANPA_COUNTRY_CODE) {
+ if (isNANPACountry(regionCallingFrom)) {
+ return countryCode + " " + rawInput;
+ }
+ } else if (metadataForRegionCallingFrom != null &&
+ countryCode == getCountryCodeForValidRegion(regionCallingFrom)) {
+ NumberFormat formattingPattern =
+ chooseFormattingPatternForNumber(metadataForRegionCallingFrom.numberFormats(),
+ nationalNumber);
+ if (formattingPattern == null) {
+ // If no pattern above is matched, we format the original input.
+ return rawInput;
+ }
+ NumberFormat newFormat = new NumberFormat();
+ newFormat.mergeFrom(formattingPattern);
+ // The first group is the first group of digits that the user wrote together.
+ newFormat.setPattern("(\\d+)(.*)");
+ // Here we just concatenate them back together after the national prefix has been fixed.
+ newFormat.setFormat("$1$2");
+ // Now we format using this pattern instead of the default pattern, but with the national
+ // prefix prefixed if necessary.
+ // This will not work in the cases where the pattern (and not the leading digits) decide
+ // whether a national prefix needs to be used, since we have overridden the pattern to match
+ // anything, but that is not the case in the metadata to date.
+ return formatNsnUsingPattern(rawInput, newFormat, PhoneNumberFormat.NATIONAL);
+ }
+ 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);
+ 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);
+ 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.
+ logger.log(Level.WARNING,
+ "Trying to format number from invalid region "
+ + regionCallingFrom
+ + ". International formatting applied.");
+ prefixNumberWithCountryCallingCode(countryCode,
+ PhoneNumberFormat.INTERNATIONAL,
+ formattedNumber);
+ }
+ return formattedNumber.toString();
+ }
+
+ /**
+ * Gets the national significant number of the a phone number. Note a national significant number
+ * doesn't contain a national prefix or any formatting.
+ *
+ * @param number the phone number for which the national significant number is needed
+ * @return the national significant number of the PhoneNumber object passed in
+ */
+ public String getNationalSignificantNumber(PhoneNumber number) {
+ // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix.
+ StringBuilder nationalNumber = new StringBuilder();
+ if (number.isItalianLeadingZero()) {
+ char[] zeros = new char[number.getNumberOfLeadingZeros()];
+ Arrays.fill(zeros, '0');
+ nationalNumber.append(new String(zeros));
+ }
+ nationalNumber.append(number.getNationalNumber());
+ return nationalNumber.toString();
+ }
+
+ /**
+ * A helper function that is used by format and formatByPattern.
+ */
+ private void prefixNumberWithCountryCallingCode(int countryCallingCode,
+ PhoneNumberFormat numberFormat,
+ StringBuilder formattedNumber) {
+ switch (numberFormat) {
+ case E164:
+ formattedNumber.insert(0, countryCallingCode).insert(0, PLUS_SIGN);
+ return;
+ case INTERNATIONAL:
+ formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, PLUS_SIGN);
+ return;
+ case RFC3966:
+ formattedNumber.insert(0, "-").insert(0, countryCallingCode).insert(0, PLUS_SIGN)
+ .insert(0, RFC3966_PREFIX);
+ return;
+ case NATIONAL:
+ default:
+ return;
+ }
+ }
+
+ // Simple wrapper of formatNsn for the common case of no carrier code.
+ private String formatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat) {
+ return formatNsn(number, metadata, numberFormat, null);
+ }
+
+ // Note in some regions, the national number can be written in two completely different ways
+ // depending on whether it forms part of the NATIONAL format or INTERNATIONAL format. The
+ // numberFormat parameter here is used to specify which format to use for those cases. If a
+ // carrierCode is specified, this will be inserted into the formatted string to replace $CC.
+ private String formatNsn(String number,
+ PhoneMetadata metadata,
+ PhoneNumberFormat numberFormat,
+ String carrierCode) {
+ List<NumberFormat> intlNumberFormats = metadata.intlNumberFormats();
+ // When the intlNumberFormats exists, we use that to format national number for the
+ // INTERNATIONAL format instead of using the numberDesc.numberFormats.
+ List<NumberFormat> availableFormats =
+ (intlNumberFormats.size() == 0 || numberFormat == PhoneNumberFormat.NATIONAL)
+ ? metadata.numberFormats()
+ : metadata.intlNumberFormats();
+ NumberFormat formattingPattern = chooseFormattingPatternForNumber(availableFormats, number);
+ return (formattingPattern == null)
+ ? number
+ : formatNsnUsingPattern(number, formattingPattern, numberFormat, carrierCode);
+ }
+
+ NumberFormat chooseFormattingPatternForNumber(List<NumberFormat> availableFormats,
+ String nationalNumber) {
+ for (NumberFormat numFormat : availableFormats) {
+ int size = numFormat.leadingDigitsPatternSize();
+ if (size == 0 || regexCache.getPatternForRegex(
+ // We always use the last leading_digits_pattern, as it is the most detailed.
+ numFormat.getLeadingDigitsPattern(size - 1)).matcher(nationalNumber).lookingAt()) {
+ Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber);
+ if (m.matches()) {
+ return numFormat;
+ }
+ }
+ }
+ return null;
+ }
+
+ // Simple wrapper of formatNsnUsingPattern for the common case of no carrier code.
+ String formatNsnUsingPattern(String nationalNumber,
+ NumberFormat formattingPattern,
+ PhoneNumberFormat numberFormat) {
+ return formatNsnUsingPattern(nationalNumber, formattingPattern, numberFormat, null);
+ }
+
+ // 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,
+ PhoneNumberFormat numberFormat,
+ String carrierCode) {
+ String numberFormatRule = formattingPattern.getFormat();
+ Matcher m =
+ regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber);
+ String formattedNationalNumber = "";
+ if (numberFormat == PhoneNumberFormat.NATIONAL &&
+ carrierCode != null && carrierCode.length() > 0 &&
+ formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) {
+ // Replace the $CC in the formatting rule with the desired carrier code.
+ String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule();
+ carrierCodeFormattingRule =
+ CC_PATTERN.matcher(carrierCodeFormattingRule).replaceFirst(carrierCode);
+ // Now replace the $FG in the formatting rule with the first group and the carrier code
+ // combined in the appropriate way.
+ numberFormatRule = FIRST_GROUP_PATTERN.matcher(numberFormatRule)
+ .replaceFirst(carrierCodeFormattingRule);
+ formattedNationalNumber = m.replaceAll(numberFormatRule);
+ } else {
+ // Use the national prefix formatting rule instead.
+ String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule();
+ if (numberFormat == PhoneNumberFormat.NATIONAL &&
+ nationalPrefixFormattingRule != null &&
+ nationalPrefixFormattingRule.length() > 0) {
+ Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule);
+ formattedNationalNumber =
+ m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule));
+ } else {
+ formattedNationalNumber = m.replaceAll(numberFormatRule);
+ }
+ }
+ if (numberFormat == PhoneNumberFormat.RFC3966) {
+ // Strip any leading punctuation.
+ Matcher matcher = SEPARATOR_PATTERN.matcher(formattedNationalNumber);
+ if (matcher.lookingAt()) {
+ formattedNationalNumber = matcher.replaceFirst("");
+ }
+ // Replace the rest with a dash between each number group.
+ formattedNationalNumber = matcher.reset(formattedNationalNumber).replaceAll("-");
+ }
+ return formattedNationalNumber;
+ }
+
+ /**
+ * Gets a valid number for the specified region.
+ *
+ * @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, 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);
+ }
+
+ /**
+ * Gets a valid number for the specified region and number type.
+ *
+ * @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 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.
+ if (!isValidRegionCode(regionCode)) {
+ logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode);
+ return null;
+ }
+ PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), type);
+ try {
+ if (desc.hasExampleNumber()) {
+ return parse(desc.getExampleNumber(), regionCode);
+ }
+ } catch (NumberParseException e) {
+ logger.log(Level.SEVERE, e.toString());
+ }
+ 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());
+ }
+ } else {
+ logger.log(Level.WARNING,
+ "Invalid or unknown country calling code provided: " + countryCallingCode);
+ }
+ return null;
+ }
+
+ /**
+ * Appends the formatted extension of a phone number to formattedNumber, if the phone number had
+ * an extension specified.
+ */
+ private void maybeAppendFormattedExtension(PhoneNumber number, PhoneMetadata metadata,
+ PhoneNumberFormat numberFormat,
+ StringBuilder formattedNumber) {
+ if (number.hasExtension() && number.getExtension().length() > 0) {
+ if (numberFormat == PhoneNumberFormat.RFC3966) {
+ formattedNumber.append(RFC3966_EXTN_PREFIX).append(number.getExtension());
+ } else {
+ if (metadata.hasPreferredExtnPrefix()) {
+ formattedNumber.append(metadata.getPreferredExtnPrefix()).append(number.getExtension());
+ } else {
+ formattedNumber.append(DEFAULT_EXTN_PREFIX).append(number.getExtension());
+ }
+ }
+ }
+ }
+
+ PhoneNumberDesc getNumberDescByType(PhoneMetadata metadata, PhoneNumberType type) {
+ switch (type) {
+ case PREMIUM_RATE:
+ return metadata.getPremiumRate();
+ case TOLL_FREE:
+ return metadata.getTollFree();
+ case MOBILE:
+ return metadata.getMobile();
+ case FIXED_LINE:
+ case FIXED_LINE_OR_MOBILE:
+ return metadata.getFixedLine();
+ case SHARED_COST:
+ return metadata.getSharedCost();
+ case VOIP:
+ return metadata.getVoip();
+ case PERSONAL_NUMBER:
+ return metadata.getPersonalNumber();
+ case PAGER:
+ return metadata.getPager();
+ case UAN:
+ return metadata.getUan();
+ case VOICEMAIL:
+ return metadata.getVoicemail();
+ default:
+ return metadata.getGeneralDesc();
+ }
+ }
+
+ /**
+ * Gets the type of a phone number.
+ *
+ * @param number the phone number that we want to know the type
+ * @return the type of the phone number
+ */
+ public PhoneNumberType getNumberType(PhoneNumber number) {
+ String regionCode = getRegionCodeForNumber(number);
+ PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode);
+ if (metadata == null) {
+ return PhoneNumberType.UNKNOWN;
+ }
+ String nationalSignificantNumber = getNationalSignificantNumber(number);
+ return getNumberTypeHelper(nationalSignificantNumber, metadata);
+ }
+
+ private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) {
+ if (!isNumberMatchingDesc(nationalNumber, metadata.getGeneralDesc())) {
+ return PhoneNumberType.UNKNOWN;
+ }
+
+ if (isNumberMatchingDesc(nationalNumber, metadata.getPremiumRate())) {
+ return PhoneNumberType.PREMIUM_RATE;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getTollFree())) {
+ return PhoneNumberType.TOLL_FREE;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getSharedCost())) {
+ return PhoneNumberType.SHARED_COST;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getVoip())) {
+ return PhoneNumberType.VOIP;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getPersonalNumber())) {
+ return PhoneNumberType.PERSONAL_NUMBER;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getPager())) {
+ return PhoneNumberType.PAGER;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getUan())) {
+ return PhoneNumberType.UAN;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getVoicemail())) {
+ return PhoneNumberType.VOICEMAIL;
+ }
+
+ boolean isFixedLine = isNumberMatchingDesc(nationalNumber, metadata.getFixedLine());
+ if (isFixedLine) {
+ if (metadata.isSameMobileAndFixedLinePattern()) {
+ return PhoneNumberType.FIXED_LINE_OR_MOBILE;
+ } else if (isNumberMatchingDesc(nationalNumber, metadata.getMobile())) {
+ return PhoneNumberType.FIXED_LINE_OR_MOBILE;
+ }
+ return PhoneNumberType.FIXED_LINE;
+ }
+ // Otherwise, test to see if the number is mobile. Only do this if certain that the patterns for
+ // mobile and fixed line aren't the same.
+ if (!metadata.isSameMobileAndFixedLinePattern() &&
+ isNumberMatchingDesc(nationalNumber, metadata.getMobile())) {
+ return PhoneNumberType.MOBILE;
+ }
+ 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;
+ }
+ synchronized (regionToMetadataMap) {
+ if (!regionToMetadataMap.containsKey(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, metadataLoader);
+ }
+ }
+ 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, metadataLoader);
+ }
+ }
+ return countryCodeToNonGeographicalMetadataMap.get(countryCallingCode);
+ }
+
+ boolean isNumberPossibleForDesc(String nationalNumber, PhoneNumberDesc numberDesc) {
+ Matcher possibleNumberPatternMatcher =
+ regexCache.getPatternForRegex(numberDesc.getPossibleNumberPattern())
+ .matcher(nationalNumber);
+ return possibleNumberPatternMatcher.matches();
+ }
+
+ boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) {
+ Matcher nationalNumberPatternMatcher =
+ regexCache.getPatternForRegex(numberDesc.getNationalNumberPattern())
+ .matcher(nationalNumber);
+ return isNumberPossibleForDesc(nationalNumber, numberDesc) &&
+ nationalNumberPatternMatcher.matches();
+ }
+
+ /**
+ * Tests whether a phone number matches a valid pattern. Note this doesn't verify the number
+ * is actually in use, which is impossible to tell by just looking at a number itself.
+ *
+ * @param number the phone number that we want to validate
+ * @return a boolean that indicates whether the number is of a valid pattern
+ */
+ public boolean isValidNumber(PhoneNumber number) {
+ String regionCode = getRegionCodeForNumber(number);
+ return isValidNumberForRegion(number, regionCode);
+ }
+
+ /**
+ * Tests whether a phone number is valid for a certain region. Note this doesn't verify the number
+ * is actually in use, which is impossible to tell by just looking at a number itself. If the
+ * country calling code is not the same as the country calling code for the region, this
+ * 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
+ * @return a boolean that indicates whether the number is of a valid pattern
+ */
+ public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) {
+ int countryCode = number.getCountryCode();
+ PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode);
+ if ((metadata == null) ||
+ (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) &&
+ countryCode != getCountryCodeForValidRegion(regionCode))) {
+ // Either the region code was invalid, or the country calling code for this number does not
+ // match that of the region code.
+ return false;
+ }
+ String nationalSignificantNumber = getNationalSignificantNumber(number);
+ return getNumberTypeHelper(nationalSignificantNumber, metadata) != PhoneNumberType.UNKNOWN;
+ }
+
+ /**
+ * Returns the region where a phone number is from. This could be used for geocoding at the region
+ * level.
+ *
+ * @param number the phone number whose origin we want to know
+ * @return the region where the phone number is from, or null if no region matches this calling
+ * code
+ */
+ public String getRegionCodeForNumber(PhoneNumber number) {
+ int countryCode = number.getCountryCode();
+ List<String> 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) {
+ return regions.get(0);
+ } else {
+ return getRegionCodeForNumberFromRegionList(number, regions);
+ }
+ }
+
+ private String getRegionCodeForNumberFromRegionList(PhoneNumber number,
+ List<String> regionCodes) {
+ 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())
+ .matcher(nationalNumber).lookingAt()) {
+ return regionCode;
+ }
+ } else if (getNumberTypeHelper(nationalNumber, metadata) != PhoneNumberType.UNKNOWN) {
+ return regionCode;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the region code that matches the specific country calling code. In the case of no
+ * region code being found, ZZ will be returned. In the case of multiple regions, the one
+ * designated in the metadata as the "main" region for this calling code will be returned. If the
+ * countryCallingCode entered is valid but doesn't match a specific region (such as in the case of
+ * non-geographical calling codes like 800) the value "001" will be returned (corresponding to
+ * the value for World in the UN M.49 schema).
+ */
+ public String getRegionCodeForCountryCode(int countryCallingCode) {
+ List<String> regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode);
+ 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.
+ *
+ * @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
+ */
+ public int getCountryCodeForRegion(String regionCode) {
+ if (!isValidRegionCode(regionCode)) {
+ logger.log(Level.WARNING,
+ "Invalid or missing region code ("
+ + ((regionCode == null) ? "null" : regionCode)
+ + ") provided.");
+ return 0;
+ }
+ return getCountryCodeForValidRegion(regionCode);
+ }
+
+ /**
+ * Returns the country calling code for a specific region. For example, this would be 1 for the
+ * United States, and 64 for New Zealand. Assumes the region is already valid.
+ *
+ * @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();
+ }
+
+ /**
+ * Returns the national dialling prefix for a specific region. For example, this would be 1 for
+ * the United States, and 0 for New Zealand. Set stripNonDigits to true to strip symbols like "~"
+ * (which indicates a wait for a dialling tone) from the prefix returned. If no national prefix is
+ * present, we return null.
+ *
+ * <p>Warning: Do not use this method for do-your-own formatting - for some regions, the
+ * national dialling prefix is used only for certain types of numbers. Use the library's
+ * formatting functions to prefix the national prefix when required.
+ *
+ * @param regionCode the region that we want to get the dialling prefix for
+ * @param stripNonDigits true to strip non-digits from the national dialling prefix
+ * @return the dialling prefix for the region denoted by regionCode
+ */
+ public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) {
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ if (metadata == null) {
+ logger.log(Level.WARNING,
+ "Invalid or missing region code ("
+ + ((regionCode == null) ? "null" : regionCode)
+ + ") provided.");
+ return null;
+ }
+ String nationalPrefix = metadata.getNationalPrefix();
+ // If no national prefix was found, we return null.
+ if (nationalPrefix.length() == 0) {
+ return null;
+ }
+ if (stripNonDigits) {
+ // Note: if any other non-numeric symbols are ever used in national prefixes, these would have
+ // to be removed here as well.
+ nationalPrefix = nationalPrefix.replace("~", "");
+ }
+ return nationalPrefix;
+ }
+
+ /**
+ * Checks if this is a region under the North American Numbering Plan Administration (NANPA).
+ *
+ * @return true if regionCode is one of the regions under NANPA
+ */
+ public boolean isNANPACountry(String regionCode) {
+ return nanpaRegions.contains(regionCode);
+ }
+
+ /**
+ * Checks whether the country calling code is from a region whose national significant number
+ * could contain a leading zero. An example of such a region is Italy. Returns false if no
+ * metadata for the country is found.
+ */
+ boolean isLeadingZeroPossible(int countryCallingCode) {
+ PhoneMetadata mainMetadataForCallingCode =
+ getMetadataForRegionOrCallingCode(countryCallingCode,
+ getRegionCodeForCountryCode(countryCallingCode));
+ if (mainMetadataForCallingCode == null) {
+ return false;
+ }
+ return mainMetadataForCallingCode.isLeadingZeroPossible();
+ }
+
+ /**
+ * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. A valid vanity
+ * number will start with at least 3 digits and will have three or more alpha characters. This
+ * does not do region-specific checks - to work out if this number is actually valid for a region,
+ * it should be parsed and methods such as {@link #isPossibleNumberWithReason} and
+ * {@link #isValidNumber} should be used.
+ *
+ * @param number the number that needs to be checked
+ * @return true if the number is a valid vanity number
+ */
+ public boolean isAlphaNumber(String number) {
+ if (!isViablePhoneNumber(number)) {
+ // Number is too short, or doesn't match the basic phone number pattern.
+ return false;
+ }
+ StringBuilder strippedNumber = new StringBuilder(number);
+ maybeStripExtension(strippedNumber);
+ return VALID_ALPHA_PHONE_PATTERN.matcher(strippedNumber).matches();
+ }
+
+ /**
+ * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of returning the reason
+ * for failure, this method returns a boolean value.
+ * @param number the number that needs to be checked
+ * @return true if the number is possible
+ */
+ public boolean isPossibleNumber(PhoneNumber number) {
+ return isPossibleNumberWithReason(number) == ValidationResult.IS_POSSIBLE;
+ }
+
+ /**
+ * Helper method to check a number against a particular pattern and determine whether it matches,
+ * or is too short or too long. Currently, if a number pattern suggests that numbers of length 7
+ * and 10 are possible, and a number in between these possible lengths is entered, such as of
+ * length 8, this will return TOO_LONG.
+ */
+ private ValidationResult testNumberLengthAgainstPattern(Pattern numberPattern, String number) {
+ Matcher numberMatcher = numberPattern.matcher(number);
+ if (numberMatcher.matches()) {
+ return ValidationResult.IS_POSSIBLE;
+ }
+ if (numberMatcher.lookingAt()) {
+ return ValidationResult.TOO_LONG;
+ } else {
+ return ValidationResult.TOO_SHORT;
+ }
+ }
+
+ /**
+ * Helper method to check whether a number is too short to be a regular length phone number in a
+ * region.
+ */
+ private boolean isShorterThanPossibleNormalNumber(PhoneMetadata regionMetadata, String number) {
+ Pattern possibleNumberPattern = regexCache.getPatternForRegex(
+ regionMetadata.getGeneralDesc().getPossibleNumberPattern());
+ return testNumberLengthAgainstPattern(possibleNumberPattern, number) ==
+ ValidationResult.TOO_SHORT;
+ }
+
+ /**
+ * Check whether a phone number is a possible number. It provides a more lenient check than
+ * {@link #isValidNumber} in the following sense:
+ *<ol>
+ * <li> It only checks the length of phone numbers. In particular, it doesn't check starting
+ * digits of the number.
+ * <li> It doesn't attempt to figure out the type of the number, but uses general rules which
+ * applies to all types of phone numbers in a region. Therefore, it is much faster than
+ * isValidNumber.
+ * <li> For fixed line numbers, many regions have the concept of area code, which together with
+ * subscriber number constitute the national significant number. It is sometimes okay to dial
+ * the subscriber number only when dialing in the same area. This function will return
+ * true if the subscriber-number-only version is passed in. On the other hand, because
+ * isValidNumber validates using information on both starting digits (for fixed line
+ * 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>
+ * @param number the number that needs to be checked
+ * @return a ValidationResult object which indicates whether the number is possible
+ */
+ public ValidationResult isPossibleNumberWithReason(PhoneNumber number) {
+ String nationalNumber = getNationalSignificantNumber(number);
+ int countryCode = number.getCountryCode();
+ // Note: For Russian Fed and NANPA numbers, we just use the rules from the default region (US or
+ // 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.
+ if (!hasValidCountryCallingCode(countryCode)) {
+ 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);
+ Pattern possibleNumberPattern =
+ regexCache.getPatternForRegex(metadata.getGeneralDesc().getPossibleNumberPattern());
+ return testNumberLengthAgainstPattern(possibleNumberPattern, nationalNumber);
+ }
+
+ /**
+ * Check whether a phone number is a possible number given a number in the form of a string, and
+ * the region where the number could be dialed from. It provides a more lenient check than
+ * {@link #isValidNumber}. See {@link #isPossibleNumber(PhoneNumber)} for details.
+ *
+ * <p>This method first parses the number, then invokes {@link #isPossibleNumber(PhoneNumber)}
+ * with the resultant PhoneNumber object.
+ *
+ * @param number the number that needs to be checked, in the form of a string
+ * @param regionDialingFrom the region that we are expecting the number to be dialed from.
+ * Note this is different from the region where the number belongs. For example, the number
+ * +1 650 253 0000 is a number that belongs to US. When written in this form, it can be
+ * dialed from any region. When it is written as 00 1 650 253 0000, it can be dialed from any
+ * region which uses an international dialling prefix of 00. When it is written as
+ * 650 253 0000, it can only be dialed from within the US, and when written as 253 0000, it
+ * can only be dialed from within a smaller area in the US (Mountain View, CA, to be more
+ * specific).
+ * @return true if the number is possible
+ */
+ public boolean isPossibleNumber(String number, String regionDialingFrom) {
+ try {
+ return isPossibleNumber(parse(number, regionDialingFrom));
+ } catch (NumberParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Attempts to extract a valid number from a phone number that is too long to be valid, and resets
+ * the PhoneNumber object passed in to that valid version. If no valid number could be extracted,
+ * the PhoneNumber object passed in will not be modified.
+ * @param number a PhoneNumber object which contains a number that is too long to be valid.
+ * @return true if a valid phone number can be successfully extracted.
+ */
+ public boolean truncateTooLongNumber(PhoneNumber number) {
+ if (isValidNumber(number)) {
+ return true;
+ }
+ PhoneNumber numberCopy = new PhoneNumber();
+ numberCopy.mergeFrom(number);
+ long nationalNumber = number.getNationalNumber();
+ do {
+ nationalNumber /= 10;
+ numberCopy.setNationalNumber(nationalNumber);
+ if (isPossibleNumberWithReason(numberCopy) == ValidationResult.TOO_SHORT ||
+ nationalNumber == 0) {
+ return false;
+ }
+ } while (!isValidNumber(numberCopy));
+ number.setNationalNumber(nationalNumber);
+ return true;
+ }
+
+ /**
+ * Gets an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} for the specific region.
+ *
+ * @param regionCode the region where the phone number is being entered
+ * @return an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} object, which can be used
+ * to format phone numbers in the specific region "as you type"
+ */
+ public AsYouTypeFormatter getAsYouTypeFormatter(String regionCode) {
+ return new AsYouTypeFormatter(regionCode);
+ }
+
+ // Extracts country calling code from fullNumber, returns it and places the remaining number in
+ // nationalNumber. It assumes that the leading plus sign or IDD has already been removed. Returns
+ // 0 if fullNumber doesn't start with a valid country calling code, and leaves nationalNumber
+ // unmodified.
+ int extractCountryCode(StringBuilder fullNumber, StringBuilder nationalNumber) {
+ if ((fullNumber.length() == 0) || (fullNumber.charAt(0) == '0')) {
+ // Country codes do not begin with a '0'.
+ return 0;
+ }
+ int potentialCountryCode;
+ int numberLength = fullNumber.length();
+ for (int i = 1; i <= MAX_LENGTH_COUNTRY_CODE && i <= numberLength; i++) {
+ potentialCountryCode = Integer.parseInt(fullNumber.substring(0, i));
+ if (countryCallingCodeToRegionCodeMap.containsKey(potentialCountryCode)) {
+ nationalNumber.append(fullNumber.substring(i));
+ return potentialCountryCode;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Tries to extract a country calling code from a number. This method will return zero if no
+ * country calling code is considered to be present. Country calling codes are extracted in the
+ * following ways:
+ * <ul>
+ * <li> by stripping the international dialing prefix of the region the person is dialing from,
+ * if this is present in the number, and looking at the next digits
+ * <li> by stripping the '+' sign if present and then looking at the next digits
+ * <li> by comparing the start of the number and the country calling code of the default region.
+ * If the number is not considered possible for the numbering plan of the default region
+ * initially, but starts with the country calling code of this region, validation will be
+ * reattempted after stripping this country calling code. If this number is considered a
+ * possible number, then the first digits will be considered the country calling code and
+ * removed as such.
+ * </ul>
+ * It will throw a NumberParseException if the number starts with a '+' but the country calling
+ * code supplied after this does not match that of any known region.
+ *
+ * @param number non-normalized telephone number that we wish to extract a country calling
+ * code from - may begin with '+'
+ * @param defaultRegionMetadata metadata about the region this number may be from
+ * @param nationalNumber a string buffer to store the national significant number in, in the case
+ * that a country calling code was extracted. The number is appended to any existing contents.
+ * If no country calling code was extracted, this will be left unchanged.
+ * @param keepRawInput true if the country_code_source and preferred_carrier_code fields of
+ * phoneNumber should be populated.
+ * @param phoneNumber the PhoneNumber object where the country_code and country_code_source need
+ * to be populated. Note the country_code is always populated, whereas country_code_source is
+ * only populated when keepCountryCodeSource is true.
+ * @return the country calling code extracted or 0 if none could be extracted
+ */
+ // @VisibleForTesting
+ int maybeExtractCountryCode(String number, PhoneMetadata defaultRegionMetadata,
+ StringBuilder nationalNumber, boolean keepRawInput,
+ PhoneNumber phoneNumber)
+ throws NumberParseException {
+ if (number.length() == 0) {
+ return 0;
+ }
+ StringBuilder fullNumber = new StringBuilder(number);
+ // Set the default prefix to be something that will never match.
+ String possibleCountryIddPrefix = "NonMatch";
+ if (defaultRegionMetadata != null) {
+ possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
+ }
+
+ CountryCodeSource countryCodeSource =
+ maybeStripInternationalPrefixAndNormalize(fullNumber, possibleCountryIddPrefix);
+ if (keepRawInput) {
+ phoneNumber.setCountryCodeSource(countryCodeSource);
+ }
+ if (countryCodeSource != CountryCodeSource.FROM_DEFAULT_COUNTRY) {
+ if (fullNumber.length() <= MIN_LENGTH_FOR_NSN) {
+ throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD,
+ "Phone number had an IDD, but after this was not "
+ + "long enough to be a viable phone number.");
+ }
+ int potentialCountryCode = extractCountryCode(fullNumber, nationalNumber);
+ if (potentialCountryCode != 0) {
+ phoneNumber.setCountryCode(potentialCountryCode);
+ return potentialCountryCode;
+ }
+
+ // If this fails, they must be using a strange country calling code that we don't recognize,
+ // or that doesn't exist.
+ throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ "Country calling code supplied was not recognised.");
+ } else if (defaultRegionMetadata != null) {
+ // Check to see if the number starts with the country calling code for the default region. If
+ // so, we remove the country calling code, and do some checks on the validity of the number
+ // before and after.
+ int defaultCountryCode = defaultRegionMetadata.getCountryCode();
+ String defaultCountryCodeString = String.valueOf(defaultCountryCode);
+ String normalizedNumber = fullNumber.toString();
+ if (normalizedNumber.startsWith(defaultCountryCodeString)) {
+ StringBuilder potentialNationalNumber =
+ new StringBuilder(normalizedNumber.substring(defaultCountryCodeString.length()));
+ PhoneNumberDesc generalDesc = defaultRegionMetadata.getGeneralDesc();
+ Pattern validNumberPattern =
+ regexCache.getPatternForRegex(generalDesc.getNationalNumberPattern());
+ maybeStripNationalPrefixAndCarrierCode(
+ potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */);
+ Pattern possibleNumberPattern =
+ regexCache.getPatternForRegex(generalDesc.getPossibleNumberPattern());
+ // If the number was not valid before but is valid now, or if it was too long before, we
+ // consider the number with the country calling code stripped to be a better result and
+ // keep that instead.
+ if ((!validNumberPattern.matcher(fullNumber).matches() &&
+ validNumberPattern.matcher(potentialNationalNumber).matches()) ||
+ testNumberLengthAgainstPattern(possibleNumberPattern, fullNumber.toString())
+ == ValidationResult.TOO_LONG) {
+ nationalNumber.append(potentialNationalNumber);
+ if (keepRawInput) {
+ phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
+ }
+ phoneNumber.setCountryCode(defaultCountryCode);
+ return defaultCountryCode;
+ }
+ }
+ }
+ // No country calling code present.
+ phoneNumber.setCountryCode(0);
+ return 0;
+ }
+
+ /**
+ * Strips the IDD from the start of the number if present. Helper function used by
+ * maybeStripInternationalPrefixAndNormalize.
+ */
+ private boolean parsePrefixAsIdd(Pattern iddPattern, StringBuilder number) {
+ Matcher m = iddPattern.matcher(number);
+ if (m.lookingAt()) {
+ int matchEnd = m.end();
+ // Only strip this if the first digit after the match is not a 0, since country calling codes
+ // cannot begin with 0.
+ Matcher digitMatcher = CAPTURING_DIGIT_PATTERN.matcher(number.substring(matchEnd));
+ if (digitMatcher.find()) {
+ String normalizedGroup = normalizeDigitsOnly(digitMatcher.group(1));
+ if (normalizedGroup.equals("0")) {
+ return false;
+ }
+ }
+ number.delete(0, matchEnd);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Strips any international prefix (such as +, 00, 011) present in the number provided, normalizes
+ * the resulting number, and indicates if an international prefix was present.
+ *
+ * @param number the non-normalized telephone number that we wish to strip any international
+ * dialing prefix from.
+ * @param possibleIddPrefix the international direct dialing prefix from the region we
+ * think this number may be dialed in
+ * @return the corresponding CountryCodeSource if an international dialing prefix could be
+ * removed from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if the number did
+ * not seem to be in international format.
+ */
+ // @VisibleForTesting
+ CountryCodeSource maybeStripInternationalPrefixAndNormalize(
+ StringBuilder number,
+ String possibleIddPrefix) {
+ if (number.length() == 0) {
+ return CountryCodeSource.FROM_DEFAULT_COUNTRY;
+ }
+ // Check to see if the number begins with one or more plus signs.
+ Matcher m = PLUS_CHARS_PATTERN.matcher(number);
+ if (m.lookingAt()) {
+ number.delete(0, m.end());
+ // Can now normalize the rest of the number since we've consumed the "+" sign at the start.
+ normalize(number);
+ return CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN;
+ }
+ // Attempt to parse the first digits as an international prefix.
+ Pattern iddPattern = regexCache.getPatternForRegex(possibleIddPrefix);
+ normalize(number);
+ return parsePrefixAsIdd(iddPattern, number)
+ ? CountryCodeSource.FROM_NUMBER_WITH_IDD
+ : CountryCodeSource.FROM_DEFAULT_COUNTRY;
+ }
+
+ /**
+ * Strips any national prefix (such as 0, 1) present in the number provided.
+ *
+ * @param number the normalized telephone number that we wish to strip any national
+ * dialing prefix from
+ * @param metadata the metadata for the region that we think this number is from
+ * @param carrierCode a place to insert the carrier code if one is extracted
+ * @return true if a national prefix or carrier code (or both) could be extracted.
+ */
+ // @VisibleForTesting
+ boolean maybeStripNationalPrefixAndCarrierCode(
+ StringBuilder number, PhoneMetadata metadata, StringBuilder carrierCode) {
+ int numberLength = number.length();
+ String possibleNationalPrefix = metadata.getNationalPrefixForParsing();
+ if (numberLength == 0 || possibleNationalPrefix.length() == 0) {
+ // Early return for numbers of zero length.
+ return false;
+ }
+ // Attempt to parse the first digits as a national prefix.
+ Matcher prefixMatcher = regexCache.getPatternForRegex(possibleNationalPrefix).matcher(number);
+ if (prefixMatcher.lookingAt()) {
+ Pattern nationalNumberRule =
+ regexCache.getPatternForRegex(metadata.getGeneralDesc().getNationalNumberPattern());
+ // Check if the original number is viable.
+ boolean isViableOriginalNumber = nationalNumberRule.matcher(number).matches();
+ // prefixMatcher.group(numOfGroups) == null implies nothing was captured by the capturing
+ // groups in possibleNationalPrefix; therefore, no transformation is necessary, and we just
+ // remove the national prefix.
+ int numOfGroups = prefixMatcher.groupCount();
+ String transformRule = metadata.getNationalPrefixTransformRule();
+ if (transformRule == null || transformRule.length() == 0 ||
+ prefixMatcher.group(numOfGroups) == null) {
+ // If the original number was viable, and the resultant number is not, we return.
+ if (isViableOriginalNumber &&
+ !nationalNumberRule.matcher(number.substring(prefixMatcher.end())).matches()) {
+ return false;
+ }
+ if (carrierCode != null && numOfGroups > 0 && prefixMatcher.group(numOfGroups) != null) {
+ carrierCode.append(prefixMatcher.group(1));
+ }
+ number.delete(0, prefixMatcher.end());
+ return true;
+ } else {
+ // Check that the resultant number is still viable. If not, return. Check this by copying
+ // the string buffer and making the transformation on the copy first.
+ StringBuilder transformedNumber = new StringBuilder(number);
+ transformedNumber.replace(0, numberLength, prefixMatcher.replaceFirst(transformRule));
+ if (isViableOriginalNumber &&
+ !nationalNumberRule.matcher(transformedNumber.toString()).matches()) {
+ return false;
+ }
+ if (carrierCode != null && numOfGroups > 1) {
+ carrierCode.append(prefixMatcher.group(1));
+ }
+ number.replace(0, number.length(), transformedNumber.toString());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Strips any extension (as in, the part of the number dialled after the call is connected,
+ * usually indicated with extn, ext, x or similar) from the end of the number, and returns it.
+ *
+ * @param number the non-normalized telephone number that we wish to strip the extension from
+ * @return the phone extension
+ */
+ // @VisibleForTesting
+ String maybeStripExtension(StringBuilder number) {
+ Matcher m = EXTN_PATTERN.matcher(number);
+ // If we find a potential extension, and the number preceding this is a viable number, we assume
+ // it is an extension.
+ if (m.find() && isViablePhoneNumber(number.substring(0, m.start()))) {
+ // The numbers are captured into groups in the regular expression.
+ for (int i = 1, length = m.groupCount(); i <= length; i++) {
+ if (m.group(i) != null) {
+ // We go through the capturing groups until we find one that captured some digits. If none
+ // did, then we will return the empty string.
+ String extension = m.group(i);
+ number.delete(m.start(), number.length());
+ return extension;
+ }
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Checks to see that the region code used is valid, or if it is not valid, that the number to
+ * parse starts with a + symbol so that we can attempt to infer the region from the number.
+ * Returns false if it cannot use the region provided and the region cannot be inferred.
+ */
+ private boolean checkRegionForParsing(String numberToParse, String defaultRegion) {
+ if (!isValidRegionCode(defaultRegion)) {
+ // If the number is null or empty, we can't infer the region.
+ if ((numberToParse == null) || (numberToParse.length() == 0) ||
+ !PLUS_CHARS_PATTERN.matcher(numberToParse).lookingAt()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Parses a string and returns it in proto buffer format. This method will throw a
+ * {@link com.google.i18n.phonenumbers.NumberParseException} if the number is not considered to be
+ * a possible number. Note that validation of whether the number is actually a valid number for a
+ * particular region is not performed. This can be done separately with {@link #isValidNumber}.
+ *
+ * @param numberToParse number that we are attempting to parse. This can contain formatting
+ * such as +, ( and -, as well as a phone number extension. It can also
+ * be provided in RFC3966 format.
+ * @param defaultRegion region that we are expecting the number to be from. This is only used
+ * if the number being parsed is not written in international format.
+ * The country_code for the number in this case would be stored as that
+ * of the default region supplied. If the number is guaranteed to
+ * start with a '+' followed by the country calling code, then
+ * "ZZ" or null can be supplied.
+ * @return a phone number proto buffer filled with the parsed number
+ * @throws NumberParseException if the string is not considered to be a viable phone number or if
+ * no default region was supplied and the number is not in
+ * international format (does not start with +)
+ */
+ public PhoneNumber parse(String numberToParse, String defaultRegion)
+ throws NumberParseException {
+ PhoneNumber phoneNumber = new PhoneNumber();
+ parse(numberToParse, defaultRegion, phoneNumber);
+ return phoneNumber;
+ }
+
+ /**
+ * Same as {@link #parse(String, String)}, but accepts mutable PhoneNumber as a parameter to
+ * decrease object creation when invoked many times.
+ */
+ public void parse(String numberToParse, String defaultRegion, PhoneNumber phoneNumber)
+ throws NumberParseException {
+ parseHelper(numberToParse, defaultRegion, false, true, phoneNumber);
+ }
+
+ /**
+ * Parses a string and returns it in proto buffer format. This method differs from {@link #parse}
+ * in that it always populates the raw_input field of the protocol buffer with numberToParse as
+ * well as the country_code_source field.
+ *
+ * @param numberToParse number that we are attempting to parse. This can contain formatting
+ * such as +, ( and -, as well as a phone number extension.
+ * @param defaultRegion region that we are expecting the number to be from. This is only used
+ * if the number being parsed is not written in international format.
+ * The country calling code for the number in this case would be stored
+ * as that of the default region supplied.
+ * @return a phone number proto buffer filled with the parsed number
+ * @throws NumberParseException if the string is not considered to be a viable phone number or if
+ * no default region was supplied
+ */
+ public PhoneNumber parseAndKeepRawInput(String numberToParse, String defaultRegion)
+ throws NumberParseException {
+ PhoneNumber phoneNumber = new PhoneNumber();
+ parseAndKeepRawInput(numberToParse, defaultRegion, phoneNumber);
+ return phoneNumber;
+ }
+
+ /**
+ * Same as{@link #parseAndKeepRawInput(String, String)}, but accepts a mutable PhoneNumber as
+ * a parameter to decrease object creation when invoked many times.
+ */
+ public void parseAndKeepRawInput(String numberToParse, String defaultRegion,
+ PhoneNumber phoneNumber)
+ throws NumberParseException {
+ parseHelper(numberToParse, defaultRegion, true, true, phoneNumber);
+ }
+
+ /**
+ * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. This
+ * is a shortcut for {@link #findNumbers(CharSequence, String, Leniency, long)
+ * getMatcher(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE)}.
+ *
+ * @param text the text to search for phone numbers, null for no text
+ * @param defaultRegion region that we are expecting the number to be from. This is only used
+ * if the number being parsed is not written in international format. The
+ * country_code for the number in this case would be stored as that of
+ * the default region supplied. May be null if only international
+ * numbers are expected.
+ */
+ public Iterable<PhoneNumberMatch> findNumbers(CharSequence text, String defaultRegion) {
+ return findNumbers(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE);
+ }
+
+ /**
+ * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}.
+ *
+ * @param text the text to search for phone numbers, null for no text
+ * @param defaultRegion region that we are expecting the number to be from. This is only used
+ * if the number being parsed is not written in international format. The
+ * country_code for the number in this case would be stored as that of
+ * the default region supplied. May be null if only international
+ * numbers are expected.
+ * @param leniency the leniency to use when evaluating candidate phone numbers
+ * @param maxTries the maximum number of invalid numbers to try before giving up on the
+ * text. This is to cover degenerate cases where the text has a lot of
+ * false positives in it. Must be {@code >= 0}.
+ */
+ public Iterable<PhoneNumberMatch> findNumbers(
+ final CharSequence text, final String defaultRegion, final Leniency leniency,
+ final long maxTries) {
+
+ return new Iterable<PhoneNumberMatch>() {
+ public Iterator<PhoneNumberMatch> iterator() {
+ return new PhoneNumberMatcher(
+ PhoneNumberUtil.this, text, defaultRegion, leniency, maxTries);
+ }
+ };
+ }
+
+ /**
+ * A helper function to set the values related to leading zeros in a PhoneNumber.
+ */
+ static void setItalianLeadingZerosForPhoneNumber(String nationalNumber, PhoneNumber phoneNumber) {
+ if (nationalNumber.length() > 1 && nationalNumber.charAt(0) == '0') {
+ phoneNumber.setItalianLeadingZero(true);
+ int numberOfLeadingZeros = 1;
+ // Note that if the national number is all "0"s, the last "0" is not counted as a leading
+ // zero.
+ while (numberOfLeadingZeros < nationalNumber.length() - 1 &&
+ nationalNumber.charAt(numberOfLeadingZeros) == '0') {
+ numberOfLeadingZeros++;
+ }
+ if (numberOfLeadingZeros != 1) {
+ phoneNumber.setNumberOfLeadingZeros(numberOfLeadingZeros);
+ }
+ }
+ }
+
+ /**
+ * Parses a string and fills up the phoneNumber. This method is the same as the public
+ * parse() method, with the exception that it allows the default region to be null, for use by
+ * isNumberMatch(). checkRegion should be set to false if it is permitted for the default region
+ * to be null or unknown ("ZZ").
+ */
+ private void parseHelper(String numberToParse, String defaultRegion, boolean keepRawInput,
+ boolean checkRegion, PhoneNumber phoneNumber)
+ throws NumberParseException {
+ if (numberToParse == null) {
+ throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER,
+ "The phone number supplied was null.");
+ } else if (numberToParse.length() > MAX_INPUT_STRING_LENGTH) {
+ throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG,
+ "The string supplied was too long to parse.");
+ }
+
+ StringBuilder nationalNumber = new StringBuilder();
+ buildNationalNumberForParsing(numberToParse, nationalNumber);
+
+ if (!isViablePhoneNumber(nationalNumber.toString())) {
+ throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER,
+ "The string supplied did not seem to be a phone number.");
+ }
+
+ // Check the region supplied is valid, or that the extracted number starts with some sort of +
+ // sign so the number's region can be determined.
+ if (checkRegion && !checkRegionForParsing(nationalNumber.toString(), defaultRegion)) {
+ throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ "Missing or invalid default region.");
+ }
+
+ if (keepRawInput) {
+ phoneNumber.setRawInput(numberToParse);
+ }
+ // Attempt to parse extension first, since it doesn't require region-specific data and we want
+ // to have the non-normalised number here.
+ String extension = maybeStripExtension(nationalNumber);
+ if (extension.length() > 0) {
+ phoneNumber.setExtension(extension);
+ }
+
+ PhoneMetadata regionMetadata = getMetadataForRegion(defaultRegion);
+ // Check to see if the number is given in international format so we know whether this number is
+ // from the default region or not.
+ StringBuilder normalizedNationalNumber = new StringBuilder();
+ int countryCode = 0;
+ try {
+ // TODO: This method should really just take in the string buffer that has already
+ // been created, and just remove the prefix, rather than taking in a string and then
+ // outputting a string buffer.
+ countryCode = maybeExtractCountryCode(nationalNumber.toString(), regionMetadata,
+ normalizedNationalNumber, keepRawInput, phoneNumber);
+ } catch (NumberParseException e) {
+ Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber.toString());
+ if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE &&
+ matcher.lookingAt()) {
+ // Strip the plus-char, and try again.
+ countryCode = maybeExtractCountryCode(nationalNumber.substring(matcher.end()),
+ regionMetadata, normalizedNationalNumber,
+ keepRawInput, phoneNumber);
+ if (countryCode == 0) {
+ throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ "Could not interpret numbers after plus-sign.");
+ }
+ } else {
+ throw new NumberParseException(e.getErrorType(), e.getMessage());
+ }
+ }
+ 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 {
+ // If no extracted country calling code, use the region supplied instead. The national number
+ // is just the normalized version of the number we were given to parse.
+ normalize(nationalNumber);
+ normalizedNationalNumber.append(nationalNumber);
+ if (defaultRegion != null) {
+ countryCode = regionMetadata.getCountryCode();
+ phoneNumber.setCountryCode(countryCode);
+ } else if (keepRawInput) {
+ phoneNumber.clearCountryCodeSource();
+ }
+ }
+ if (normalizedNationalNumber.length() < MIN_LENGTH_FOR_NSN) {
+ throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN,
+ "The string supplied is too short to be a phone number.");
+ }
+ if (regionMetadata != null) {
+ StringBuilder carrierCode = new StringBuilder();
+ StringBuilder potentialNationalNumber = new StringBuilder(normalizedNationalNumber);
+ maybeStripNationalPrefixAndCarrierCode(potentialNationalNumber, regionMetadata, carrierCode);
+ // We require that the NSN remaining after stripping the national prefix and carrier code be
+ // of a possible length for the region. Otherwise, we don't do the stripping, since the
+ // original number could be a valid short number.
+ if (!isShorterThanPossibleNormalNumber(regionMetadata, potentialNationalNumber.toString())) {
+ normalizedNationalNumber = potentialNationalNumber;
+ if (keepRawInput) {
+ phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString());
+ }
+ }
+ }
+ int lengthOfNationalNumber = normalizedNationalNumber.length();
+ if (lengthOfNationalNumber < MIN_LENGTH_FOR_NSN) {
+ throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN,
+ "The string supplied is too short to be a phone number.");
+ }
+ if (lengthOfNationalNumber > MAX_LENGTH_FOR_NSN) {
+ throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG,
+ "The string supplied is too long to be a phone number.");
+ }
+ setItalianLeadingZerosForPhoneNumber(normalizedNationalNumber.toString(), phoneNumber);
+ phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString()));
+ }
+
+ /**
+ * Converts numberToParse to a form that we can parse and write it to nationalNumber if it is
+ * written in RFC3966; otherwise extract a possible number out of it and write to nationalNumber.
+ */
+ private void buildNationalNumberForParsing(String numberToParse, StringBuilder nationalNumber) {
+ int indexOfPhoneContext = numberToParse.indexOf(RFC3966_PHONE_CONTEXT);
+ if (indexOfPhoneContext > 0) {
+ int phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT.length();
+ // If the phone context contains a phone number prefix, we need to capture it, whereas domains
+ // will be ignored.
+ if (numberToParse.charAt(phoneContextStart) == PLUS_SIGN) {
+ // Additional parameters might follow the phone context. If so, we will remove them here
+ // because the parameters after phone context are not important for parsing the
+ // phone number.
+ int phoneContextEnd = numberToParse.indexOf(';', phoneContextStart);
+ if (phoneContextEnd > 0) {
+ nationalNumber.append(numberToParse.substring(phoneContextStart, phoneContextEnd));
+ } else {
+ nationalNumber.append(numberToParse.substring(phoneContextStart));
+ }
+ }
+
+ // Now append everything between the "tel:" prefix and the phone-context. This should include
+ // the national number, an optional extension or isdn-subaddress component. Note we also
+ // handle the case when "tel:" is missing, as we have seen in some of the phone number inputs.
+ // In that case, we append everything from the beginning.
+ int indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX);
+ int indexOfNationalNumber = (indexOfRfc3966Prefix >= 0) ?
+ indexOfRfc3966Prefix + RFC3966_PREFIX.length() : 0;
+ nationalNumber.append(numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext));
+ } else {
+ // Extract a possible number from the string passed in (this strips leading characters that
+ // could not be the start of a phone number.)
+ nationalNumber.append(extractPossibleNumber(numberToParse));
+ }
+
+ // Delete the isdn-subaddress and everything after it if it is present. Note extension won't
+ // appear at the same time with isdn-subaddress according to paragraph 5.3 of the RFC3966 spec,
+ int indexOfIsdn = nationalNumber.indexOf(RFC3966_ISDN_SUBADDRESS);
+ if (indexOfIsdn > 0) {
+ nationalNumber.delete(indexOfIsdn, nationalNumber.length());
+ }
+ // If both phone context and isdn-subaddress are absent but other parameters are present, the
+ // parameters are left in nationalNumber. This is because we are concerned about deleting
+ // content from a potential number string when there is no strong evidence that the number is
+ // actually written in RFC3966.
+ }
+
+ /**
+ * Takes two phone numbers and compares them for equality.
+ *
+ * <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero for Italian numbers
+ * and any extension present are the same.
+ * Returns NSN_MATCH if either or both has no region specified, and the NSNs and extensions are
+ * the same.
+ * Returns SHORT_NSN_MATCH if either or both has no region specified, or the region specified is
+ * the same, and one NSN could be a shorter version of the other number. This includes the case
+ * where one has an extension specified, and the other does not.
+ * Returns NO_MATCH otherwise.
+ * For example, the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH.
+ * The numbers +1 345 657 1234 and 345 657 are a NO_MATCH.
+ *
+ * @param firstNumberIn first number to compare
+ * @param secondNumberIn second number to compare
+ *
+ * @return NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of equality
+ * of the two numbers, described in the method definition.
+ */
+ public MatchType isNumberMatch(PhoneNumber firstNumberIn, PhoneNumber secondNumberIn) {
+ // Make copies of the phone number so that the numbers passed in are not edited.
+ PhoneNumber firstNumber = new PhoneNumber();
+ firstNumber.mergeFrom(firstNumberIn);
+ PhoneNumber secondNumber = new PhoneNumber();
+ secondNumber.mergeFrom(secondNumberIn);
+ // First clear raw_input, country_code_source and preferred_domestic_carrier_code fields and any
+ // empty-string extensions so that we can use the proto-buffer equality method.
+ firstNumber.clearRawInput();
+ firstNumber.clearCountryCodeSource();
+ firstNumber.clearPreferredDomesticCarrierCode();
+ secondNumber.clearRawInput();
+ secondNumber.clearCountryCodeSource();
+ secondNumber.clearPreferredDomesticCarrierCode();
+ if (firstNumber.hasExtension() &&
+ firstNumber.getExtension().length() == 0) {
+ firstNumber.clearExtension();
+ }
+ if (secondNumber.hasExtension() &&
+ secondNumber.getExtension().length() == 0) {
+ secondNumber.clearExtension();
+ }
+ // Early exit if both had extensions and these are different.
+ if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
+ !firstNumber.getExtension().equals(secondNumber.getExtension())) {
+ return MatchType.NO_MATCH;
+ }
+ int firstNumberCountryCode = firstNumber.getCountryCode();
+ int secondNumberCountryCode = secondNumber.getCountryCode();
+ // Both had country_code specified.
+ if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
+ if (firstNumber.exactlySameAs(secondNumber)) {
+ return MatchType.EXACT_MATCH;
+ } else if (firstNumberCountryCode == secondNumberCountryCode &&
+ isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) {
+ // A SHORT_NSN_MATCH occurs if there is a difference because of the presence or absence of
+ // an 'Italian leading zero', the presence or absence of an extension, or one NSN being a
+ // shorter variant of the other.
+ return MatchType.SHORT_NSN_MATCH;
+ }
+ // This is not a match.
+ return MatchType.NO_MATCH;
+ }
+ // Checks cases where one or both country_code fields were not specified. To make equality
+ // checks easier, we first set the country_code fields to be equal.
+ firstNumber.setCountryCode(secondNumberCountryCode);
+ // If all else was the same, then this is an NSN_MATCH.
+ if (firstNumber.exactlySameAs(secondNumber)) {
+ return MatchType.NSN_MATCH;
+ }
+ if (isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) {
+ return MatchType.SHORT_NSN_MATCH;
+ }
+ return MatchType.NO_MATCH;
+ }
+
+ // Returns true when one national number is the suffix of the other or both are the same.
+ private boolean isNationalNumberSuffixOfTheOther(PhoneNumber firstNumber,
+ PhoneNumber secondNumber) {
+ String firstNumberNationalNumber = String.valueOf(firstNumber.getNationalNumber());
+ String secondNumberNationalNumber = String.valueOf(secondNumber.getNationalNumber());
+ // Note that endsWith returns true if the numbers are equal.
+ return firstNumberNationalNumber.endsWith(secondNumberNationalNumber) ||
+ secondNumberNationalNumber.endsWith(firstNumberNationalNumber);
+ }
+
+ /**
+ * Takes two phone numbers as strings and compares them for equality. This is a convenience
+ * wrapper for {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known.
+ *
+ * @param firstNumber first number to compare. Can contain formatting, and can have country
+ * calling code specified with + at the start.
+ * @param secondNumber second number to compare. Can contain formatting, and can have country
+ * calling code specified with + at the start.
+ * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See
+ * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details.
+ */
+ public MatchType isNumberMatch(String firstNumber, String secondNumber) {
+ try {
+ PhoneNumber firstNumberAsProto = parse(firstNumber, UNKNOWN_REGION);
+ return isNumberMatch(firstNumberAsProto, secondNumber);
+ } catch (NumberParseException e) {
+ if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) {
+ try {
+ PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION);
+ return isNumberMatch(secondNumberAsProto, firstNumber);
+ } catch (NumberParseException e2) {
+ if (e2.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) {
+ try {
+ PhoneNumber firstNumberProto = new PhoneNumber();
+ PhoneNumber secondNumberProto = new PhoneNumber();
+ parseHelper(firstNumber, null, false, false, firstNumberProto);
+ parseHelper(secondNumber, null, false, false, secondNumberProto);
+ return isNumberMatch(firstNumberProto, secondNumberProto);
+ } catch (NumberParseException e3) {
+ // Fall through and return MatchType.NOT_A_NUMBER.
+ }
+ }
+ }
+ }
+ }
+ // One or more of the phone numbers we are trying to match is not a viable phone number.
+ return MatchType.NOT_A_NUMBER;
+ }
+
+ /**
+ * Takes two phone numbers and compares them for equality. This is a convenience wrapper for
+ * {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known.
+ *
+ * @param firstNumber first number to compare in proto buffer format.
+ * @param secondNumber second number to compare. Can contain formatting, and can have country
+ * calling code specified with + at the start.
+ * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See
+ * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details.
+ */
+ public MatchType isNumberMatch(PhoneNumber firstNumber, String secondNumber) {
+ // First see if the second number has an implicit country calling code, by attempting to parse
+ // it.
+ try {
+ PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION);
+ return isNumberMatch(firstNumber, secondNumberAsProto);
+ } catch (NumberParseException e) {
+ if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) {
+ // The second number has no country calling code. EXACT_MATCH is no longer possible.
+ // We parse it as if the region was the same as that for the first number, and if
+ // EXACT_MATCH is returned, we replace this with NSN_MATCH.
+ String firstNumberRegion = getRegionCodeForCountryCode(firstNumber.getCountryCode());
+ try {
+ if (!firstNumberRegion.equals(UNKNOWN_REGION)) {
+ PhoneNumber secondNumberWithFirstNumberRegion = parse(secondNumber, firstNumberRegion);
+ MatchType match = isNumberMatch(firstNumber, secondNumberWithFirstNumberRegion);
+ if (match == MatchType.EXACT_MATCH) {
+ return MatchType.NSN_MATCH;
+ }
+ return match;
+ } else {
+ // If the first number didn't have a valid country calling code, then we parse the
+ // second number without one as well.
+ PhoneNumber secondNumberProto = new PhoneNumber();
+ parseHelper(secondNumber, null, false, false, secondNumberProto);
+ return isNumberMatch(firstNumber, secondNumberProto);
+ }
+ } catch (NumberParseException e2) {
+ // Fall-through to return NOT_A_NUMBER.
+ }
+ }
+ }
+ // One or more of the phone numbers we are trying to match is not a viable phone number.
+ return MatchType.NOT_A_NUMBER;
+ }
+
+ /**
+ * 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. Note that, at the moment, this method does not handle short numbers.
+ * 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 diallable from
+ * outside the region
+ */
+ // @VisibleForTesting
+ boolean canBeInternationallyDialled(PhoneNumber number) {
+ 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;
+ }
+ String nationalSignificantNumber = getNationalSignificantNumber(number);
+ return !isNumberMatchingDesc(nationalSignificantNumber, metadata.getNoInternationalDialling());
+ }
+
+ /**
+ * Returns true if the supplied region supports mobile number portability. Returns false for
+ * invalid, unknown or regions that don't support mobile number portability.
+ *
+ * @param regionCode the region for which we want to know whether it supports mobile number
+ * portability or not.
+ */
+ public boolean isMobileNumberPortableRegion(String regionCode) {
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ if (metadata == null) {
+ logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode);
+ return false;
+ }
+ return metadata.isMobileNumberPortableRegion();
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java b/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java
new file mode 100644
index 00000000..14904c5e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/**
+ * Definition of the class representing metadata for international telephone numbers. This class is
+ * hand created based on the class file compiled from phonemetadata.proto. Please refer to that file
+ * for detailed descriptions of the meaning of each field.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+public final class Phonemetadata {
+ private Phonemetadata() {}
+ public static class NumberFormat implements Externalizable {
+ private static final long serialVersionUID = 1;
+ public NumberFormat() {}
+
+ /**
+ * Provides a dummy builder to 'emulate' the API of the code generated by the latest version of
+ * Protocol Buffers. This lets BuildMetadataFromXml class to build with both this hand created
+ * class and the one generated by the latest version of Protocol Buffers.
+ */
+ public static final class Builder extends NumberFormat {
+ public NumberFormat build() {
+ return this;
+ }
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ // required string pattern = 1;
+ private boolean hasPattern;
+ private String pattern_ = "";
+ public boolean hasPattern() { return hasPattern; }
+ public String getPattern() { return pattern_; }
+ public NumberFormat setPattern(String value) {
+ hasPattern = true;
+ pattern_ = value;
+ return this;
+ }
+
+ // required string format = 2;
+ private boolean hasFormat;
+ private String format_ = "";
+ public boolean hasFormat() { return hasFormat; }
+ public String getFormat() { return format_; }
+ public NumberFormat setFormat(String value) {
+ hasFormat = true;
+ format_ = value;
+ return this;
+ }
+
+ // repeated string leading_digits_pattern = 3;
+ private java.util.List<String> leadingDigitsPattern_ = new java.util.ArrayList<String>();
+ public java.util.List<String> leadingDigitPatterns() {
+ return leadingDigitsPattern_;
+ }
+ public int leadingDigitsPatternSize() { return leadingDigitsPattern_.size(); }
+ public String getLeadingDigitsPattern(int index) {
+ return leadingDigitsPattern_.get(index);
+ }
+ public NumberFormat addLeadingDigitsPattern(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ leadingDigitsPattern_.add(value);
+ return this;
+ }
+
+ // optional string national_prefix_formatting_rule = 4;
+ private boolean hasNationalPrefixFormattingRule;
+ private String nationalPrefixFormattingRule_ = "";
+ public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; }
+ public String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; }
+ public NumberFormat setNationalPrefixFormattingRule(String value) {
+ hasNationalPrefixFormattingRule = true;
+ nationalPrefixFormattingRule_ = value;
+ return this;
+ }
+ public NumberFormat clearNationalPrefixFormattingRule() {
+ hasNationalPrefixFormattingRule = false;
+ nationalPrefixFormattingRule_ = "";
+ return this;
+ }
+
+ // optional bool national_prefix_optional_when_formatting = 6;
+ private boolean hasNationalPrefixOptionalWhenFormatting;
+ private boolean nationalPrefixOptionalWhenFormatting_ = false;
+ public boolean hasNationalPrefixOptionalWhenFormatting() {
+ return hasNationalPrefixOptionalWhenFormatting; }
+ public boolean isNationalPrefixOptionalWhenFormatting() {
+ return nationalPrefixOptionalWhenFormatting_; }
+ public NumberFormat setNationalPrefixOptionalWhenFormatting(boolean value) {
+ hasNationalPrefixOptionalWhenFormatting = true;
+ nationalPrefixOptionalWhenFormatting_ = value;
+ return this;
+ }
+
+ // optional string domestic_carrier_code_formatting_rule = 5;
+ private boolean hasDomesticCarrierCodeFormattingRule;
+ private String domesticCarrierCodeFormattingRule_ = "";
+ public boolean hasDomesticCarrierCodeFormattingRule() {
+ return hasDomesticCarrierCodeFormattingRule; }
+ public String getDomesticCarrierCodeFormattingRule() {
+ return domesticCarrierCodeFormattingRule_; }
+ public NumberFormat setDomesticCarrierCodeFormattingRule(String value) {
+ hasDomesticCarrierCodeFormattingRule = true;
+ domesticCarrierCodeFormattingRule_ = value;
+ return this;
+ }
+
+ public NumberFormat mergeFrom(NumberFormat other) {
+ if (other.hasPattern()) {
+ setPattern(other.getPattern());
+ }
+ if (other.hasFormat()) {
+ setFormat(other.getFormat());
+ }
+ int leadingDigitsPatternSize = other.leadingDigitsPatternSize();
+ for (int i = 0; i < leadingDigitsPatternSize; i++) {
+ addLeadingDigitsPattern(other.getLeadingDigitsPattern(i));
+ }
+ if (other.hasNationalPrefixFormattingRule()) {
+ setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule());
+ }
+ if (other.hasDomesticCarrierCodeFormattingRule()) {
+ setDomesticCarrierCodeFormattingRule(other.getDomesticCarrierCodeFormattingRule());
+ }
+ setNationalPrefixOptionalWhenFormatting(other.isNationalPrefixOptionalWhenFormatting());
+ return this;
+ }
+
+ public void writeExternal(ObjectOutput objectOutput) throws IOException {
+ objectOutput.writeUTF(pattern_);
+ objectOutput.writeUTF(format_);
+ int leadingDigitsPatternSize = leadingDigitsPatternSize();
+ objectOutput.writeInt(leadingDigitsPatternSize);
+ for (int i = 0; i < leadingDigitsPatternSize; i++) {
+ objectOutput.writeUTF(leadingDigitsPattern_.get(i));
+ }
+
+ objectOutput.writeBoolean(hasNationalPrefixFormattingRule);
+ if (hasNationalPrefixFormattingRule) {
+ objectOutput.writeUTF(nationalPrefixFormattingRule_);
+ }
+ objectOutput.writeBoolean(hasDomesticCarrierCodeFormattingRule);
+ if (hasDomesticCarrierCodeFormattingRule) {
+ objectOutput.writeUTF(domesticCarrierCodeFormattingRule_);
+ }
+ objectOutput.writeBoolean(nationalPrefixOptionalWhenFormatting_);
+ }
+
+ public void readExternal(ObjectInput objectInput) throws IOException {
+ setPattern(objectInput.readUTF());
+ setFormat(objectInput.readUTF());
+ int leadingDigitsPatternSize = objectInput.readInt();
+ for (int i = 0; i < leadingDigitsPatternSize; i++) {
+ leadingDigitsPattern_.add(objectInput.readUTF());
+ }
+ if (objectInput.readBoolean()) {
+ setNationalPrefixFormattingRule(objectInput.readUTF());
+ }
+ if (objectInput.readBoolean()) {
+ setDomesticCarrierCodeFormattingRule(objectInput.readUTF());
+ }
+ setNationalPrefixOptionalWhenFormatting(objectInput.readBoolean());
+ }
+ }
+
+ public static class PhoneNumberDesc implements Externalizable {
+ private static final long serialVersionUID = 1;
+ public PhoneNumberDesc() {}
+
+ /**
+ * Provides a dummy builder.
+ *
+ * @see NumberFormat.Builder
+ */
+ public static final class Builder extends PhoneNumberDesc {
+ public PhoneNumberDesc build() {
+ return this;
+ }
+ }
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ // optional string national_number_pattern = 2;
+ private boolean hasNationalNumberPattern;
+ private String nationalNumberPattern_ = "";
+ public boolean hasNationalNumberPattern() { return hasNationalNumberPattern; }
+ public String getNationalNumberPattern() { return nationalNumberPattern_; }
+ public PhoneNumberDesc setNationalNumberPattern(String value) {
+ hasNationalNumberPattern = true;
+ nationalNumberPattern_ = value;
+ return this;
+ }
+
+ // optional string possible_number_pattern = 3;
+ private boolean hasPossibleNumberPattern;
+ private String possibleNumberPattern_ = "";
+ public boolean hasPossibleNumberPattern() { return hasPossibleNumberPattern; }
+ public String getPossibleNumberPattern() { return possibleNumberPattern_; }
+ public PhoneNumberDesc setPossibleNumberPattern(String value) {
+ hasPossibleNumberPattern = true;
+ possibleNumberPattern_ = value;
+ return this;
+ }
+
+ // optional string example_number = 6;
+ private boolean hasExampleNumber;
+ private String exampleNumber_ = "";
+ public boolean hasExampleNumber() { return hasExampleNumber; }
+ public String getExampleNumber() { return exampleNumber_; }
+ public PhoneNumberDesc setExampleNumber(String value) {
+ hasExampleNumber = true;
+ exampleNumber_ = value;
+ return this;
+ }
+
+ public PhoneNumberDesc mergeFrom(PhoneNumberDesc other) {
+ if (other.hasNationalNumberPattern()) {
+ setNationalNumberPattern(other.getNationalNumberPattern());
+ }
+ if (other.hasPossibleNumberPattern()) {
+ setPossibleNumberPattern(other.getPossibleNumberPattern());
+ }
+ if (other.hasExampleNumber()) {
+ setExampleNumber(other.getExampleNumber());
+ }
+ return this;
+ }
+
+ public boolean exactlySameAs(PhoneNumberDesc other) {
+ return nationalNumberPattern_.equals(other.nationalNumberPattern_) &&
+ possibleNumberPattern_.equals(other.possibleNumberPattern_) &&
+ exampleNumber_.equals(other.exampleNumber_);
+ }
+
+ public void writeExternal(ObjectOutput objectOutput) throws IOException {
+ objectOutput.writeBoolean(hasNationalNumberPattern);
+ if (hasNationalNumberPattern) {
+ objectOutput.writeUTF(nationalNumberPattern_);
+ }
+
+ objectOutput.writeBoolean(hasPossibleNumberPattern);
+ if (hasPossibleNumberPattern) {
+ objectOutput.writeUTF(possibleNumberPattern_);
+ }
+
+ objectOutput.writeBoolean(hasExampleNumber);
+ if (hasExampleNumber) {
+ objectOutput.writeUTF(exampleNumber_);
+ }
+ }
+
+ public void readExternal(ObjectInput objectInput) throws IOException {
+ if (objectInput.readBoolean()) {
+ setNationalNumberPattern(objectInput.readUTF());
+ }
+
+ if (objectInput.readBoolean()) {
+ setPossibleNumberPattern(objectInput.readUTF());
+ }
+
+ if (objectInput.readBoolean()) {
+ setExampleNumber(objectInput.readUTF());
+ }
+ }
+ }
+
+ public static class PhoneMetadata implements Externalizable {
+ private static final long serialVersionUID = 1;
+ public PhoneMetadata() {}
+
+ /**
+ * Provides a dummy builder.
+ *
+ * @see NumberFormat.Builder
+ */
+ public static final class Builder extends PhoneMetadata {
+ public PhoneMetadata build() {
+ return this;
+ }
+ }
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ // optional PhoneNumberDesc general_desc = 1;
+ private boolean hasGeneralDesc;
+ private PhoneNumberDesc generalDesc_ = null;
+ public boolean hasGeneralDesc() { return hasGeneralDesc; }
+ public PhoneNumberDesc getGeneralDesc() { return generalDesc_; }
+ public PhoneMetadata setGeneralDesc(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasGeneralDesc = true;
+ generalDesc_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc fixed_line = 2;
+ private boolean hasFixedLine;
+ private PhoneNumberDesc fixedLine_ = null;
+ public boolean hasFixedLine() { return hasFixedLine; }
+ public PhoneNumberDesc getFixedLine() { return fixedLine_; }
+ public PhoneMetadata setFixedLine(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasFixedLine = true;
+ fixedLine_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc mobile = 3;
+ private boolean hasMobile;
+ private PhoneNumberDesc mobile_ = null;
+ public boolean hasMobile() { return hasMobile; }
+ public PhoneNumberDesc getMobile() { return mobile_; }
+ public PhoneMetadata setMobile(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasMobile = true;
+ mobile_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc toll_free = 4;
+ private boolean hasTollFree;
+ private PhoneNumberDesc tollFree_ = null;
+ public boolean hasTollFree() { return hasTollFree; }
+ public PhoneNumberDesc getTollFree() { return tollFree_; }
+ public PhoneMetadata setTollFree(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasTollFree = true;
+ tollFree_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc premium_rate = 5;
+ private boolean hasPremiumRate;
+ private PhoneNumberDesc premiumRate_ = null;
+ public boolean hasPremiumRate() { return hasPremiumRate; }
+ public PhoneNumberDesc getPremiumRate() { return premiumRate_; }
+ public PhoneMetadata setPremiumRate(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasPremiumRate = true;
+ premiumRate_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc shared_cost = 6;
+ private boolean hasSharedCost;
+ private PhoneNumberDesc sharedCost_ = null;
+ public boolean hasSharedCost() { return hasSharedCost; }
+ public PhoneNumberDesc getSharedCost() { return sharedCost_; }
+ public PhoneMetadata setSharedCost(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasSharedCost = true;
+ sharedCost_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc personal_number = 7;
+ private boolean hasPersonalNumber;
+ private PhoneNumberDesc personalNumber_ = null;
+ public boolean hasPersonalNumber() { return hasPersonalNumber; }
+ public PhoneNumberDesc getPersonalNumber() { return personalNumber_; }
+ public PhoneMetadata setPersonalNumber(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasPersonalNumber = true;
+ personalNumber_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc voip = 8;
+ private boolean hasVoip;
+ private PhoneNumberDesc voip_ = null;
+ public boolean hasVoip() { return hasVoip; }
+ public PhoneNumberDesc getVoip() { return voip_; }
+ public PhoneMetadata setVoip(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasVoip = true;
+ voip_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc pager = 21;
+ private boolean hasPager;
+ private PhoneNumberDesc pager_ = null;
+ public boolean hasPager() { return hasPager; }
+ public PhoneNumberDesc getPager() { return pager_; }
+ public PhoneMetadata setPager(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasPager = true;
+ pager_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc uan = 25;
+ private boolean hasUan;
+ private PhoneNumberDesc uan_ = null;
+ public boolean hasUan() { return hasUan; }
+ public PhoneNumberDesc getUan() { return uan_; }
+ public PhoneMetadata setUan(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasUan = true;
+ uan_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc emergency = 27;
+ private boolean hasEmergency;
+ private PhoneNumberDesc emergency_ = null;
+ public boolean hasEmergency() { return hasEmergency; }
+ public PhoneNumberDesc getEmergency() { return emergency_; }
+ public PhoneMetadata setEmergency(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasEmergency = true;
+ emergency_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc voicemail = 28;
+ private boolean hasVoicemail;
+ private PhoneNumberDesc voicemail_ = null;
+ public boolean hasVoicemail() { return hasVoicemail; }
+ public PhoneNumberDesc getVoicemail() { return voicemail_; }
+ public PhoneMetadata setVoicemail(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasVoicemail = true;
+ voicemail_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc short_code = 29;
+ private boolean hasShortCode;
+ private PhoneNumberDesc shortCode_ = null;
+ public boolean hasShortCode() { return hasShortCode; }
+ public PhoneNumberDesc getShortCode() { return shortCode_; }
+ public PhoneMetadata setShortCode(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasShortCode = true;
+ shortCode_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc standard_rate = 30;
+ private boolean hasStandardRate;
+ private PhoneNumberDesc standardRate_ = null;
+ public boolean hasStandardRate() { return hasStandardRate; }
+ public PhoneNumberDesc getStandardRate() { return standardRate_; }
+ public PhoneMetadata setStandardRate(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasStandardRate = true;
+ standardRate_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc carrier_specific = 31;
+ private boolean hasCarrierSpecific;
+ private PhoneNumberDesc carrierSpecific_ = null;
+ public boolean hasCarrierSpecific() { return hasCarrierSpecific; }
+ public PhoneNumberDesc getCarrierSpecific() { return carrierSpecific_; }
+ public PhoneMetadata setCarrierSpecific(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasCarrierSpecific = true;
+ carrierSpecific_ = value;
+ return this;
+ }
+
+ // optional PhoneNumberDesc noInternationalDialling = 24;
+ private boolean hasNoInternationalDialling;
+ private PhoneNumberDesc noInternationalDialling_ = null;
+ public boolean hasNoInternationalDialling() { return hasNoInternationalDialling; }
+ public PhoneNumberDesc getNoInternationalDialling() { return noInternationalDialling_; }
+ public PhoneMetadata setNoInternationalDialling(PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasNoInternationalDialling = true;
+ noInternationalDialling_ = value;
+ return this;
+ }
+
+ // required string id = 9;
+ private boolean hasId;
+ private String id_ = "";
+ public boolean hasId() { return hasId; }
+ public String getId() { return id_; }
+ public PhoneMetadata setId(String value) {
+ hasId = true;
+ id_ = value;
+ return this;
+ }
+
+ // optional int32 country_code = 10;
+ private boolean hasCountryCode;
+ private int countryCode_ = 0;
+ public boolean hasCountryCode() { return hasCountryCode; }
+ public int getCountryCode() { return countryCode_; }
+ public PhoneMetadata setCountryCode(int value) {
+ hasCountryCode = true;
+ countryCode_ = value;
+ return this;
+ }
+
+ // optional string international_prefix = 11;
+ private boolean hasInternationalPrefix;
+ private String internationalPrefix_ = "";
+ public boolean hasInternationalPrefix() { return hasInternationalPrefix; }
+ public String getInternationalPrefix() { return internationalPrefix_; }
+ public PhoneMetadata setInternationalPrefix(String value) {
+ hasInternationalPrefix = true;
+ internationalPrefix_ = value;
+ return this;
+ }
+
+ // optional string preferred_international_prefix = 17;
+ private boolean hasPreferredInternationalPrefix;
+ private String preferredInternationalPrefix_ = "";
+ public boolean hasPreferredInternationalPrefix() { return hasPreferredInternationalPrefix; }
+ public String getPreferredInternationalPrefix() { return preferredInternationalPrefix_; }
+ public PhoneMetadata setPreferredInternationalPrefix(String value) {
+ hasPreferredInternationalPrefix = true;
+ preferredInternationalPrefix_ = value;
+ return this;
+ }
+
+ // optional string national_prefix = 12;
+ private boolean hasNationalPrefix;
+ private String nationalPrefix_ = "";
+ public boolean hasNationalPrefix() { return hasNationalPrefix; }
+ public String getNationalPrefix() { return nationalPrefix_; }
+ public PhoneMetadata setNationalPrefix(String value) {
+ hasNationalPrefix = true;
+ nationalPrefix_ = value;
+ return this;
+ }
+
+ // optional string preferred_extn_prefix = 13;
+ private boolean hasPreferredExtnPrefix;
+ private String preferredExtnPrefix_ = "";
+ public boolean hasPreferredExtnPrefix() { return hasPreferredExtnPrefix; }
+ public String getPreferredExtnPrefix() { return preferredExtnPrefix_; }
+ public PhoneMetadata setPreferredExtnPrefix(String value) {
+ hasPreferredExtnPrefix = true;
+ preferredExtnPrefix_ = value;
+ return this;
+ }
+
+ // optional string national_prefix_for_parsing = 15;
+ private boolean hasNationalPrefixForParsing;
+ private String nationalPrefixForParsing_ = "";
+ public boolean hasNationalPrefixForParsing() { return hasNationalPrefixForParsing; }
+ public String getNationalPrefixForParsing() { return nationalPrefixForParsing_; }
+ public PhoneMetadata setNationalPrefixForParsing(String value) {
+ hasNationalPrefixForParsing = true;
+ nationalPrefixForParsing_ = value;
+ return this;
+ }
+
+ // optional string national_prefix_transform_rule = 16;
+ private boolean hasNationalPrefixTransformRule;
+ private String nationalPrefixTransformRule_ = "";
+ public boolean hasNationalPrefixTransformRule() { return hasNationalPrefixTransformRule; }
+ public String getNationalPrefixTransformRule() { return nationalPrefixTransformRule_; }
+ public PhoneMetadata setNationalPrefixTransformRule(String value) {
+ hasNationalPrefixTransformRule = true;
+ nationalPrefixTransformRule_ = value;
+ return this;
+ }
+
+ // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false];
+ private boolean hasSameMobileAndFixedLinePattern;
+ private boolean sameMobileAndFixedLinePattern_ = false;
+ public boolean hasSameMobileAndFixedLinePattern() { return hasSameMobileAndFixedLinePattern; }
+ public boolean isSameMobileAndFixedLinePattern() { return sameMobileAndFixedLinePattern_; }
+ public PhoneMetadata setSameMobileAndFixedLinePattern(boolean value) {
+ hasSameMobileAndFixedLinePattern = true;
+ sameMobileAndFixedLinePattern_ = value;
+ return this;
+ }
+
+ // repeated NumberFormat number_format = 19;
+ private java.util.List<NumberFormat> numberFormat_ = new java.util.ArrayList<NumberFormat>();
+ public java.util.List<NumberFormat> numberFormats() {
+ return numberFormat_;
+ }
+ public int numberFormatSize() { return numberFormat_.size(); }
+ public NumberFormat getNumberFormat(int index) {
+ return numberFormat_.get(index);
+ }
+ public PhoneMetadata addNumberFormat(NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ numberFormat_.add(value);
+ return this;
+ }
+
+ // repeated NumberFormat intl_number_format = 20;
+ private java.util.List<NumberFormat> intlNumberFormat_ =
+ new java.util.ArrayList<NumberFormat>();
+ public java.util.List<NumberFormat> intlNumberFormats() {
+ return intlNumberFormat_;
+ }
+ public int intlNumberFormatSize() { return intlNumberFormat_.size(); }
+ public NumberFormat getIntlNumberFormat(int index) {
+ return intlNumberFormat_.get(index);
+ }
+
+ public PhoneMetadata addIntlNumberFormat(NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ intlNumberFormat_.add(value);
+ return this;
+ }
+ public PhoneMetadata clearIntlNumberFormat() {
+ intlNumberFormat_.clear();
+ return this;
+ }
+
+ // optional bool main_country_for_code = 22 [default = false];
+ private boolean hasMainCountryForCode;
+ private boolean mainCountryForCode_ = false;
+ public boolean hasMainCountryForCode() { return hasMainCountryForCode; }
+ public boolean isMainCountryForCode() { return mainCountryForCode_; }
+ // Method that lets this class have the same interface as the one generated by Protocol Buffers
+ // which is used by C++ build tools.
+ public boolean getMainCountryForCode() { return mainCountryForCode_; }
+ public PhoneMetadata setMainCountryForCode(boolean value) {
+ hasMainCountryForCode = true;
+ mainCountryForCode_ = value;
+ return this;
+ }
+
+ // optional string leading_digits = 23;
+ private boolean hasLeadingDigits;
+ private String leadingDigits_ = "";
+ public boolean hasLeadingDigits() { return hasLeadingDigits; }
+ public String getLeadingDigits() { return leadingDigits_; }
+ public PhoneMetadata setLeadingDigits(String value) {
+ hasLeadingDigits = true;
+ leadingDigits_ = value;
+ return this;
+ }
+
+ // optional bool leading_zero_possible = 26 [default = false];
+ private boolean hasLeadingZeroPossible;
+ private boolean leadingZeroPossible_ = false;
+ public boolean hasLeadingZeroPossible() { return hasLeadingZeroPossible; }
+ public boolean isLeadingZeroPossible() { return leadingZeroPossible_; }
+ public PhoneMetadata setLeadingZeroPossible(boolean value) {
+ hasLeadingZeroPossible = true;
+ leadingZeroPossible_ = value;
+ return this;
+ }
+
+ // optional bool mobile_number_portable_region = 32 [default = false];
+ private boolean hasMobileNumberPortableRegion;
+ private boolean mobileNumberPortableRegion_ = false;
+ public boolean hasMobileNumberPortableRegion() { return hasMobileNumberPortableRegion; }
+ public boolean isMobileNumberPortableRegion() { return mobileNumberPortableRegion_; }
+ public PhoneMetadata setMobileNumberPortableRegion(boolean value) {
+ hasMobileNumberPortableRegion = true;
+ mobileNumberPortableRegion_ = value;
+ return this;
+ }
+
+ public void writeExternal(ObjectOutput objectOutput) throws IOException {
+ objectOutput.writeBoolean(hasGeneralDesc);
+ if (hasGeneralDesc) {
+ generalDesc_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasFixedLine);
+ if (hasFixedLine) {
+ fixedLine_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasMobile);
+ if (hasMobile) {
+ mobile_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasTollFree);
+ if (hasTollFree) {
+ tollFree_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasPremiumRate);
+ if (hasPremiumRate) {
+ premiumRate_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasSharedCost);
+ if (hasSharedCost) {
+ sharedCost_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasPersonalNumber);
+ if (hasPersonalNumber) {
+ personalNumber_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasVoip);
+ if (hasVoip) {
+ voip_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasPager);
+ if (hasPager) {
+ pager_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasUan);
+ if (hasUan) {
+ uan_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasEmergency);
+ if (hasEmergency) {
+ emergency_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasVoicemail);
+ if (hasVoicemail) {
+ voicemail_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasShortCode);
+ if (hasShortCode) {
+ shortCode_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasStandardRate);
+ if (hasStandardRate) {
+ standardRate_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasCarrierSpecific);
+ if (hasCarrierSpecific) {
+ carrierSpecific_.writeExternal(objectOutput);
+ }
+ objectOutput.writeBoolean(hasNoInternationalDialling);
+ if (hasNoInternationalDialling) {
+ noInternationalDialling_.writeExternal(objectOutput);
+ }
+
+ objectOutput.writeUTF(id_);
+ objectOutput.writeInt(countryCode_);
+ objectOutput.writeUTF(internationalPrefix_);
+
+ objectOutput.writeBoolean(hasPreferredInternationalPrefix);
+ if (hasPreferredInternationalPrefix) {
+ objectOutput.writeUTF(preferredInternationalPrefix_);
+ }
+
+ objectOutput.writeBoolean(hasNationalPrefix);
+ if (hasNationalPrefix) {
+ objectOutput.writeUTF(nationalPrefix_);
+ }
+
+ objectOutput.writeBoolean(hasPreferredExtnPrefix);
+ if (hasPreferredExtnPrefix) {
+ objectOutput.writeUTF(preferredExtnPrefix_);
+ }
+
+ objectOutput.writeBoolean(hasNationalPrefixForParsing);
+ if (hasNationalPrefixForParsing) {
+ objectOutput.writeUTF(nationalPrefixForParsing_);
+ }
+
+ objectOutput.writeBoolean(hasNationalPrefixTransformRule);
+ if (hasNationalPrefixTransformRule) {
+ objectOutput.writeUTF(nationalPrefixTransformRule_);
+ }
+
+ objectOutput.writeBoolean(sameMobileAndFixedLinePattern_);
+
+ int numberFormatSize = numberFormatSize();
+ objectOutput.writeInt(numberFormatSize);
+ for (int i = 0; i < numberFormatSize; i++) {
+ numberFormat_.get(i).writeExternal(objectOutput);
+ }
+
+ int intlNumberFormatSize = intlNumberFormatSize();
+ objectOutput.writeInt(intlNumberFormatSize);
+ for (int i = 0; i < intlNumberFormatSize; i++) {
+ intlNumberFormat_.get(i).writeExternal(objectOutput);
+ }
+
+ objectOutput.writeBoolean(mainCountryForCode_);
+
+ objectOutput.writeBoolean(hasLeadingDigits);
+ if (hasLeadingDigits) {
+ objectOutput.writeUTF(leadingDigits_);
+ }
+
+ objectOutput.writeBoolean(leadingZeroPossible_);
+
+ objectOutput.writeBoolean(mobileNumberPortableRegion_);
+ }
+
+ public void readExternal(ObjectInput objectInput) throws IOException {
+ boolean hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setGeneralDesc(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setFixedLine(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setMobile(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setTollFree(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setPremiumRate(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setSharedCost(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setPersonalNumber(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setVoip(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setPager(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setUan(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setEmergency(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setVoicemail(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setShortCode(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setStandardRate(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setCarrierSpecific(desc);
+ }
+ hasDesc = objectInput.readBoolean();
+ if (hasDesc) {
+ PhoneNumberDesc desc = new PhoneNumberDesc();
+ desc.readExternal(objectInput);
+ setNoInternationalDialling(desc);
+ }
+
+ setId(objectInput.readUTF());
+ setCountryCode(objectInput.readInt());
+ setInternationalPrefix(objectInput.readUTF());
+
+ boolean hasString = objectInput.readBoolean();
+ if (hasString) {
+ setPreferredInternationalPrefix(objectInput.readUTF());
+ }
+
+ hasString = objectInput.readBoolean();
+ if (hasString) {
+ setNationalPrefix(objectInput.readUTF());
+ }
+
+ hasString = objectInput.readBoolean();
+ if (hasString) {
+ setPreferredExtnPrefix(objectInput.readUTF());
+ }
+
+ hasString = objectInput.readBoolean();
+ if (hasString) {
+ setNationalPrefixForParsing(objectInput.readUTF());
+ }
+
+ hasString = objectInput.readBoolean();
+ if (hasString) {
+ setNationalPrefixTransformRule(objectInput.readUTF());
+ }
+
+ setSameMobileAndFixedLinePattern(objectInput.readBoolean());
+
+ int nationalFormatSize = objectInput.readInt();
+ for (int i = 0; i < nationalFormatSize; i++) {
+ NumberFormat numFormat = new NumberFormat();
+ numFormat.readExternal(objectInput);
+ numberFormat_.add(numFormat);
+ }
+
+ int intlNumberFormatSize = objectInput.readInt();
+ for (int i = 0; i < intlNumberFormatSize; i++) {
+ NumberFormat numFormat = new NumberFormat();
+ numFormat.readExternal(objectInput);
+ intlNumberFormat_.add(numFormat);
+ }
+
+ setMainCountryForCode(objectInput.readBoolean());
+
+ hasString = objectInput.readBoolean();
+ if (hasString) {
+ setLeadingDigits(objectInput.readUTF());
+ }
+
+ setLeadingZeroPossible(objectInput.readBoolean());
+
+ setMobileNumberPortableRegion(objectInput.readBoolean());
+ }
+ }
+
+ public static class PhoneMetadataCollection implements Externalizable {
+ private static final long serialVersionUID = 1;
+ public PhoneMetadataCollection() {}
+
+ /**
+ * Provides a dummy builder.
+ *
+ * @see NumberFormat.Builder
+ */
+ public static final class Builder extends PhoneMetadataCollection {
+ public PhoneMetadataCollection build() {
+ return this;
+ }
+ }
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ // repeated PhoneMetadata metadata = 1;
+ private java.util.List<PhoneMetadata> metadata_ = new java.util.ArrayList<PhoneMetadata>();
+
+ public java.util.List<PhoneMetadata> getMetadataList() {
+ return metadata_;
+ }
+ public int getMetadataCount() { return metadata_.size(); }
+
+ public PhoneMetadataCollection addMetadata(PhoneMetadata value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ metadata_.add(value);
+ return this;
+ }
+
+ public void writeExternal(ObjectOutput objectOutput) throws IOException {
+ int size = getMetadataCount();
+ objectOutput.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ metadata_.get(i).writeExternal(objectOutput);
+ }
+ }
+
+ public void readExternal(ObjectInput objectInput) throws IOException {
+ int size = objectInput.readInt();
+ for (int i = 0; i < size; i++) {
+ PhoneMetadata metadata = new PhoneMetadata();
+ metadata.readExternal(objectInput);
+ metadata_.add(metadata);
+ }
+ }
+
+ public PhoneMetadataCollection clear() {
+ metadata_.clear();
+ return this;
+ }
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java b/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java
new file mode 100644
index 00000000..6ac5b83d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/**
+ * Definition of the class representing international telephone numbers. This class is hand-created
+ * based on the class file compiled from phonenumber.proto. Please refer to that file for detailed
+ * descriptions of the meaning of each field.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.io.Serializable;
+
+public final class Phonenumber {
+ private Phonenumber() {}
+ public static class PhoneNumber implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public enum CountryCodeSource {
+ FROM_NUMBER_WITH_PLUS_SIGN,
+ FROM_NUMBER_WITH_IDD,
+ FROM_NUMBER_WITHOUT_PLUS_SIGN,
+ FROM_DEFAULT_COUNTRY
+ }
+
+ public PhoneNumber() {
+ countryCodeSource_ = CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN;
+ }
+
+ // required int32 country_code = 1;
+ private boolean hasCountryCode;
+ private int countryCode_ = 0;
+ public boolean hasCountryCode() { return hasCountryCode; }
+ public int getCountryCode() { return countryCode_; }
+ public PhoneNumber setCountryCode(int value) {
+ hasCountryCode = true;
+ countryCode_ = value;
+ return this;
+ }
+ public PhoneNumber clearCountryCode() {
+ hasCountryCode = false;
+ countryCode_ = 0;
+ return this;
+ }
+
+ // required uint64 national_number = 2;
+ private boolean hasNationalNumber;
+ private long nationalNumber_ = 0L;
+ public boolean hasNationalNumber() { return hasNationalNumber; }
+ public long getNationalNumber() { return nationalNumber_; }
+ public PhoneNumber setNationalNumber(long value) {
+ hasNationalNumber = true;
+ nationalNumber_ = value;
+ return this;
+ }
+ public PhoneNumber clearNationalNumber() {
+ hasNationalNumber = false;
+ nationalNumber_ = 0L;
+ return this;
+ }
+
+ // optional string extension = 3;
+ private boolean hasExtension;
+ private java.lang.String extension_ = "";
+ public boolean hasExtension() { return hasExtension; }
+ public String getExtension() { return extension_; }
+ public PhoneNumber setExtension(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasExtension = true;
+ extension_ = value;
+ return this;
+ }
+ public PhoneNumber clearExtension() {
+ hasExtension = false;
+ extension_ = "";
+ return this;
+ }
+
+ // optional bool italian_leading_zero = 4;
+ private boolean hasItalianLeadingZero;
+ private boolean italianLeadingZero_ = false;
+ public boolean hasItalianLeadingZero() { return hasItalianLeadingZero; }
+ public boolean isItalianLeadingZero() { return italianLeadingZero_; }
+ public PhoneNumber setItalianLeadingZero(boolean value) {
+ hasItalianLeadingZero = true;
+ italianLeadingZero_ = value;
+ return this;
+ }
+ public PhoneNumber clearItalianLeadingZero() {
+ hasItalianLeadingZero = false;
+ italianLeadingZero_ = false;
+ return this;
+ }
+
+ // optional int32 number_of_leading_zeros = 8 [default = 1];
+ private boolean hasNumberOfLeadingZeros;
+ private int numberOfLeadingZeros_ = 1;
+ public boolean hasNumberOfLeadingZeros() { return hasNumberOfLeadingZeros; }
+ public int getNumberOfLeadingZeros() { return numberOfLeadingZeros_; }
+ public PhoneNumber setNumberOfLeadingZeros(int value) {
+ hasNumberOfLeadingZeros = true;
+ numberOfLeadingZeros_ = value;
+ return this;
+ }
+ public PhoneNumber clearNumberOfLeadingZeros() {
+ hasNumberOfLeadingZeros = false;
+ numberOfLeadingZeros_ = 1;
+ return this;
+ }
+
+ // optional string raw_input = 5;
+ private boolean hasRawInput;
+ private String rawInput_ = "";
+ public boolean hasRawInput() { return hasRawInput; }
+ public String getRawInput() { return rawInput_; }
+ public PhoneNumber setRawInput(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasRawInput = true;
+ rawInput_ = value;
+ return this;
+ }
+ public PhoneNumber clearRawInput() {
+ hasRawInput = false;
+ rawInput_ = "";
+ return this;
+ }
+
+ // optional CountryCodeSource country_code_source = 6;
+ private boolean hasCountryCodeSource;
+ private CountryCodeSource countryCodeSource_;
+ public boolean hasCountryCodeSource() { return hasCountryCodeSource; }
+ public CountryCodeSource getCountryCodeSource() { return countryCodeSource_; }
+ public PhoneNumber setCountryCodeSource(CountryCodeSource value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasCountryCodeSource = true;
+ countryCodeSource_ = value;
+ return this;
+ }
+ public PhoneNumber clearCountryCodeSource() {
+ hasCountryCodeSource = false;
+ countryCodeSource_ = CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN;
+ return this;
+ }
+
+ // optional string preferred_domestic_carrier_code = 7;
+ private boolean hasPreferredDomesticCarrierCode;
+ private java.lang.String preferredDomesticCarrierCode_ = "";
+ public boolean hasPreferredDomesticCarrierCode() { return hasPreferredDomesticCarrierCode; }
+ public String getPreferredDomesticCarrierCode() { return preferredDomesticCarrierCode_; }
+ public PhoneNumber setPreferredDomesticCarrierCode(String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ hasPreferredDomesticCarrierCode = true;
+ preferredDomesticCarrierCode_ = value;
+ return this;
+ }
+ public PhoneNumber clearPreferredDomesticCarrierCode() {
+ hasPreferredDomesticCarrierCode = false;
+ preferredDomesticCarrierCode_ = "";
+ return this;
+ }
+
+ public final PhoneNumber clear() {
+ clearCountryCode();
+ clearNationalNumber();
+ clearExtension();
+ clearItalianLeadingZero();
+ clearNumberOfLeadingZeros();
+ clearRawInput();
+ clearCountryCodeSource();
+ clearPreferredDomesticCarrierCode();
+ return this;
+ }
+
+ public PhoneNumber mergeFrom(PhoneNumber other) {
+ if (other.hasCountryCode()) {
+ setCountryCode(other.getCountryCode());
+ }
+ if (other.hasNationalNumber()) {
+ setNationalNumber(other.getNationalNumber());
+ }
+ if (other.hasExtension()) {
+ setExtension(other.getExtension());
+ }
+ if (other.hasItalianLeadingZero()) {
+ setItalianLeadingZero(other.isItalianLeadingZero());
+ }
+ if (other.hasNumberOfLeadingZeros()) {
+ setNumberOfLeadingZeros(other.getNumberOfLeadingZeros());
+ }
+ if (other.hasRawInput()) {
+ setRawInput(other.getRawInput());
+ }
+ if (other.hasCountryCodeSource()) {
+ setCountryCodeSource(other.getCountryCodeSource());
+ }
+ if (other.hasPreferredDomesticCarrierCode()) {
+ setPreferredDomesticCarrierCode(other.getPreferredDomesticCarrierCode());
+ }
+ return this;
+ }
+
+ public boolean exactlySameAs(PhoneNumber other) {
+ if (other == null) {
+ return false;
+ }
+ if (this == other) {
+ return true;
+ }
+ return (countryCode_ == other.countryCode_ && nationalNumber_ == other.nationalNumber_ &&
+ extension_.equals(other.extension_) && italianLeadingZero_ == other.italianLeadingZero_ &&
+ numberOfLeadingZeros_ == other.numberOfLeadingZeros_ &&
+ rawInput_.equals(other.rawInput_) && countryCodeSource_ == other.countryCodeSource_ &&
+ preferredDomesticCarrierCode_.equals(other.preferredDomesticCarrierCode_) &&
+ hasPreferredDomesticCarrierCode() == other.hasPreferredDomesticCarrierCode());
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ return (that instanceof PhoneNumber) && exactlySameAs((PhoneNumber) that);
+ }
+
+ @Override
+ public int hashCode() {
+ // Simplified rendition of the hashCode function automatically generated from the proto
+ // compiler with java_generate_equals_and_hash set to true. We are happy with unset values to
+ // be considered equal to their explicitly-set equivalents, so don't check if any value is
+ // unknown. The only exception to this is the preferred domestic carrier code.
+ int hash = 41;
+ hash = (53 * hash) + getCountryCode();
+ hash = (53 * hash) + Long.valueOf(getNationalNumber()).hashCode();
+ hash = (53 * hash) + getExtension().hashCode();
+ hash = (53 * hash) + (isItalianLeadingZero() ? 1231 : 1237);
+ hash = (53 * hash) + getNumberOfLeadingZeros();
+ hash = (53 * hash) + getRawInput().hashCode();
+ hash = (53 * hash) + getCountryCodeSource().hashCode();
+ hash = (53 * hash) + getPreferredDomesticCarrierCode().hashCode();
+ hash = (53 * hash) + (hasPreferredDomesticCarrierCode() ? 1231 : 1237);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder outputString = new StringBuilder();
+ outputString.append("Country Code: ").append(countryCode_);
+ outputString.append(" National Number: ").append(nationalNumber_);
+ if (hasItalianLeadingZero() && isItalianLeadingZero()) {
+ outputString.append(" Leading Zero(s): true");
+ }
+ if (hasNumberOfLeadingZeros()) {
+ outputString.append(" Number of leading zeros: ").append(numberOfLeadingZeros_);
+ }
+ if (hasExtension()) {
+ outputString.append(" Extension: ").append(extension_);
+ }
+ if (hasCountryCodeSource()) {
+ outputString.append(" Country Code Source: ").append(countryCodeSource_);
+ }
+ if (hasPreferredDomesticCarrierCode()) {
+ outputString.append(" Preferred Domestic Carrier Code: ").
+ append(preferredDomesticCarrierCode_);
+ }
+ return outputString.toString();
+ }
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java b/libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java
new file mode 100644
index 00000000..a9ff7e02
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * LRU Cache for compiled regular expressions used by the libphonenumbers libary.
+ *
+ * @author Shaopeng Jia
+ */
+public class RegexCache {
+ private LRUCache<String, Pattern> cache;
+
+ public RegexCache(int size) {
+ cache = new LRUCache<String, Pattern>(size);
+ }
+
+ public Pattern getPatternForRegex(String regex) {
+ Pattern pattern = cache.get(regex);
+ if (pattern == null) {
+ pattern = Pattern.compile(regex);
+ cache.put(regex, pattern);
+ }
+ return pattern;
+ }
+
+ // This method is used for testing.
+ boolean containsRegex(String regex) {
+ return cache.containsKey(regex);
+ }
+
+ private static class LRUCache<K, V> {
+ // LinkedHashMap offers a straightforward implementation of LRU cache.
+ private LinkedHashMap<K, V> map;
+ private int size;
+
+ @SuppressWarnings("serial")
+ public LRUCache(int size) {
+ this.size = size;
+ map = new LinkedHashMap<K, V>(size * 4 / 3 + 1, 0.75f, true) {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+ return size() > LRUCache.this.size;
+ }
+ };
+ }
+
+ public synchronized V get(K key) {
+ return map.get(key);
+ }
+
+ public synchronized void put(K key, V value) {
+ map.put(key, value);
+ }
+
+ public synchronized boolean containsKey(K key) {
+ return map.containsKey(key);
+ }
+ }
+}
+
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java
new file mode 100644
index 00000000..401d260d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright (C) 2013 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;
+
+import com.google.i18n.phonenumbers.internal.MatcherApi;
+import com.google.i18n.phonenumbers.internal.RegexBasedMatcher;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * Methods for getting information about short phone numbers, such as short codes and emergency
+ * numbers. Note that most commercial short numbers are not handled here, but by the
+ * {@link PhoneNumberUtil}.
+ *
+ * @author Shaopeng Jia
+ * @author David Yonge-Mallo
+ */
+public class ShortNumberInfo {
+ private static final Logger logger = Logger.getLogger(ShortNumberInfo.class.getName());
+
+ private static final ShortNumberInfo INSTANCE =
+ new ShortNumberInfo(RegexBasedMatcher.create());
+
+ // In these countries, if extra digits are added to an emergency number, it no longer connects
+ // to the emergency service.
+ private static final Set<String> REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT =
+ new HashSet<String>();
+ static {
+ REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("BR");
+ REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("CL");
+ REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("NI");
+ }
+
+ /** Cost categories of short numbers. */
+ public enum ShortNumberCost {
+ TOLL_FREE,
+ STANDARD_RATE,
+ PREMIUM_RATE,
+ UNKNOWN_COST
+ }
+
+ /** Returns the singleton instance of the ShortNumberInfo. */
+ public static ShortNumberInfo getInstance() {
+ return INSTANCE;
+ }
+
+ // MatcherApi supports the basic matching method for checking if a given national number matches
+ // a national number patten or a possible number patten defined in the given
+ // {@code PhoneNumberDesc}.
+ private final MatcherApi matcherApi;
+
+ // A mapping from a country calling code to the region codes which denote the region represented
+ // by that country calling code. In the case of multiple regions sharing a calling code, such as
+ // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be
+ // first.
+ private final Map<Integer, List<String>> countryCallingCodeToRegionCodeMap;
+
+ // @VisibleForTesting
+ ShortNumberInfo(MatcherApi matcherApi) {
+ this.matcherApi = matcherApi;
+ // TODO: Create ShortNumberInfo for a given map
+ this.countryCallingCodeToRegionCodeMap =
+ CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap();
+ }
+
+ /**
+ * 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.
+ */
+ private List<String> getRegionCodesForCountryCode(int countryCallingCode) {
+ List<String> regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode);
+ return Collections.unmodifiableList(regionCodes == null ? new ArrayList<String>(0)
+ : regionCodes);
+ }
+
+ /**
+ * Check whether a short number is a possible number when dialled from a region, given the number
+ * in the form of a string, and the region where the number is dialed from. This provides a more
+ * lenient check than {@link #isValidShortNumberForRegion}.
+ *
+ * @param shortNumber the short number to check as a string
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return whether the number is a possible short number
+ * @deprecated Anyone who was using it and passing in a string with whitespace (or other
+ * formatting characters) would have been getting the wrong result. You should parse
+ * the string to PhoneNumber and use the method
+ * {@code #isPossibleShortNumberForRegion(PhoneNumber, String)}. This method will be
+ * removed in the next release.
+ */
+ @Deprecated
+ public boolean isPossibleShortNumberForRegion(String shortNumber, String regionDialingFrom) {
+ PhoneMetadata phoneMetadata =
+ MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
+ if (phoneMetadata == null) {
+ return false;
+ }
+ return matcherApi.matchesPossibleNumber(shortNumber, phoneMetadata.getGeneralDesc());
+ }
+
+ /**
+ * Check whether a short number is a possible number when dialed from the given region. This
+ * provides a more lenient check than {@link #isValidShortNumberForRegion}.
+ *
+ * @param number the short number to check
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return whether the number is a possible short number
+ */
+ public boolean isPossibleShortNumberForRegion(PhoneNumber number, String regionDialingFrom) {
+ PhoneMetadata phoneMetadata =
+ MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
+ if (phoneMetadata == null) {
+ return false;
+ }
+ return matcherApi.matchesPossibleNumber(getNationalSignificantNumber(number),
+ phoneMetadata.getGeneralDesc());
+ }
+
+ /**
+ * Check whether a short number is a possible number. If a country calling code is shared by
+ * multiple regions, this returns true if it's possible in any of them. This provides a more
+ * lenient check than {@link #isValidShortNumber}. See {@link
+ * #isPossibleShortNumberForRegion(PhoneNumber, String)} for details.
+ *
+ * @param number the short number to check
+ * @return whether the number is a possible short number
+ */
+ public boolean isPossibleShortNumber(PhoneNumber number) {
+ List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
+ String shortNumber = getNationalSignificantNumber(number);
+ for (String region : regionCodes) {
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(region);
+ if (matcherApi.matchesPossibleNumber(shortNumber, phoneMetadata.getGeneralDesc())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify
+ * the number is actually in use, which is impossible to tell by just looking at the number
+ * itself.
+ *
+ * @param shortNumber the short number to check as a string
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return whether the short number matches a valid pattern
+ * @deprecated Anyone who was using it and passing in a string with whitespace (or other
+ * formatting characters) would have been getting the wrong result. You should parse
+ * the string to PhoneNumber and use the method
+ * {@code #isValidShortNumberForRegion(PhoneNumber, String)}. This method will be
+ * removed in the next release.
+ */
+ @Deprecated
+ public boolean isValidShortNumberForRegion(String shortNumber, String regionDialingFrom) {
+ PhoneMetadata phoneMetadata =
+ MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
+ if (phoneMetadata == null) {
+ return false;
+ }
+ PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc();
+ if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) {
+ return false;
+ }
+ PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode();
+ return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc);
+ }
+
+ /**
+ * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify
+ * the number is actually in use, which is impossible to tell by just looking at the number
+ * itself.
+ *
+ * @param number the short number for which we want to test the validity
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return whether the short number matches a valid pattern
+ */
+ public boolean isValidShortNumberForRegion(PhoneNumber number, String regionDialingFrom) {
+ PhoneMetadata phoneMetadata =
+ MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom);
+ if (phoneMetadata == null) {
+ return false;
+ }
+ String shortNumber = getNationalSignificantNumber(number);
+ PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc();
+ if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) {
+ return false;
+ }
+ PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode();
+ return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc);
+ }
+
+ /**
+ * Tests whether a short number matches a valid pattern. If a country calling code is shared by
+ * multiple regions, this returns true if it's valid in any of them. Note that this doesn't verify
+ * the number is actually in use, which is impossible to tell by just looking at the number
+ * itself. See {@link #isValidShortNumberForRegion(PhoneNumber, String)} for details.
+ *
+ * @param number the short number for which we want to test the validity
+ * @return whether the short number matches a valid pattern
+ */
+ public boolean isValidShortNumber(PhoneNumber number) {
+ List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
+ String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes);
+ if (regionCodes.size() > 1 && regionCode != null) {
+ // If a matching region had been found for the phone number from among two or more regions,
+ // then we have already implicitly verified its validity for that region.
+ return true;
+ }
+ return isValidShortNumberForRegion(number, regionCode);
+ }
+
+ /**
+ * Gets the expected cost category of a short number when dialled from a region (however, nothing
+ * is implied about its validity). If it is important that the number is valid, then its validity
+ * must first be checked using {@link isValidShortNumberForRegion}. Note that emergency numbers
+ * are always considered toll-free. Example usage:
+ * <pre>{@code
+ * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
+ * String shortNumber = "110";
+ * String regionCode = "FR";
+ * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
+ * ShortNumberInfo.ShortNumberCost cost = shortInfo.getExpectedCostForRegion(shortNumber,
+ * regionCode);
+ * // Do something with the cost information here.
+ * }}</pre>
+ *
+ * @param shortNumber the short number for which we want to know the expected cost category,
+ * as a string
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if
+ * the number does not match a cost category. Note that an invalid number may match any cost
+ * category.
+ * @deprecated Anyone who was using it and passing in a string with whitespace (or other
+ * formatting characters) would have been getting the wrong result. You should parse
+ * the string to PhoneNumber and use the method
+ * {@code #getExpectedCostForRegion(PhoneNumber, String)}. This method will be
+ * removed in the next release.
+ */
+ @Deprecated
+ public ShortNumberCost getExpectedCostForRegion(String shortNumber, String regionDialingFrom) {
+ // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null.
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(
+ regionDialingFrom);
+ if (phoneMetadata == null) {
+ return ShortNumberCost.UNKNOWN_COST;
+ }
+
+ // The cost categories are tested in order of decreasing expense, since if for some reason the
+ // patterns overlap the most expensive matching cost category should be returned.
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) {
+ return ShortNumberCost.PREMIUM_RATE;
+ }
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) {
+ return ShortNumberCost.STANDARD_RATE;
+ }
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) {
+ return ShortNumberCost.TOLL_FREE;
+ }
+ if (isEmergencyNumber(shortNumber, regionDialingFrom)) {
+ // Emergency numbers are implicitly toll-free.
+ return ShortNumberCost.TOLL_FREE;
+ }
+ return ShortNumberCost.UNKNOWN_COST;
+ }
+
+ /**
+ * Gets the expected cost category of a short number when dialed from a region (however, nothing
+ * is implied about its validity). If it is important that the number is valid, then its validity
+ * must first be checked using {@link #isValidShortNumberForRegion}. Note that emergency numbers
+ * are always considered toll-free. Example usage:
+ * <pre>{@code
+ * // The region for which the number was parsed and the region we subsequently check against
+ * // need not be the same. Here we parse the number in the US and check it for Canada.
+ * PhoneNumber number = phoneUtil.parse("110", "US");
+ * ...
+ * String regionCode = "CA";
+ * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
+ * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
+ * ShortNumberCost cost = shortInfo.getExpectedCostForRegion(number, regionCode);
+ * // Do something with the cost information here.
+ * }}</pre>
+ *
+ * @param number the short number for which we want to know the expected cost category
+ * @param regionDialingFrom the region from which the number is dialed
+ * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if
+ * the number does not match a cost category. Note that an invalid number may match any cost
+ * category.
+ */
+ public ShortNumberCost getExpectedCostForRegion(PhoneNumber number, String regionDialingFrom) {
+ // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null.
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(
+ regionDialingFrom);
+ if (phoneMetadata == null) {
+ return ShortNumberCost.UNKNOWN_COST;
+ }
+
+ String shortNumber = getNationalSignificantNumber(number);
+
+ // The cost categories are tested in order of decreasing expense, since if for some reason the
+ // patterns overlap the most expensive matching cost category should be returned.
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) {
+ return ShortNumberCost.PREMIUM_RATE;
+ }
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) {
+ return ShortNumberCost.STANDARD_RATE;
+ }
+ if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) {
+ return ShortNumberCost.TOLL_FREE;
+ }
+ if (isEmergencyNumber(shortNumber, regionDialingFrom)) {
+ // Emergency numbers are implicitly toll-free.
+ return ShortNumberCost.TOLL_FREE;
+ }
+ return ShortNumberCost.UNKNOWN_COST;
+ }
+
+ /**
+ * Gets the expected cost category of a short number (however, nothing is implied about its
+ * validity). If the country calling code is unique to a region, this method behaves exactly the
+ * same as {@link #getExpectedCostForRegion(PhoneNumber, String)}. However, if the country
+ * calling code is shared by multiple regions, then it returns the highest cost in the sequence
+ * PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of
+ * UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE
+ * or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it
+ * might be a PREMIUM_RATE number.
+ * <p>
+ * For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected
+ * cost returned by this method will be STANDARD_RATE, since the NANPA countries share the same
+ * country calling code.
+ * <p>
+ * Note: If the region from which the number is dialed is known, it is highly preferable to call
+ * {@link #getExpectedCostForRegion(PhoneNumber, String)} instead.
+ *
+ * @param number the short number for which we want to know the expected cost category
+ * @return the highest expected cost category of the short number in the region(s) with the given
+ * country calling code
+ */
+ public ShortNumberCost getExpectedCost(PhoneNumber number) {
+ List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
+ if (regionCodes.size() == 0) {
+ return ShortNumberCost.UNKNOWN_COST;
+ }
+ if (regionCodes.size() == 1) {
+ return getExpectedCostForRegion(number, regionCodes.get(0));
+ }
+ ShortNumberCost cost = ShortNumberCost.TOLL_FREE;
+ for (String regionCode : regionCodes) {
+ ShortNumberCost costForRegion = getExpectedCostForRegion(number, regionCode);
+ switch (costForRegion) {
+ case PREMIUM_RATE:
+ return ShortNumberCost.PREMIUM_RATE;
+ case UNKNOWN_COST:
+ cost = ShortNumberCost.UNKNOWN_COST;
+ break;
+ case STANDARD_RATE:
+ if (cost != ShortNumberCost.UNKNOWN_COST) {
+ cost = ShortNumberCost.STANDARD_RATE;
+ }
+ break;
+ case TOLL_FREE:
+ // Do nothing.
+ break;
+ default:
+ logger.log(Level.SEVERE, "Unrecognised cost for region: " + costForRegion);
+ }
+ }
+ return cost;
+ }
+
+ // Helper method to get the region code for a given phone number, from a list of possible region
+ // codes. If the list contains more than one region, the first region for which the number is
+ // valid is returned.
+ private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number,
+ List<String> regionCodes) {
+ if (regionCodes.size() == 0) {
+ return null;
+ } else if (regionCodes.size() == 1) {
+ return regionCodes.get(0);
+ }
+ String nationalNumber = getNationalSignificantNumber(number);
+ for (String regionCode : regionCodes) {
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
+ if (phoneMetadata != null
+ && matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getShortCode())) {
+ // The number is valid for this region.
+ return regionCode;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Convenience method to get a list of what regions the library has metadata for.
+ */
+ Set<String> getSupportedRegions() {
+ return Collections.unmodifiableSet(MetadataManager.getShortNumberMetadataSupportedRegions());
+ }
+
+ /**
+ * Gets a valid short number for the specified region.
+ *
+ * @param regionCode the region for which an example short number is needed
+ * @return a valid short number for the specified region. Returns an empty string when the
+ * metadata does not contain such information.
+ */
+ // @VisibleForTesting
+ String getExampleShortNumber(String regionCode) {
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
+ if (phoneMetadata == null) {
+ return "";
+ }
+ PhoneNumberDesc desc = phoneMetadata.getShortCode();
+ if (desc.hasExampleNumber()) {
+ return desc.getExampleNumber();
+ }
+ return "";
+ }
+
+ /**
+ * Gets a valid short number for the specified cost category.
+ *
+ * @param regionCode the region for which an example short number is needed
+ * @param cost the cost category of number that is needed
+ * @return a valid short number for the specified region and cost category. Returns an empty
+ * string when the metadata does not contain such information, or the cost is UNKNOWN_COST.
+ */
+ // @VisibleForTesting
+ String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) {
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
+ if (phoneMetadata == null) {
+ return "";
+ }
+ PhoneNumberDesc desc = null;
+ switch (cost) {
+ case TOLL_FREE:
+ desc = phoneMetadata.getTollFree();
+ break;
+ case STANDARD_RATE:
+ desc = phoneMetadata.getStandardRate();
+ break;
+ case PREMIUM_RATE:
+ desc = phoneMetadata.getPremiumRate();
+ break;
+ default:
+ // UNKNOWN_COST numbers are computed by the process of elimination from the other cost
+ // categories.
+ }
+ if (desc != null && desc.hasExampleNumber()) {
+ return desc.getExampleNumber();
+ }
+ return "";
+ }
+
+ /**
+ * Returns true if the given number, exactly as dialed, might be used to connect to an emergency
+ * service in the given region.
+ * <p>
+ * This method accepts a string, rather than a PhoneNumber, because it needs to distinguish
+ * cases such as "+1 911" and "911", where the former may not connect to an emergency service in
+ * all cases but the latter would. This method takes into account cases where the number might
+ * contain formatting, or might have additional digits appended (when it is okay to do that in
+ * the specified region).
+ *
+ * @param number the phone number to test
+ * @param regionCode the region where the phone number is being dialed
+ * @return whether the number might be used to connect to an emergency service in the given region
+ */
+ public boolean connectsToEmergencyNumber(String number, String regionCode) {
+ return matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */);
+ }
+
+ /**
+ * Returns true if the given number exactly matches an emergency service number in the given
+ * region.
+ * <p>
+ * This method takes into account cases where the number might contain formatting, but doesn't
+ * allow additional digits to be appended. Note that {@code isEmergencyNumber(number, region)}
+ * implies {@code connectsToEmergencyNumber(number, region)}.
+ *
+ * @param number the phone number to test
+ * @param regionCode the region where the phone number is being dialed
+ * @return whether the number exactly matches an emergency services number in the given region
+ */
+ public boolean isEmergencyNumber(String number, String regionCode) {
+ return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */);
+ }
+
+ private boolean matchesEmergencyNumberHelper(String number, String regionCode,
+ boolean allowPrefixMatch) {
+ number = PhoneNumberUtil.extractPossibleNumber(number);
+ if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(number).lookingAt()) {
+ // Returns false if the number starts with a plus sign. We don't believe dialing the country
+ // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can
+ // add additional logic here to handle it.
+ return false;
+ }
+ PhoneMetadata metadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
+ if (metadata == null || !metadata.hasEmergency()) {
+ return false;
+ }
+
+ String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number);
+ PhoneNumberDesc emergencyDesc = metadata.getEmergency();
+ boolean allowPrefixMatchForRegion =
+ allowPrefixMatch && !REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.contains(regionCode);
+ return matcherApi.matchesNationalNumber(normalizedNumber, emergencyDesc,
+ allowPrefixMatchForRegion);
+ }
+
+ /**
+ * Given a valid short number, determines whether it is carrier-specific (however, nothing is
+ * implied about its validity). If it is important that the number is valid, then its validity
+ * must first be checked using {@link #isValidShortNumber} or
+ * {@link #isValidShortNumberForRegion}.
+ *
+ * @param number the valid short number to check
+ * @return whether the short number is carrier-specific (assuming the input was a valid short
+ * number).
+ */
+ public boolean isCarrierSpecific(PhoneNumber number) {
+ List<String> regionCodes = getRegionCodesForCountryCode(number.getCountryCode());
+ String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes);
+ String nationalNumber = getNationalSignificantNumber(number);
+ PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode);
+ return (phoneMetadata != null)
+ && (matchesPossibleNumberAndNationalNumber(nationalNumber,
+ phoneMetadata.getCarrierSpecific()));
+ }
+
+ /**
+ * Gets the national significant number of the a phone number. Note a national significant number
+ * doesn't contain a national prefix or any formatting.
+ * <p>
+ * This is a temporary duplicate of the {@code getNationalSignificantNumber} method from
+ * {@code PhoneNumberUtil}. Ultimately a canonical static version should exist in a separate
+ * utility class (to prevent {@code ShortNumberInfo} needing to depend on PhoneNumberUtil).
+ *
+ * @param number the phone number for which the national significant number is needed
+ * @return the national significant number of the PhoneNumber object passed in
+ */
+ private static String getNationalSignificantNumber(PhoneNumber number) {
+ // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix.
+ StringBuilder nationalNumber = new StringBuilder();
+ if (number.isItalianLeadingZero()) {
+ char[] zeros = new char[number.getNumberOfLeadingZeros()];
+ Arrays.fill(zeros, '0');
+ nationalNumber.append(new String(zeros));
+ }
+ nationalNumber.append(number.getNationalNumber());
+ return nationalNumber.toString();
+ }
+
+ // TODO: Once we have benchmarked ShortNumberInfo, consider if it is worth keeping
+ // this performance optimization, and if so move this into the matcher implementation.
+ private boolean matchesPossibleNumberAndNationalNumber(String number,
+ PhoneNumberDesc numberDesc) {
+ return matcherApi.matchesPossibleNumber(number, numberDesc)
+ && matcherApi.matchesNationalNumber(number, numberDesc, false);
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java
new file mode 100644
index 00000000..5ea1a91f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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;
+
+import java.util.Set;
+
+/*
+ * Utility for international short phone numbers, such as short codes and emergency numbers. Note
+ * most commercial short numbers are not handled here, but by the PhoneNumberUtil.
+ *
+ * @deprecated("As of release 5.8, replaced by ShortNumberInfo.")
+ *
+ * @author Shaopeng Jia
+ * @author David Yonge-Mallo
+ */
+@Deprecated public class ShortNumberUtil {
+
+ /**
+ * Cost categories of short numbers.
+ */
+ public enum ShortNumberCost {
+ TOLL_FREE,
+ STANDARD_RATE,
+ PREMIUM_RATE,
+ UNKNOWN_COST
+ }
+
+ public ShortNumberUtil() {
+ }
+
+ /**
+ * Convenience method to get a list of what regions the library has metadata for.
+ */
+ public Set<String> getSupportedRegions() {
+ return ShortNumberInfo.getInstance().getSupportedRegions();
+ }
+
+ /**
+ * Returns true if the number might be used to connect to an emergency service in the given
+ * region.
+ *
+ * This method takes into account cases where the number might contain formatting, or might have
+ * additional digits appended (when it is okay to do that in the region specified).
+ *
+ * @param number the phone number to test
+ * @param regionCode the region where the phone number is being dialed
+ * @return if the number might be used to connect to an emergency service in the given region.
+ */
+ public boolean connectsToEmergencyNumber(String number, String regionCode) {
+ return ShortNumberInfo.getInstance().connectsToEmergencyNumber(number, regionCode);
+ }
+
+ /**
+ * Returns true if the number exactly matches an emergency service number in the given region.
+ *
+ * This method takes into account cases where the number might contain formatting, but doesn't
+ * allow additional digits to be appended.
+ *
+ * @param number the phone number to test
+ * @param regionCode the region where the phone number is being dialed
+ * @return if the number exactly matches an emergency services number in the given region.
+ */
+ public boolean isEmergencyNumber(String number, String regionCode) {
+ return ShortNumberInfo.getInstance().isEmergencyNumber(number, regionCode);
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java
new file mode 100644
index 00000000..9f3a9273
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/* This file is automatically generated by {@link BuildMetadataProtoFromXml}.
+ * Please don't modify it directly.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class ShortNumbersRegionCodeSet {
+ // A set of all region codes for which data is available.
+ static Set<String> getRegionCodeSet() {
+ // The capacity is set to 309 as there are 232 different entries,
+ // and this offers a load factor of roughly 0.75.
+ Set<String> regionCodeSet = new HashSet<String>(309);
+
+ regionCodeSet.add("AC");
+ regionCodeSet.add("AD");
+ regionCodeSet.add("AE");
+ regionCodeSet.add("AF");
+ regionCodeSet.add("AG");
+ regionCodeSet.add("AI");
+ regionCodeSet.add("AL");
+ regionCodeSet.add("AM");
+ regionCodeSet.add("AO");
+ regionCodeSet.add("AR");
+ regionCodeSet.add("AS");
+ regionCodeSet.add("AT");
+ regionCodeSet.add("AU");
+ regionCodeSet.add("AW");
+ regionCodeSet.add("AX");
+ regionCodeSet.add("AZ");
+ regionCodeSet.add("BA");
+ regionCodeSet.add("BB");
+ regionCodeSet.add("BD");
+ regionCodeSet.add("BE");
+ regionCodeSet.add("BF");
+ regionCodeSet.add("BG");
+ regionCodeSet.add("BH");
+ regionCodeSet.add("BI");
+ regionCodeSet.add("BJ");
+ regionCodeSet.add("BL");
+ regionCodeSet.add("BM");
+ regionCodeSet.add("BN");
+ regionCodeSet.add("BO");
+ regionCodeSet.add("BQ");
+ regionCodeSet.add("BR");
+ regionCodeSet.add("BS");
+ regionCodeSet.add("BT");
+ regionCodeSet.add("BW");
+ regionCodeSet.add("BY");
+ regionCodeSet.add("BZ");
+ regionCodeSet.add("CA");
+ regionCodeSet.add("CC");
+ regionCodeSet.add("CD");
+ regionCodeSet.add("CH");
+ regionCodeSet.add("CI");
+ regionCodeSet.add("CK");
+ regionCodeSet.add("CL");
+ regionCodeSet.add("CM");
+ regionCodeSet.add("CN");
+ regionCodeSet.add("CO");
+ regionCodeSet.add("CR");
+ regionCodeSet.add("CU");
+ regionCodeSet.add("CV");
+ regionCodeSet.add("CW");
+ regionCodeSet.add("CX");
+ regionCodeSet.add("CY");
+ regionCodeSet.add("CZ");
+ regionCodeSet.add("DE");
+ regionCodeSet.add("DJ");
+ regionCodeSet.add("DK");
+ regionCodeSet.add("DM");
+ regionCodeSet.add("DO");
+ regionCodeSet.add("DZ");
+ regionCodeSet.add("EC");
+ regionCodeSet.add("EE");
+ regionCodeSet.add("EG");
+ regionCodeSet.add("EH");
+ regionCodeSet.add("ES");
+ regionCodeSet.add("ET");
+ regionCodeSet.add("FI");
+ regionCodeSet.add("FJ");
+ regionCodeSet.add("FK");
+ regionCodeSet.add("FM");
+ regionCodeSet.add("FO");
+ regionCodeSet.add("FR");
+ regionCodeSet.add("GA");
+ regionCodeSet.add("GB");
+ regionCodeSet.add("GD");
+ regionCodeSet.add("GE");
+ regionCodeSet.add("GF");
+ regionCodeSet.add("GG");
+ regionCodeSet.add("GH");
+ regionCodeSet.add("GI");
+ regionCodeSet.add("GL");
+ regionCodeSet.add("GM");
+ regionCodeSet.add("GN");
+ regionCodeSet.add("GP");
+ regionCodeSet.add("GR");
+ regionCodeSet.add("GT");
+ regionCodeSet.add("GU");
+ regionCodeSet.add("GW");
+ regionCodeSet.add("GY");
+ regionCodeSet.add("HK");
+ regionCodeSet.add("HN");
+ regionCodeSet.add("HR");
+ regionCodeSet.add("HT");
+ regionCodeSet.add("HU");
+ regionCodeSet.add("ID");
+ regionCodeSet.add("IE");
+ regionCodeSet.add("IL");
+ regionCodeSet.add("IM");
+ regionCodeSet.add("IN");
+ regionCodeSet.add("IQ");
+ regionCodeSet.add("IR");
+ regionCodeSet.add("IS");
+ regionCodeSet.add("IT");
+ regionCodeSet.add("JE");
+ regionCodeSet.add("JM");
+ regionCodeSet.add("JO");
+ regionCodeSet.add("JP");
+ regionCodeSet.add("KE");
+ regionCodeSet.add("KG");
+ regionCodeSet.add("KH");
+ regionCodeSet.add("KI");
+ regionCodeSet.add("KM");
+ regionCodeSet.add("KN");
+ regionCodeSet.add("KR");
+ regionCodeSet.add("KW");
+ regionCodeSet.add("KY");
+ regionCodeSet.add("KZ");
+ regionCodeSet.add("LA");
+ regionCodeSet.add("LB");
+ regionCodeSet.add("LC");
+ regionCodeSet.add("LI");
+ regionCodeSet.add("LK");
+ regionCodeSet.add("LR");
+ regionCodeSet.add("LS");
+ regionCodeSet.add("LT");
+ regionCodeSet.add("LU");
+ regionCodeSet.add("LV");
+ regionCodeSet.add("LY");
+ regionCodeSet.add("MA");
+ regionCodeSet.add("MC");
+ regionCodeSet.add("MD");
+ regionCodeSet.add("ME");
+ regionCodeSet.add("MF");
+ regionCodeSet.add("MG");
+ regionCodeSet.add("MH");
+ regionCodeSet.add("MK");
+ regionCodeSet.add("ML");
+ regionCodeSet.add("MM");
+ regionCodeSet.add("MN");
+ regionCodeSet.add("MO");
+ regionCodeSet.add("MP");
+ regionCodeSet.add("MQ");
+ regionCodeSet.add("MR");
+ regionCodeSet.add("MS");
+ regionCodeSet.add("MT");
+ regionCodeSet.add("MU");
+ regionCodeSet.add("MV");
+ regionCodeSet.add("MW");
+ regionCodeSet.add("MX");
+ regionCodeSet.add("MY");
+ regionCodeSet.add("MZ");
+ regionCodeSet.add("NA");
+ regionCodeSet.add("NC");
+ regionCodeSet.add("NF");
+ regionCodeSet.add("NG");
+ regionCodeSet.add("NI");
+ regionCodeSet.add("NL");
+ regionCodeSet.add("NO");
+ regionCodeSet.add("NP");
+ regionCodeSet.add("NR");
+ regionCodeSet.add("NU");
+ regionCodeSet.add("NZ");
+ regionCodeSet.add("OM");
+ regionCodeSet.add("PA");
+ regionCodeSet.add("PE");
+ regionCodeSet.add("PF");
+ regionCodeSet.add("PG");
+ regionCodeSet.add("PH");
+ regionCodeSet.add("PK");
+ regionCodeSet.add("PL");
+ regionCodeSet.add("PM");
+ regionCodeSet.add("PR");
+ regionCodeSet.add("PT");
+ regionCodeSet.add("PW");
+ regionCodeSet.add("PY");
+ regionCodeSet.add("QA");
+ regionCodeSet.add("RE");
+ regionCodeSet.add("RO");
+ regionCodeSet.add("RS");
+ regionCodeSet.add("RU");
+ regionCodeSet.add("RW");
+ regionCodeSet.add("SA");
+ regionCodeSet.add("SB");
+ regionCodeSet.add("SC");
+ regionCodeSet.add("SD");
+ regionCodeSet.add("SE");
+ regionCodeSet.add("SG");
+ regionCodeSet.add("SH");
+ regionCodeSet.add("SI");
+ regionCodeSet.add("SJ");
+ regionCodeSet.add("SK");
+ regionCodeSet.add("SL");
+ regionCodeSet.add("SM");
+ regionCodeSet.add("SN");
+ regionCodeSet.add("SR");
+ regionCodeSet.add("ST");
+ regionCodeSet.add("SV");
+ regionCodeSet.add("SX");
+ regionCodeSet.add("SY");
+ regionCodeSet.add("SZ");
+ regionCodeSet.add("TC");
+ regionCodeSet.add("TD");
+ regionCodeSet.add("TG");
+ regionCodeSet.add("TH");
+ regionCodeSet.add("TJ");
+ regionCodeSet.add("TL");
+ regionCodeSet.add("TM");
+ regionCodeSet.add("TN");
+ regionCodeSet.add("TO");
+ regionCodeSet.add("TR");
+ regionCodeSet.add("TT");
+ regionCodeSet.add("TV");
+ regionCodeSet.add("TW");
+ regionCodeSet.add("TZ");
+ regionCodeSet.add("UA");
+ regionCodeSet.add("UG");
+ regionCodeSet.add("US");
+ regionCodeSet.add("UY");
+ regionCodeSet.add("UZ");
+ regionCodeSet.add("VA");
+ regionCodeSet.add("VC");
+ regionCodeSet.add("VE");
+ regionCodeSet.add("VG");
+ regionCodeSet.add("VI");
+ regionCodeSet.add("VN");
+ regionCodeSet.add("VU");
+ regionCodeSet.add("WF");
+ regionCodeSet.add("WS");
+ regionCodeSet.add("YE");
+ regionCodeSet.add("YT");
+ regionCodeSet.add("ZA");
+ regionCodeSet.add("ZM");
+ regionCodeSet.add("ZW");
+
+ return regionCodeSet;
+ }
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255
new file mode 100644
index 00000000..7c4f9daa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27
new file mode 100644
index 00000000..5ab6d03f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30
new file mode 100644
index 00000000..4f6f50a5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31
new file mode 100644
index 00000000..1999488e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34
new file mode 100644
index 00000000..7c60d3d6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350
new file mode 100644
index 00000000..e857d20e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351
new file mode 100644
index 00000000..bd077e77
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352
new file mode 100644
index 00000000..7ee05e92
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358
new file mode 100644
index 00000000..dc7a5d13
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359
new file mode 100644
index 00000000..6431d101
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36
new file mode 100644
index 00000000..9284fb16
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372
new file mode 100644
index 00000000..a16f968b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373
new file mode 100644
index 00000000..6932076f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_375 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_375
new file mode 100644
index 00000000..b7d8cacd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_375
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380
new file mode 100644
index 00000000..ef963276
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381
new file mode 100644
index 00000000..37654d46
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385
new file mode 100644
index 00000000..c6d79133
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43
new file mode 100644
index 00000000..48addfeb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44
new file mode 100644
index 00000000..4864eeb6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49
new file mode 100644
index 00000000..54cc030a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505
new file mode 100644
index 00000000..f8b78ffb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506
new file mode 100644
index 00000000..1987a239
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54
new file mode 100644
index 00000000..c401bf93
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55
new file mode 100644
index 00000000..a2075952
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58
new file mode 100644
index 00000000..da951398
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595
new file mode 100644
index 00000000..8f4dfc66
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61
new file mode 100644
index 00000000..7a0a3b81
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62
new file mode 100644
index 00000000..8763d3c0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_63 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_63
new file mode 100644
index 00000000..84f5a53c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_63
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66
new file mode 100644
index 00000000..bcf3abb9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675
new file mode 100644
index 00000000..52d0a37d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676
new file mode 100644
index 00000000..e7f5f11d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679
new file mode 100644
index 00000000..15209d24
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7
new file mode 100644
index 00000000..5d72f0be
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81
new file mode 100644
index 00000000..efe9684b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84
new file mode 100644
index 00000000..5c772332
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855
new file mode 100644
index 00000000..e231e9d5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90
new file mode 100644
index 00000000..94750712
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91
new file mode 100644
index 00000000..f63b8ecf
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94
new file mode 100644
index 00000000..69584350
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95
new file mode 100644
index 00000000..a672784f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971
new file mode 100644
index 00000000..31d4fe03
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972
new file mode 100644
index 00000000..01d2cb9f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995
new file mode 100644
index 00000000..81d6f13b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800
new file mode 100644
index 00000000..03c5f19e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808
new file mode 100644
index 00000000..683e159e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870
new file mode 100644
index 00000000..954e72b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878
new file mode 100644
index 00000000..f6eaf0aa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881
new file mode 100644
index 00000000..d750a33e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882
new file mode 100644
index 00000000..a6e6f449
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883
new file mode 100644
index 00000000..cc8cc35c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888
new file mode 100644
index 00000000..11a52b1e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979
new file mode 100644
index 00000000..5fb8fb58
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC
new file mode 100644
index 00000000..c1d98feb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD
new file mode 100644
index 00000000..24d4d001
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE
new file mode 100644
index 00000000..33d770f6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF
new file mode 100644
index 00000000..d80c5968
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG
new file mode 100644
index 00000000..6140377e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI
new file mode 100644
index 00000000..61bd0228
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL
new file mode 100644
index 00000000..54228be8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM
new file mode 100644
index 00000000..3c6b31bc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO
new file mode 100644
index 00000000..fe65c05e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR
new file mode 100644
index 00000000..b9a27fdc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS
new file mode 100644
index 00000000..f2a61e94
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT
new file mode 100644
index 00000000..143082d3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU
new file mode 100644
index 00000000..1212a887
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW
new file mode 100644
index 00000000..a7b06e98
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX
new file mode 100644
index 00000000..8de12c46
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ
new file mode 100644
index 00000000..11ee8681
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA
new file mode 100644
index 00000000..b3ed0bbf
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB
new file mode 100644
index 00000000..8c45b2b6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD
new file mode 100644
index 00000000..7b3a4f28
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE
new file mode 100644
index 00000000..8d2a5a27
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF
new file mode 100644
index 00000000..2311f572
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG
new file mode 100644
index 00000000..2d1787e0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH
new file mode 100644
index 00000000..d930cfc1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI
new file mode 100644
index 00000000..26aaa656
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ
new file mode 100644
index 00000000..290ec580
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL
new file mode 100644
index 00000000..94ba050e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM
new file mode 100644
index 00000000..0bef470f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN
new file mode 100644
index 00000000..cffdb8b6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO
new file mode 100644
index 00000000..021c2274
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ
new file mode 100644
index 00000000..62f35c24
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR
new file mode 100644
index 00000000..6b971763
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS
new file mode 100644
index 00000000..f385d53a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT
new file mode 100644
index 00000000..e98b41a4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW
new file mode 100644
index 00000000..777d118e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY
new file mode 100644
index 00000000..c1be2b9d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ
new file mode 100644
index 00000000..831e7213
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA
new file mode 100644
index 00000000..b92641f6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC
new file mode 100644
index 00000000..4d94ee04
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD
new file mode 100644
index 00000000..b52fcca4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF
new file mode 100644
index 00000000..af516499
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG
new file mode 100644
index 00000000..52b7b7a8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH
new file mode 100644
index 00000000..6449451e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI
new file mode 100644
index 00000000..972c334d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK
new file mode 100644
index 00000000..c084b84c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL
new file mode 100644
index 00000000..14696510
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM
new file mode 100644
index 00000000..7e8dff07
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN
new file mode 100644
index 00000000..ed06d7c9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO
new file mode 100644
index 00000000..b86a88f7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR
new file mode 100644
index 00000000..3857111b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU
new file mode 100644
index 00000000..fedae526
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV
new file mode 100644
index 00000000..0544c71f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW
new file mode 100644
index 00000000..c72f5590
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX
new file mode 100644
index 00000000..4462c5ba
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY
new file mode 100644
index 00000000..49fc8544
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ
new file mode 100644
index 00000000..297fbe4d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE
new file mode 100644
index 00000000..2afa77e2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ
new file mode 100644
index 00000000..a9d3ddf8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK
new file mode 100644
index 00000000..bd3a9d40
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM
new file mode 100644
index 00000000..459a0f23
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO
new file mode 100644
index 00000000..8a4dace5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ
new file mode 100644
index 00000000..92b247fb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC
new file mode 100644
index 00000000..7d1eecca
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE
new file mode 100644
index 00000000..8f1881a6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG
new file mode 100644
index 00000000..7511ce67
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH
new file mode 100644
index 00000000..f9a97fa7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER
new file mode 100644
index 00000000..0e1f43a8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES
new file mode 100644
index 00000000..b895148c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET
new file mode 100644
index 00000000..cbf1c4c8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI
new file mode 100644
index 00000000..44d04e05
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ
new file mode 100644
index 00000000..fe9f621e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK
new file mode 100644
index 00000000..7343c284
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM
new file mode 100644
index 00000000..714e4649
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO
new file mode 100644
index 00000000..2fdbbfb8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR
new file mode 100644
index 00000000..80e45dde
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA
new file mode 100644
index 00000000..ffaca37a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB
new file mode 100644
index 00000000..c409f124
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD
new file mode 100644
index 00000000..9849e748
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE
new file mode 100644
index 00000000..62d6dacc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF
new file mode 100644
index 00000000..494984c7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG
new file mode 100644
index 00000000..eb89ae69
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH
new file mode 100644
index 00000000..cd8b59a0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI
new file mode 100644
index 00000000..58279c9c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL
new file mode 100644
index 00000000..4a9150e6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM
new file mode 100644
index 00000000..bd678000
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN
new file mode 100644
index 00000000..b975a1d4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP
new file mode 100644
index 00000000..ca0192bb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ
new file mode 100644
index 00000000..13942357
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR
new file mode 100644
index 00000000..c9c43ddc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT
new file mode 100644
index 00000000..cb729cd2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU
new file mode 100644
index 00000000..78a606de
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW
new file mode 100644
index 00000000..006de137
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY
new file mode 100644
index 00000000..a7b2ae13
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK
new file mode 100644
index 00000000..7f3ff70a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN
new file mode 100644
index 00000000..a66ea52c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR
new file mode 100644
index 00000000..7c3657b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT
new file mode 100644
index 00000000..438952c4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU
new file mode 100644
index 00000000..0da84020
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID
new file mode 100644
index 00000000..90d5487e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE
new file mode 100644
index 00000000..9db8f6ef
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL
new file mode 100644
index 00000000..afe40ac5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM
new file mode 100644
index 00000000..216267c0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN
new file mode 100644
index 00000000..43fc271c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO
new file mode 100644
index 00000000..a6caa036
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ
new file mode 100644
index 00000000..5436f0ab
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR
new file mode 100644
index 00000000..b66fcccb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS
new file mode 100644
index 00000000..ece7eb7e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT
new file mode 100644
index 00000000..926ad1b5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE
new file mode 100644
index 00000000..15be96b2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM
new file mode 100644
index 00000000..17200e0f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO
new file mode 100644
index 00000000..e2ff6b93
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP
new file mode 100644
index 00000000..e3b61f1f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE
new file mode 100644
index 00000000..6afb7b7d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG
new file mode 100644
index 00000000..08b01753
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH
new file mode 100644
index 00000000..80a41a19
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI
new file mode 100644
index 00000000..1be3aa87
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM
new file mode 100644
index 00000000..ab70e5ca
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN
new file mode 100644
index 00000000..e185e763
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP
new file mode 100644
index 00000000..2713b6c3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR
new file mode 100644
index 00000000..9e587ee0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW
new file mode 100644
index 00000000..19da153e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY
new file mode 100644
index 00000000..720d62c9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ
new file mode 100644
index 00000000..3ca2463a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA
new file mode 100644
index 00000000..2b900017
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB
new file mode 100644
index 00000000..39882264
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC
new file mode 100644
index 00000000..b36be6b6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI
new file mode 100644
index 00000000..25255311
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK
new file mode 100644
index 00000000..effd73cd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR
new file mode 100644
index 00000000..428ad11d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS
new file mode 100644
index 00000000..7bec656b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT
new file mode 100644
index 00000000..d9c46a38
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU
new file mode 100644
index 00000000..fd878778
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV
new file mode 100644
index 00000000..a0a53af2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY
new file mode 100644
index 00000000..2616120b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA
new file mode 100644
index 00000000..333d0870
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC
new file mode 100644
index 00000000..36bd6598
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD
new file mode 100644
index 00000000..a725e1f4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME
new file mode 100644
index 00000000..cdcb96db
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF
new file mode 100644
index 00000000..7a8f9173
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG
new file mode 100644
index 00000000..8599673b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH
new file mode 100644
index 00000000..1f20fa6b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK
new file mode 100644
index 00000000..95ebb144
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML
new file mode 100644
index 00000000..b14c8bb6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM
new file mode 100644
index 00000000..c2cbbdf4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN
new file mode 100644
index 00000000..0a931c92
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO
new file mode 100644
index 00000000..04bbe12c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP
new file mode 100644
index 00000000..e0cbcf92
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ
new file mode 100644
index 00000000..07858595
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR
new file mode 100644
index 00000000..a00424d8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS
new file mode 100644
index 00000000..9cc97639
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT
new file mode 100644
index 00000000..8375e5f6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU
new file mode 100644
index 00000000..63676ca2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV
new file mode 100644
index 00000000..5d3a10ab
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW
new file mode 100644
index 00000000..f4605620
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX
new file mode 100644
index 00000000..7dd414a5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY
new file mode 100644
index 00000000..2e455305
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ
new file mode 100644
index 00000000..65b2f1f1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA
new file mode 100644
index 00000000..f8d70495
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC
new file mode 100644
index 00000000..6f3083ab
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE
new file mode 100644
index 00000000..8d0e16c1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF
new file mode 100644
index 00000000..615256de
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG
new file mode 100644
index 00000000..384af71e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI
new file mode 100644
index 00000000..fd6a7c13
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL
new file mode 100644
index 00000000..b9c52db0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO
new file mode 100644
index 00000000..71d187a3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP
new file mode 100644
index 00000000..49a9ff4c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR
new file mode 100644
index 00000000..7f9f74f4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU
new file mode 100644
index 00000000..be8fe367
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ
new file mode 100644
index 00000000..ca431407
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM
new file mode 100644
index 00000000..88e9406f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA
new file mode 100644
index 00000000..24a7a770
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE
new file mode 100644
index 00000000..2c9bbc5b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF
new file mode 100644
index 00000000..b1536f4c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG
new file mode 100644
index 00000000..ab342f6b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH
new file mode 100644
index 00000000..6f565d6a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK
new file mode 100644
index 00000000..f569c5cd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL
new file mode 100644
index 00000000..491de26c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM
new file mode 100644
index 00000000..df14f84a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR
new file mode 100644
index 00000000..7ce02f20
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS
new file mode 100644
index 00000000..821f17a3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT
new file mode 100644
index 00000000..5c15da8f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW
new file mode 100644
index 00000000..3a01a256
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY
new file mode 100644
index 00000000..298e973c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA
new file mode 100644
index 00000000..24c88869
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE
new file mode 100644
index 00000000..8a1cb9ee
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO
new file mode 100644
index 00000000..db604af0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS
new file mode 100644
index 00000000..06de92e5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU
new file mode 100644
index 00000000..c769356a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW
new file mode 100644
index 00000000..a6d7a148
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA
new file mode 100644
index 00000000..48930210
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB
new file mode 100644
index 00000000..49974502
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC
new file mode 100644
index 00000000..8762a536
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD
new file mode 100644
index 00000000..c56f4fbd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE
new file mode 100644
index 00000000..c23cf2f9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG
new file mode 100644
index 00000000..9204ad9f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH
new file mode 100644
index 00000000..77d4a794
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI
new file mode 100644
index 00000000..a2607df1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ
new file mode 100644
index 00000000..4ca42737
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK
new file mode 100644
index 00000000..19642c6b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL
new file mode 100644
index 00000000..f5d38fcd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM
new file mode 100644
index 00000000..4294cf93
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN
new file mode 100644
index 00000000..9cfc22eb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO
new file mode 100644
index 00000000..96ea1998
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR
new file mode 100644
index 00000000..7ea63edd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS
new file mode 100644
index 00000000..86e0518d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST
new file mode 100644
index 00000000..f364573a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV
new file mode 100644
index 00000000..d1666974
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX
new file mode 100644
index 00000000..472486a2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY
new file mode 100644
index 00000000..7f03a188
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ
new file mode 100644
index 00000000..3cd853b3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA
new file mode 100644
index 00000000..769f6f09
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC
new file mode 100644
index 00000000..409fe598
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD
new file mode 100644
index 00000000..b5401425
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG
new file mode 100644
index 00000000..0e90dbc1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH
new file mode 100644
index 00000000..b2f44e25
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ
new file mode 100644
index 00000000..02a73f61
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK
new file mode 100644
index 00000000..e20bb98d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL
new file mode 100644
index 00000000..11fd5af0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM
new file mode 100644
index 00000000..9013b60d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN
new file mode 100644
index 00000000..a6441e8d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO
new file mode 100644
index 00000000..29d6dee5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR
new file mode 100644
index 00000000..19d2338e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT
new file mode 100644
index 00000000..7d3b2e0e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV
new file mode 100644
index 00000000..ca2e8b86
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW
new file mode 100644
index 00000000..de246f5e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ
new file mode 100644
index 00000000..f9f553b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA
new file mode 100644
index 00000000..f700468f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG
new file mode 100644
index 00000000..12d16a91
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US
new file mode 100644
index 00000000..e8d8683c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY
new file mode 100644
index 00000000..e2f73886
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ
new file mode 100644
index 00000000..1711a97c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA
new file mode 100644
index 00000000..72c260fa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC
new file mode 100644
index 00000000..551e326e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE
new file mode 100644
index 00000000..5e3db17e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG
new file mode 100644
index 00000000..28f0f02e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI
new file mode 100644
index 00000000..8454793e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN
new file mode 100644
index 00000000..0fd97d47
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU
new file mode 100644
index 00000000..36fd3d80
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF
new file mode 100644
index 00000000..a0801df4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS
new file mode 100644
index 00000000..02cced67
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE
new file mode 100644
index 00000000..24f3bd2a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT
new file mode 100644
index 00000000..2f6153d9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA
new file mode 100644
index 00000000..8598631a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM
new file mode 100644
index 00000000..0ba0feef
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW
new file mode 100644
index 00000000..f295d2c1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC
new file mode 100644
index 00000000..0fb368e1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD
new file mode 100644
index 00000000..fe534033
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE
new file mode 100644
index 00000000..fb4894dd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF
new file mode 100644
index 00000000..6ea72a59
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG
new file mode 100644
index 00000000..d1b952a8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI
new file mode 100644
index 00000000..d0cf967c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL
new file mode 100644
index 00000000..b8948291
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM
new file mode 100644
index 00000000..40ae751f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO
new file mode 100644
index 00000000..2b7b5450
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR
new file mode 100644
index 00000000..4b38d722
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS
new file mode 100644
index 00000000..3a15688f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT
new file mode 100644
index 00000000..946641be
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU
new file mode 100644
index 00000000..8a14d4f8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW
new file mode 100644
index 00000000..933e7cca
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX
new file mode 100644
index 00000000..a52bc978
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ
new file mode 100644
index 00000000..797d5294
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA
new file mode 100644
index 00000000..c1c073c1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB
new file mode 100644
index 00000000..048dea48
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD
new file mode 100644
index 00000000..18b73445
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE
new file mode 100644
index 00000000..1352acfc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF
new file mode 100644
index 00000000..2cb5251c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG
new file mode 100644
index 00000000..a454f3b8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH
new file mode 100644
index 00000000..4d857280
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI
new file mode 100644
index 00000000..a0eacfdf
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ
new file mode 100644
index 00000000..153ec9ec
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL
new file mode 100644
index 00000000..3e4866ec
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM
new file mode 100644
index 00000000..155b7d52
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN
new file mode 100644
index 00000000..37ee404a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO
new file mode 100644
index 00000000..7a01bf81
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ
new file mode 100644
index 00000000..d3b876e3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR
new file mode 100644
index 00000000..5d2d656b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS
new file mode 100644
index 00000000..aa460ff6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT
new file mode 100644
index 00000000..b4046502
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW
new file mode 100644
index 00000000..85fdfc0b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY
new file mode 100644
index 00000000..49bf8ab9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ
new file mode 100644
index 00000000..bbd87bf7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA
new file mode 100644
index 00000000..87c09c94
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC
new file mode 100644
index 00000000..0a5f6751
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD
new file mode 100644
index 00000000..dfa9f7a1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH
new file mode 100644
index 00000000..821281fe
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI
new file mode 100644
index 00000000..81f7dccc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK
new file mode 100644
index 00000000..3c396905
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL
new file mode 100644
index 00000000..ecaa04f1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM
new file mode 100644
index 00000000..8df38012
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN
new file mode 100644
index 00000000..98054ff0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO
new file mode 100644
index 00000000..0c4eff1b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR
new file mode 100644
index 00000000..3411d7f1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU
new file mode 100644
index 00000000..ea834cb8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV
new file mode 100644
index 00000000..783da2e7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW
new file mode 100644
index 00000000..57187502
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX
new file mode 100644
index 00000000..ce8b75d8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY
new file mode 100644
index 00000000..c5962d38
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ
new file mode 100644
index 00000000..4a644f3c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE
new file mode 100644
index 00000000..8fe45dd3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ
new file mode 100644
index 00000000..8825c8b2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK
new file mode 100644
index 00000000..7cdaea8f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM
new file mode 100644
index 00000000..1a3604dd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO
new file mode 100644
index 00000000..34432f16
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ
new file mode 100644
index 00000000..2a1c8a7c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC
new file mode 100644
index 00000000..47142711
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE
new file mode 100644
index 00000000..6ca452dd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG
new file mode 100644
index 00000000..8638f07e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH
new file mode 100644
index 00000000..87c38a91
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES
new file mode 100644
index 00000000..e086ffa1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET
new file mode 100644
index 00000000..e0594080
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI
new file mode 100644
index 00000000..4982038a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ
new file mode 100644
index 00000000..2f2665e4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK
new file mode 100644
index 00000000..349ebe6c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM
new file mode 100644
index 00000000..24fba7ce
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO
new file mode 100644
index 00000000..f0901ac2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR
new file mode 100644
index 00000000..b91acd62
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA
new file mode 100644
index 00000000..958d8e99
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB
new file mode 100644
index 00000000..8be70a07
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD
new file mode 100644
index 00000000..208a7a78
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE
new file mode 100644
index 00000000..fb236a77
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF
new file mode 100644
index 00000000..d35588db
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG
new file mode 100644
index 00000000..ac284653
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH
new file mode 100644
index 00000000..9a8a4721
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI
new file mode 100644
index 00000000..c494df98
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL
new file mode 100644
index 00000000..177d6fdb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM
new file mode 100644
index 00000000..c890061a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN
new file mode 100644
index 00000000..6e2b7c9a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP
new file mode 100644
index 00000000..d199bed2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR
new file mode 100644
index 00000000..1f9b0b12
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT
new file mode 100644
index 00000000..53c1c04f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU
new file mode 100644
index 00000000..97b9bef4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW
new file mode 100644
index 00000000..e2966942
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY
new file mode 100644
index 00000000..b5977d98
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK
new file mode 100644
index 00000000..db5f3f8d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN
new file mode 100644
index 00000000..cd8a2108
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR
new file mode 100644
index 00000000..df743037
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT
new file mode 100644
index 00000000..6eedab01
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU
new file mode 100644
index 00000000..46498f6d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID
new file mode 100644
index 00000000..630d89bd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE
new file mode 100644
index 00000000..5db571af
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL
new file mode 100644
index 00000000..13567974
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM
new file mode 100644
index 00000000..51af3cd3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN
new file mode 100644
index 00000000..323d45c5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ
new file mode 100644
index 00000000..5a711cbf
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR
new file mode 100644
index 00000000..f2b7611d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS
new file mode 100644
index 00000000..d9d473b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT
new file mode 100644
index 00000000..b4fb3215
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE
new file mode 100644
index 00000000..918ae8ce
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM
new file mode 100644
index 00000000..865b0ce8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO
new file mode 100644
index 00000000..e7afad28
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP
new file mode 100644
index 00000000..a881213d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE
new file mode 100644
index 00000000..31013f9f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG
new file mode 100644
index 00000000..be9ba991
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH
new file mode 100644
index 00000000..f92e2c38
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI
new file mode 100644
index 00000000..58942690
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM
new file mode 100644
index 00000000..282b9aff
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN
new file mode 100644
index 00000000..11f927b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR
new file mode 100644
index 00000000..6e009678
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW
new file mode 100644
index 00000000..a492b005
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY
new file mode 100644
index 00000000..2c7fa884
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ
new file mode 100644
index 00000000..19f3e541
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA
new file mode 100644
index 00000000..fae89ce2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB
new file mode 100644
index 00000000..825a9ee1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC
new file mode 100644
index 00000000..a26db878
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI
new file mode 100644
index 00000000..4c5f9bf2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK
new file mode 100644
index 00000000..adb6cfc9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR
new file mode 100644
index 00000000..8d7a29ac
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS
new file mode 100644
index 00000000..3819b431
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT
new file mode 100644
index 00000000..8148ca74
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU
new file mode 100644
index 00000000..f099c4ba
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV
new file mode 100644
index 00000000..e6d922f2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY
new file mode 100644
index 00000000..f389f9c2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA
new file mode 100644
index 00000000..a00d409d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC
new file mode 100644
index 00000000..eae7953b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD
new file mode 100644
index 00000000..41b3e576
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME
new file mode 100644
index 00000000..e9d5f1d0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF
new file mode 100644
index 00000000..e6ee4a2e
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG
new file mode 100644
index 00000000..203b7250
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH
new file mode 100644
index 00000000..a3e55bea
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK
new file mode 100644
index 00000000..3702ec24
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML
new file mode 100644
index 00000000..eb61dd4a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM
new file mode 100644
index 00000000..7016f326
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN
new file mode 100644
index 00000000..097cbbb1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO
new file mode 100644
index 00000000..623e577d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP
new file mode 100644
index 00000000..2f4a6b6c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ
new file mode 100644
index 00000000..690367fb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR
new file mode 100644
index 00000000..8e8d9922
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS
new file mode 100644
index 00000000..083f7fd4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT
new file mode 100644
index 00000000..f8345497
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU
new file mode 100644
index 00000000..a37fec1b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV
new file mode 100644
index 00000000..aeb03dd4
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW
new file mode 100644
index 00000000..8efd2c57
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX
new file mode 100644
index 00000000..7e666437
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY
new file mode 100644
index 00000000..5c25f4ae
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ
new file mode 100644
index 00000000..fd9a38b2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA
new file mode 100644
index 00000000..24dbfc46
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC
new file mode 100644
index 00000000..3a506877
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF
new file mode 100644
index 00000000..65ca9ae5
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG
new file mode 100644
index 00000000..d6c02c30
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI
new file mode 100644
index 00000000..27e56139
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL
new file mode 100644
index 00000000..01dcf65b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO
new file mode 100644
index 00000000..f3f8843a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP
new file mode 100644
index 00000000..f937cc8a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR
new file mode 100644
index 00000000..4b6a0e43
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU
new file mode 100644
index 00000000..678a2827
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ
new file mode 100644
index 00000000..70f10e15
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM
new file mode 100644
index 00000000..76832fd9
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA
new file mode 100644
index 00000000..2358ea75
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE
new file mode 100644
index 00000000..819a123a
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF
new file mode 100644
index 00000000..91a65ed2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG
new file mode 100644
index 00000000..7d51ac94
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH
new file mode 100644
index 00000000..ef96a5a6
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK
new file mode 100644
index 00000000..678f4875
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL
new file mode 100644
index 00000000..ae1b6201
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM
new file mode 100644
index 00000000..ad1e7663
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR
new file mode 100644
index 00000000..bfefb4b1
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT
new file mode 100644
index 00000000..15fb4780
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW
new file mode 100644
index 00000000..a9f82943
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY
new file mode 100644
index 00000000..9bdea25c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA
new file mode 100644
index 00000000..9a704435
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE
new file mode 100644
index 00000000..1be529fe
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO
new file mode 100644
index 00000000..4cc39ab0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS
new file mode 100644
index 00000000..28af2446
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU
new file mode 100644
index 00000000..d0a711bb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW
new file mode 100644
index 00000000..6319123b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA
new file mode 100644
index 00000000..dc227c70
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB
new file mode 100644
index 00000000..53f59a03
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC
new file mode 100644
index 00000000..be38ce85
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD
new file mode 100644
index 00000000..27a91d47
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE
new file mode 100644
index 00000000..d10dc143
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG
new file mode 100644
index 00000000..18f18130
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH
new file mode 100644
index 00000000..559091cb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI
new file mode 100644
index 00000000..0722842b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ
new file mode 100644
index 00000000..72e937d8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK
new file mode 100644
index 00000000..ab81e665
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL
new file mode 100644
index 00000000..9a3e1398
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM
new file mode 100644
index 00000000..f7c73f14
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN
new file mode 100644
index 00000000..cb8ecc01
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR
new file mode 100644
index 00000000..16c24603
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST
new file mode 100644
index 00000000..51d2a9aa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV
new file mode 100644
index 00000000..4c26fe4b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX
new file mode 100644
index 00000000..297cb68b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY
new file mode 100644
index 00000000..009ec93d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ
new file mode 100644
index 00000000..7e5eb9fa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC
new file mode 100644
index 00000000..818bc0ac
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD
new file mode 100644
index 00000000..ff036a2f
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG
new file mode 100644
index 00000000..e2d5c285
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH
new file mode 100644
index 00000000..60bd59bd
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ
new file mode 100644
index 00000000..954c0f80
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL
new file mode 100644
index 00000000..1beee259
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM
new file mode 100644
index 00000000..83d453f2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN
new file mode 100644
index 00000000..7277d419
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO
new file mode 100644
index 00000000..735b30b0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR
new file mode 100644
index 00000000..c24e45d3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT
new file mode 100644
index 00000000..c68094eb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV
new file mode 100644
index 00000000..05f763fa
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW
new file mode 100644
index 00000000..ae252940
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ
new file mode 100644
index 00000000..44f79df0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA
new file mode 100644
index 00000000..9603cb81
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG
new file mode 100644
index 00000000..78128a28
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US
new file mode 100644
index 00000000..7c0cfb76
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY
new file mode 100644
index 00000000..d0e5e72b
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ
new file mode 100644
index 00000000..15f91a78
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA
new file mode 100644
index 00000000..8c2d76b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC
new file mode 100644
index 00000000..f91a7f52
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE
new file mode 100644
index 00000000..721c0ef3
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG
new file mode 100644
index 00000000..edea90f2
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI
new file mode 100644
index 00000000..56cce8c0
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN
new file mode 100644
index 00000000..d315c602
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU
new file mode 100644
index 00000000..6f9df3b7
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF
new file mode 100644
index 00000000..973769fc
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS
new file mode 100644
index 00000000..eaee6b8c
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE
new file mode 100644
index 00000000..e5066d43
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT
new file mode 100644
index 00000000..cb112c99
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA
new file mode 100644
index 00000000..f0afb76d
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM
new file mode 100644
index 00000000..db15bda8
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW
new file mode 100644
index 00000000..1a97eb42
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW
Binary files differ
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/internal/MatcherApi.java b/libphonenumber/src/com/google/i18n/phonenumbers/internal/MatcherApi.java
new file mode 100644
index 00000000..38319cbb
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/internal/MatcherApi.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+
+/**
+ * Internal phonenumber matching API used to isolate the underlying implementation of the
+ * matcher and allow different implementations to be swapped in easily.
+ */
+public interface MatcherApi {
+ /**
+ * Returns whether the given national number (a string containing only decimal digits) matches
+ * the national number pattern defined in the given {@code PhoneNumberDesc} message.
+ */
+ boolean matchesNationalNumber(String nationalNumber, PhoneNumberDesc numberDesc,
+ boolean allowPrefixMatch);
+
+ /**
+ * Returns whether the given national number (a string containing only decimal digits) matches
+ * the possible number pattern defined in the given {@code PhoneNumberDesc} message.
+ */
+ boolean matchesPossibleNumber(String nationalNumber, PhoneNumberDesc numberDesc);
+}
diff --git a/libphonenumber/src/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java b/libphonenumber/src/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java
new file mode 100644
index 00000000..125a1822
--- /dev/null
+++ b/libphonenumber/src/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+import com.google.i18n.phonenumbers.RegexCache;
+
+import java.util.regex.Matcher;
+
+/**
+ * Implementation of the matcher API using the regular expressions in the PhoneNumberDesc
+ * proto message to match numbers.
+ */
+public final class RegexBasedMatcher implements MatcherApi {
+ public static MatcherApi create() {
+ return new RegexBasedMatcher();
+ }
+
+ private final RegexCache regexCache = new RegexCache(100);
+
+ private RegexBasedMatcher() {}
+
+ // @Override
+ public boolean matchesNationalNumber(String nationalNumber, PhoneNumberDesc numberDesc,
+ boolean allowPrefixMatch) {
+ Matcher nationalNumberPatternMatcher = regexCache.getPatternForRegex(
+ numberDesc.getNationalNumberPattern()).matcher(nationalNumber);
+ return nationalNumberPatternMatcher.matches()
+ || (allowPrefixMatch && nationalNumberPatternMatcher.lookingAt());
+ }
+
+ // @Override
+ public boolean matchesPossibleNumber(String nationalNumber, PhoneNumberDesc numberDesc) {
+ Matcher possibleNumberPatternMatcher = regexCache.getPatternForRegex(
+ numberDesc.getPossibleNumberPattern()).matcher(nationalNumber);
+ return possibleNumberPatternMatcher.matches();
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java
new file mode 100644
index 00000000..3461a826
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (C) 2009 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;
+
+/**
+ * Unit tests for AsYouTypeFormatter.java
+ *
+ * Note that these tests use the test metadata, not the normal metadata file, so should not be used
+ * for regression test purposes - these tests are illustrative only and test functionality.
+ *
+ * @author Shaopeng Jia
+ */
+public class AsYouTypeFormatterTest extends TestMetadataTestCase {
+
+ public void testInvalidRegion() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.ZZ);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+4", formatter.inputDigit('4'));
+ assertEquals("+48 ", formatter.inputDigit('8'));
+ assertEquals("+48 8", formatter.inputDigit('8'));
+ assertEquals("+48 88", formatter.inputDigit('8'));
+ assertEquals("+48 88 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 12", formatter.inputDigit('2'));
+ assertEquals("+48 88 123", formatter.inputDigit('3'));
+ assertEquals("+48 88 123 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 123 12", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("6", formatter.inputDigit('6'));
+ assertEquals("65", formatter.inputDigit('5'));
+ assertEquals("650", formatter.inputDigit('0'));
+ assertEquals("6502", formatter.inputDigit('2'));
+ assertEquals("65025", formatter.inputDigit('5'));
+ assertEquals("650253", formatter.inputDigit('3'));
+ }
+
+ public void testInvalidPlusSign() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.ZZ);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+4", formatter.inputDigit('4'));
+ assertEquals("+48 ", formatter.inputDigit('8'));
+ assertEquals("+48 8", formatter.inputDigit('8'));
+ assertEquals("+48 88", formatter.inputDigit('8'));
+ assertEquals("+48 88 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 12", formatter.inputDigit('2'));
+ assertEquals("+48 88 123", formatter.inputDigit('3'));
+ assertEquals("+48 88 123 1", formatter.inputDigit('1'));
+ // A plus sign can only appear at the beginning of the number; otherwise, no formatting is
+ // applied.
+ assertEquals("+48881231+", formatter.inputDigit('+'));
+ assertEquals("+48881231+2", formatter.inputDigit('2'));
+ }
+
+ public void testTooLongNumberMatchingMultipleLeadingDigits() {
+ // See http://code.google.com/p/libphonenumber/issues/detail?id=36
+ // The bug occurred last time for countries which have two formatting rules with exactly the
+ // same leading digits pattern but differ in length.
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.ZZ);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+81 ", formatter.inputDigit('1'));
+ assertEquals("+81 9", formatter.inputDigit('9'));
+ assertEquals("+81 90", formatter.inputDigit('0'));
+ assertEquals("+81 90 1", formatter.inputDigit('1'));
+ assertEquals("+81 90 12", formatter.inputDigit('2'));
+ assertEquals("+81 90 123", formatter.inputDigit('3'));
+ assertEquals("+81 90 1234", formatter.inputDigit('4'));
+ assertEquals("+81 90 1234 5", formatter.inputDigit('5'));
+ assertEquals("+81 90 1234 56", formatter.inputDigit('6'));
+ assertEquals("+81 90 1234 567", formatter.inputDigit('7'));
+ assertEquals("+81 90 1234 5678", formatter.inputDigit('8'));
+ assertEquals("+81 90 12 345 6789", formatter.inputDigit('9'));
+ assertEquals("+81901234567890", formatter.inputDigit('0'));
+ assertEquals("+819012345678901", formatter.inputDigit('1'));
+ }
+
+ public void testCountryWithSpaceInNationalPrefixFormattingRule() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.BY);
+ assertEquals("8", formatter.inputDigit('8'));
+ assertEquals("88", formatter.inputDigit('8'));
+ assertEquals("881", formatter.inputDigit('1'));
+ assertEquals("8 819", formatter.inputDigit('9'));
+ assertEquals("8 8190", formatter.inputDigit('0'));
+ // The formatting rule for 5 digit numbers states that no space should be present after the
+ // national prefix.
+ assertEquals("881 901", formatter.inputDigit('1'));
+ assertEquals("8 819 012", formatter.inputDigit('2'));
+ // Too long, no formatting rule applies.
+ assertEquals("88190123", formatter.inputDigit('3'));
+ }
+
+ public void testCountryWithSpaceInNationalPrefixFormattingRuleAndLongNdd() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.BY);
+ assertEquals("9", formatter.inputDigit('9'));
+ assertEquals("99", formatter.inputDigit('9'));
+ assertEquals("999", formatter.inputDigit('9'));
+ assertEquals("9999", formatter.inputDigit('9'));
+ assertEquals("99999 ", formatter.inputDigit('9'));
+ assertEquals("99999 1", formatter.inputDigit('1'));
+ assertEquals("99999 12", formatter.inputDigit('2'));
+ assertEquals("99999 123", formatter.inputDigit('3'));
+ assertEquals("99999 1234", formatter.inputDigit('4'));
+ assertEquals("99999 12 345", formatter.inputDigit('5'));
+ }
+
+ public void testAYTFUS() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+ assertEquals("6", formatter.inputDigit('6'));
+ assertEquals("65", formatter.inputDigit('5'));
+ assertEquals("650", formatter.inputDigit('0'));
+ assertEquals("650 2", formatter.inputDigit('2'));
+ assertEquals("650 25", formatter.inputDigit('5'));
+ assertEquals("650 253", formatter.inputDigit('3'));
+ // Note this is how a US local number (without area code) should be formatted.
+ assertEquals("650 2532", formatter.inputDigit('2'));
+ assertEquals("650 253 22", formatter.inputDigit('2'));
+ assertEquals("650 253 222", formatter.inputDigit('2'));
+ assertEquals("650 253 2222", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("16", formatter.inputDigit('6'));
+ assertEquals("1 65", formatter.inputDigit('5'));
+ assertEquals("1 650", formatter.inputDigit('0'));
+ assertEquals("1 650 2", formatter.inputDigit('2'));
+ assertEquals("1 650 25", formatter.inputDigit('5'));
+ assertEquals("1 650 253", formatter.inputDigit('3'));
+ assertEquals("1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("1 650 253 2222", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011 ", formatter.inputDigit('1'));
+ assertEquals("011 4", formatter.inputDigit('4'));
+ assertEquals("011 44 ", formatter.inputDigit('4'));
+ assertEquals("011 44 6", formatter.inputDigit('6'));
+ assertEquals("011 44 61", formatter.inputDigit('1'));
+ assertEquals("011 44 6 12", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123", formatter.inputDigit('3'));
+ assertEquals("011 44 6 123 1", formatter.inputDigit('1'));
+ assertEquals("011 44 6 123 12", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123 123", formatter.inputDigit('3'));
+ assertEquals("011 44 6 123 123 1", formatter.inputDigit('1'));
+ assertEquals("011 44 6 123 123 12", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123 123 123", formatter.inputDigit('3'));
+
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011 ", formatter.inputDigit('1'));
+ assertEquals("011 5", formatter.inputDigit('5'));
+ assertEquals("011 54 ", formatter.inputDigit('4'));
+ assertEquals("011 54 9", formatter.inputDigit('9'));
+ assertEquals("011 54 91", formatter.inputDigit('1'));
+ assertEquals("011 54 9 11", formatter.inputDigit('1'));
+ assertEquals("011 54 9 11 2", formatter.inputDigit('2'));
+ assertEquals("011 54 9 11 23", formatter.inputDigit('3'));
+ assertEquals("011 54 9 11 231", formatter.inputDigit('1'));
+ assertEquals("011 54 9 11 2312", formatter.inputDigit('2'));
+ assertEquals("011 54 9 11 2312 1", formatter.inputDigit('1'));
+ assertEquals("011 54 9 11 2312 12", formatter.inputDigit('2'));
+ assertEquals("011 54 9 11 2312 123", formatter.inputDigit('3'));
+ assertEquals("011 54 9 11 2312 1234", formatter.inputDigit('4'));
+
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011 ", formatter.inputDigit('1'));
+ assertEquals("011 2", formatter.inputDigit('2'));
+ assertEquals("011 24", formatter.inputDigit('4'));
+ assertEquals("011 244 ", formatter.inputDigit('4'));
+ assertEquals("011 244 2", formatter.inputDigit('2'));
+ assertEquals("011 244 28", formatter.inputDigit('8'));
+ assertEquals("011 244 280", formatter.inputDigit('0'));
+ assertEquals("011 244 280 0", formatter.inputDigit('0'));
+ assertEquals("011 244 280 00", formatter.inputDigit('0'));
+ assertEquals("011 244 280 000", formatter.inputDigit('0'));
+ assertEquals("011 244 280 000 0", formatter.inputDigit('0'));
+ assertEquals("011 244 280 000 00", formatter.inputDigit('0'));
+ assertEquals("011 244 280 000 000", formatter.inputDigit('0'));
+
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+4", formatter.inputDigit('4'));
+ assertEquals("+48 ", formatter.inputDigit('8'));
+ assertEquals("+48 8", formatter.inputDigit('8'));
+ assertEquals("+48 88", formatter.inputDigit('8'));
+ assertEquals("+48 88 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 12", formatter.inputDigit('2'));
+ assertEquals("+48 88 123", formatter.inputDigit('3'));
+ assertEquals("+48 88 123 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 123 12", formatter.inputDigit('2'));
+ assertEquals("+48 88 123 12 1", formatter.inputDigit('1'));
+ assertEquals("+48 88 123 12 12", formatter.inputDigit('2'));
+ }
+
+ public void testAYTFUSFullWidthCharacters() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+ assertEquals("\uFF16", formatter.inputDigit('\uFF16'));
+ assertEquals("\uFF16\uFF15", formatter.inputDigit('\uFF15'));
+ assertEquals("650", formatter.inputDigit('\uFF10'));
+ assertEquals("650 2", formatter.inputDigit('\uFF12'));
+ assertEquals("650 25", formatter.inputDigit('\uFF15'));
+ assertEquals("650 253", formatter.inputDigit('\uFF13'));
+ assertEquals("650 2532", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 22", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 222", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 2222", formatter.inputDigit('\uFF12'));
+ }
+
+ public void testAYTFUSMobileShortCode() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+ assertEquals("*", formatter.inputDigit('*'));
+ assertEquals("*1", formatter.inputDigit('1'));
+ assertEquals("*12", formatter.inputDigit('2'));
+ assertEquals("*121", formatter.inputDigit('1'));
+ assertEquals("*121#", formatter.inputDigit('#'));
+ }
+
+ public void testAYTFUSVanityNumber() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+ assertEquals("8", formatter.inputDigit('8'));
+ assertEquals("80", formatter.inputDigit('0'));
+ assertEquals("800", formatter.inputDigit('0'));
+ assertEquals("800 ", formatter.inputDigit(' '));
+ assertEquals("800 M", formatter.inputDigit('M'));
+ assertEquals("800 MY", formatter.inputDigit('Y'));
+ assertEquals("800 MY ", formatter.inputDigit(' '));
+ assertEquals("800 MY A", formatter.inputDigit('A'));
+ assertEquals("800 MY AP", formatter.inputDigit('P'));
+ assertEquals("800 MY APP", formatter.inputDigit('P'));
+ assertEquals("800 MY APPL", formatter.inputDigit('L'));
+ assertEquals("800 MY APPLE", formatter.inputDigit('E'));
+ }
+
+ public void testAYTFAndRememberPositionUS() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+ assertEquals("1", formatter.inputDigitAndRememberPosition('1'));
+ assertEquals(1, formatter.getRememberedPosition());
+ assertEquals("16", formatter.inputDigit('6'));
+ assertEquals("1 65", formatter.inputDigit('5'));
+ assertEquals(1, formatter.getRememberedPosition());
+ assertEquals("1 650", formatter.inputDigitAndRememberPosition('0'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("1 650 2", formatter.inputDigit('2'));
+ assertEquals("1 650 25", formatter.inputDigit('5'));
+ // Note the remembered position for digit "0" changes from 4 to 5, because a space is now
+ // inserted in the front.
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("1 650 253", formatter.inputDigit('3'));
+ assertEquals("1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("1 650 253 22", formatter.inputDigit('2'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("1 650 253 222", formatter.inputDigitAndRememberPosition('2'));
+ assertEquals(13, formatter.getRememberedPosition());
+ assertEquals("1 650 253 2222", formatter.inputDigit('2'));
+ assertEquals(13, formatter.getRememberedPosition());
+ assertEquals("165025322222", formatter.inputDigit('2'));
+ assertEquals(10, formatter.getRememberedPosition());
+ assertEquals("1650253222222", formatter.inputDigit('2'));
+ assertEquals(10, formatter.getRememberedPosition());
+
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("16", formatter.inputDigitAndRememberPosition('6'));
+ assertEquals(2, formatter.getRememberedPosition());
+ assertEquals("1 65", formatter.inputDigit('5'));
+ assertEquals("1 650", formatter.inputDigit('0'));
+ assertEquals(3, formatter.getRememberedPosition());
+ assertEquals("1 650 2", formatter.inputDigit('2'));
+ assertEquals("1 650 25", formatter.inputDigit('5'));
+ assertEquals(3, formatter.getRememberedPosition());
+ assertEquals("1 650 253", formatter.inputDigit('3'));
+ assertEquals("1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("1 650 253 22", formatter.inputDigit('2'));
+ assertEquals(3, formatter.getRememberedPosition());
+ assertEquals("1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("1 650 253 2222", formatter.inputDigit('2'));
+ assertEquals("165025322222", formatter.inputDigit('2'));
+ assertEquals(2, formatter.getRememberedPosition());
+ assertEquals("1650253222222", formatter.inputDigit('2'));
+ assertEquals(2, formatter.getRememberedPosition());
+
+ formatter.clear();
+ assertEquals("6", formatter.inputDigit('6'));
+ assertEquals("65", formatter.inputDigit('5'));
+ assertEquals("650", formatter.inputDigit('0'));
+ assertEquals("650 2", formatter.inputDigit('2'));
+ assertEquals("650 25", formatter.inputDigit('5'));
+ assertEquals("650 253", formatter.inputDigit('3'));
+ assertEquals("650 2532", formatter.inputDigitAndRememberPosition('2'));
+ assertEquals(8, formatter.getRememberedPosition());
+ assertEquals("650 253 22", formatter.inputDigit('2'));
+ assertEquals(9, formatter.getRememberedPosition());
+ assertEquals("650 253 222", formatter.inputDigit('2'));
+ // No more formatting when semicolon is entered.
+ assertEquals("650253222;", formatter.inputDigit(';'));
+ assertEquals(7, formatter.getRememberedPosition());
+ assertEquals("650253222;2", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("6", formatter.inputDigit('6'));
+ assertEquals("65", formatter.inputDigit('5'));
+ assertEquals("650", formatter.inputDigit('0'));
+ // No more formatting when users choose to do their own formatting.
+ assertEquals("650-", formatter.inputDigit('-'));
+ assertEquals("650-2", formatter.inputDigitAndRememberPosition('2'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("650-25", formatter.inputDigit('5'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("650-253", formatter.inputDigit('3'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("650-253-", formatter.inputDigit('-'));
+ assertEquals("650-253-2", formatter.inputDigit('2'));
+ assertEquals("650-253-22", formatter.inputDigit('2'));
+ assertEquals("650-253-222", formatter.inputDigit('2'));
+ assertEquals("650-253-2222", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011 ", formatter.inputDigit('1'));
+ assertEquals("011 4", formatter.inputDigitAndRememberPosition('4'));
+ assertEquals("011 48 ", formatter.inputDigit('8'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("011 48 8", formatter.inputDigit('8'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("011 48 88", formatter.inputDigit('8'));
+ assertEquals("011 48 88 1", formatter.inputDigit('1'));
+ assertEquals("011 48 88 12", formatter.inputDigit('2'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("011 48 88 123", formatter.inputDigit('3'));
+ assertEquals("011 48 88 123 1", formatter.inputDigit('1'));
+ assertEquals("011 48 88 123 12", formatter.inputDigit('2'));
+ assertEquals("011 48 88 123 12 1", formatter.inputDigit('1'));
+ assertEquals("011 48 88 123 12 12", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+1", formatter.inputDigit('1'));
+ assertEquals("+1 6", formatter.inputDigitAndRememberPosition('6'));
+ assertEquals("+1 65", formatter.inputDigit('5'));
+ assertEquals("+1 650", formatter.inputDigit('0'));
+ assertEquals(4, formatter.getRememberedPosition());
+ assertEquals("+1 650 2", formatter.inputDigit('2'));
+ assertEquals(4, formatter.getRememberedPosition());
+ assertEquals("+1 650 25", formatter.inputDigit('5'));
+ assertEquals("+1 650 253", formatter.inputDigitAndRememberPosition('3'));
+ assertEquals("+1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 222", formatter.inputDigit('2'));
+ assertEquals(10, formatter.getRememberedPosition());
+
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+1", formatter.inputDigit('1'));
+ assertEquals("+1 6", formatter.inputDigitAndRememberPosition('6'));
+ assertEquals("+1 65", formatter.inputDigit('5'));
+ assertEquals("+1 650", formatter.inputDigit('0'));
+ assertEquals(4, formatter.getRememberedPosition());
+ assertEquals("+1 650 2", formatter.inputDigit('2'));
+ assertEquals(4, formatter.getRememberedPosition());
+ assertEquals("+1 650 25", formatter.inputDigit('5'));
+ assertEquals("+1 650 253", formatter.inputDigit('3'));
+ assertEquals("+1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("+1650253222;", formatter.inputDigit(';'));
+ assertEquals(3, formatter.getRememberedPosition());
+ }
+
+ public void testAYTFGBFixedLine() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.GB);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("020", formatter.inputDigit('0'));
+ assertEquals("020 7", formatter.inputDigitAndRememberPosition('7'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("020 70", formatter.inputDigit('0'));
+ assertEquals("020 703", formatter.inputDigit('3'));
+ assertEquals(5, formatter.getRememberedPosition());
+ assertEquals("020 7031", formatter.inputDigit('1'));
+ assertEquals("020 7031 3", formatter.inputDigit('3'));
+ assertEquals("020 7031 30", formatter.inputDigit('0'));
+ assertEquals("020 7031 300", formatter.inputDigit('0'));
+ assertEquals("020 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFGBTollFree() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.GB);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("08", formatter.inputDigit('8'));
+ assertEquals("080", formatter.inputDigit('0'));
+ assertEquals("080 7", formatter.inputDigit('7'));
+ assertEquals("080 70", formatter.inputDigit('0'));
+ assertEquals("080 703", formatter.inputDigit('3'));
+ assertEquals("080 7031", formatter.inputDigit('1'));
+ assertEquals("080 7031 3", formatter.inputDigit('3'));
+ assertEquals("080 7031 30", formatter.inputDigit('0'));
+ assertEquals("080 7031 300", formatter.inputDigit('0'));
+ assertEquals("080 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFGBPremiumRate() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.GB);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("09", formatter.inputDigit('9'));
+ assertEquals("090", formatter.inputDigit('0'));
+ assertEquals("090 7", formatter.inputDigit('7'));
+ assertEquals("090 70", formatter.inputDigit('0'));
+ assertEquals("090 703", formatter.inputDigit('3'));
+ assertEquals("090 7031", formatter.inputDigit('1'));
+ assertEquals("090 7031 3", formatter.inputDigit('3'));
+ assertEquals("090 7031 30", formatter.inputDigit('0'));
+ assertEquals("090 7031 300", formatter.inputDigit('0'));
+ assertEquals("090 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFNZMobile() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.NZ);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("021", formatter.inputDigit('1'));
+ assertEquals("02-11", formatter.inputDigit('1'));
+ assertEquals("02-112", formatter.inputDigit('2'));
+ // Note the unittest is using fake metadata which might produce non-ideal results.
+ assertEquals("02-112 3", formatter.inputDigit('3'));
+ assertEquals("02-112 34", formatter.inputDigit('4'));
+ assertEquals("02-112 345", formatter.inputDigit('5'));
+ assertEquals("02-112 3456", formatter.inputDigit('6'));
+ }
+
+ public void testAYTFDE() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.DE);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("03", formatter.inputDigit('3'));
+ assertEquals("030", formatter.inputDigit('0'));
+ assertEquals("030/1", formatter.inputDigit('1'));
+ assertEquals("030/12", formatter.inputDigit('2'));
+ assertEquals("030/123", formatter.inputDigit('3'));
+ assertEquals("030/1234", formatter.inputDigit('4'));
+
+ // 04134 1234
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("04", formatter.inputDigit('4'));
+ assertEquals("041", formatter.inputDigit('1'));
+ assertEquals("041 3", formatter.inputDigit('3'));
+ assertEquals("041 34", formatter.inputDigit('4'));
+ assertEquals("04134 1", formatter.inputDigit('1'));
+ assertEquals("04134 12", formatter.inputDigit('2'));
+ assertEquals("04134 123", formatter.inputDigit('3'));
+ assertEquals("04134 1234", formatter.inputDigit('4'));
+
+ // 08021 2345
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("08", formatter.inputDigit('8'));
+ assertEquals("080", formatter.inputDigit('0'));
+ assertEquals("080 2", formatter.inputDigit('2'));
+ assertEquals("080 21", formatter.inputDigit('1'));
+ assertEquals("08021 2", formatter.inputDigit('2'));
+ assertEquals("08021 23", formatter.inputDigit('3'));
+ assertEquals("08021 234", formatter.inputDigit('4'));
+ assertEquals("08021 2345", formatter.inputDigit('5'));
+
+ // 00 1 650 253 2250
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("00 1 ", formatter.inputDigit('1'));
+ assertEquals("00 1 6", formatter.inputDigit('6'));
+ assertEquals("00 1 65", formatter.inputDigit('5'));
+ assertEquals("00 1 650", formatter.inputDigit('0'));
+ assertEquals("00 1 650 2", formatter.inputDigit('2'));
+ assertEquals("00 1 650 25", formatter.inputDigit('5'));
+ assertEquals("00 1 650 253", formatter.inputDigit('3'));
+ assertEquals("00 1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("00 1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("00 1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("00 1 650 253 2222", formatter.inputDigit('2'));
+ }
+
+ public void testAYTFAR() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.AR);
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011", formatter.inputDigit('1'));
+ assertEquals("011 7", formatter.inputDigit('7'));
+ assertEquals("011 70", formatter.inputDigit('0'));
+ assertEquals("011 703", formatter.inputDigit('3'));
+ assertEquals("011 7031", formatter.inputDigit('1'));
+ assertEquals("011 7031-3", formatter.inputDigit('3'));
+ assertEquals("011 7031-30", formatter.inputDigit('0'));
+ assertEquals("011 7031-300", formatter.inputDigit('0'));
+ assertEquals("011 7031-3000", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFARMobile() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.AR);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+54 ", formatter.inputDigit('4'));
+ assertEquals("+54 9", formatter.inputDigit('9'));
+ assertEquals("+54 91", formatter.inputDigit('1'));
+ assertEquals("+54 9 11", formatter.inputDigit('1'));
+ assertEquals("+54 9 11 2", formatter.inputDigit('2'));
+ assertEquals("+54 9 11 23", formatter.inputDigit('3'));
+ assertEquals("+54 9 11 231", formatter.inputDigit('1'));
+ assertEquals("+54 9 11 2312", formatter.inputDigit('2'));
+ assertEquals("+54 9 11 2312 1", formatter.inputDigit('1'));
+ assertEquals("+54 9 11 2312 12", formatter.inputDigit('2'));
+ assertEquals("+54 9 11 2312 123", formatter.inputDigit('3'));
+ assertEquals("+54 9 11 2312 1234", formatter.inputDigit('4'));
+ }
+
+ public void testAYTFKR() {
+ // +82 51 234 5678
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.KR);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+82 ", formatter.inputDigit('2'));
+ assertEquals("+82 5", formatter.inputDigit('5'));
+ assertEquals("+82 51", formatter.inputDigit('1'));
+ assertEquals("+82 51-2", formatter.inputDigit('2'));
+ assertEquals("+82 51-23", formatter.inputDigit('3'));
+ assertEquals("+82 51-234", formatter.inputDigit('4'));
+ assertEquals("+82 51-234-5", formatter.inputDigit('5'));
+ assertEquals("+82 51-234-56", formatter.inputDigit('6'));
+ assertEquals("+82 51-234-567", formatter.inputDigit('7'));
+ assertEquals("+82 51-234-5678", formatter.inputDigit('8'));
+
+ // +82 2 531 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+82 ", formatter.inputDigit('2'));
+ assertEquals("+82 2", formatter.inputDigit('2'));
+ assertEquals("+82 25", formatter.inputDigit('5'));
+ assertEquals("+82 2-53", formatter.inputDigit('3'));
+ assertEquals("+82 2-531", formatter.inputDigit('1'));
+ assertEquals("+82 2-531-5", formatter.inputDigit('5'));
+ assertEquals("+82 2-531-56", formatter.inputDigit('6'));
+ assertEquals("+82 2-531-567", formatter.inputDigit('7'));
+ assertEquals("+82 2-531-5678", formatter.inputDigit('8'));
+
+ // +82 2 3665 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+82 ", formatter.inputDigit('2'));
+ assertEquals("+82 2", formatter.inputDigit('2'));
+ assertEquals("+82 23", formatter.inputDigit('3'));
+ assertEquals("+82 2-36", formatter.inputDigit('6'));
+ assertEquals("+82 2-366", formatter.inputDigit('6'));
+ assertEquals("+82 2-3665", formatter.inputDigit('5'));
+ assertEquals("+82 2-3665-5", formatter.inputDigit('5'));
+ assertEquals("+82 2-3665-56", formatter.inputDigit('6'));
+ assertEquals("+82 2-3665-567", formatter.inputDigit('7'));
+ assertEquals("+82 2-3665-5678", formatter.inputDigit('8'));
+
+ // 02-114
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("021", formatter.inputDigit('1'));
+ assertEquals("02-11", formatter.inputDigit('1'));
+ assertEquals("02-114", formatter.inputDigit('4'));
+
+ // 02-1300
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("021", formatter.inputDigit('1'));
+ assertEquals("02-13", formatter.inputDigit('3'));
+ assertEquals("02-130", formatter.inputDigit('0'));
+ assertEquals("02-1300", formatter.inputDigit('0'));
+
+ // 011-456-7890
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011", formatter.inputDigit('1'));
+ assertEquals("011-4", formatter.inputDigit('4'));
+ assertEquals("011-45", formatter.inputDigit('5'));
+ assertEquals("011-456", formatter.inputDigit('6'));
+ assertEquals("011-456-7", formatter.inputDigit('7'));
+ assertEquals("011-456-78", formatter.inputDigit('8'));
+ assertEquals("011-456-789", formatter.inputDigit('9'));
+ assertEquals("011-456-7890", formatter.inputDigit('0'));
+
+ // 011-9876-7890
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011", formatter.inputDigit('1'));
+ assertEquals("011-9", formatter.inputDigit('9'));
+ assertEquals("011-98", formatter.inputDigit('8'));
+ assertEquals("011-987", formatter.inputDigit('7'));
+ assertEquals("011-9876", formatter.inputDigit('6'));
+ assertEquals("011-9876-7", formatter.inputDigit('7'));
+ assertEquals("011-9876-78", formatter.inputDigit('8'));
+ assertEquals("011-9876-789", formatter.inputDigit('9'));
+ assertEquals("011-9876-7890", formatter.inputDigit('0'));
+ }
+
+ public void testAYTF_MX() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.MX);
+
+ // +52 800 123 4567
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 8", formatter.inputDigit('8'));
+ assertEquals("+52 80", formatter.inputDigit('0'));
+ assertEquals("+52 800", formatter.inputDigit('0'));
+ assertEquals("+52 800 1", formatter.inputDigit('1'));
+ assertEquals("+52 800 12", formatter.inputDigit('2'));
+ assertEquals("+52 800 123", formatter.inputDigit('3'));
+ assertEquals("+52 800 123 4", formatter.inputDigit('4'));
+ assertEquals("+52 800 123 45", formatter.inputDigit('5'));
+ assertEquals("+52 800 123 456", formatter.inputDigit('6'));
+ assertEquals("+52 800 123 4567", formatter.inputDigit('7'));
+
+ // +52 55 1234 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 5", formatter.inputDigit('5'));
+ assertEquals("+52 55", formatter.inputDigit('5'));
+ assertEquals("+52 55 1", formatter.inputDigit('1'));
+ assertEquals("+52 55 12", formatter.inputDigit('2'));
+ assertEquals("+52 55 123", formatter.inputDigit('3'));
+ assertEquals("+52 55 1234", formatter.inputDigit('4'));
+ assertEquals("+52 55 1234 5", formatter.inputDigit('5'));
+ assertEquals("+52 55 1234 56", formatter.inputDigit('6'));
+ assertEquals("+52 55 1234 567", formatter.inputDigit('7'));
+ assertEquals("+52 55 1234 5678", formatter.inputDigit('8'));
+
+ // +52 212 345 6789
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 2", formatter.inputDigit('2'));
+ assertEquals("+52 21", formatter.inputDigit('1'));
+ assertEquals("+52 212", formatter.inputDigit('2'));
+ assertEquals("+52 212 3", formatter.inputDigit('3'));
+ assertEquals("+52 212 34", formatter.inputDigit('4'));
+ assertEquals("+52 212 345", formatter.inputDigit('5'));
+ assertEquals("+52 212 345 6", formatter.inputDigit('6'));
+ assertEquals("+52 212 345 67", formatter.inputDigit('7'));
+ assertEquals("+52 212 345 678", formatter.inputDigit('8'));
+ assertEquals("+52 212 345 6789", formatter.inputDigit('9'));
+
+ // +52 1 55 1234 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 1", formatter.inputDigit('1'));
+ assertEquals("+52 15", formatter.inputDigit('5'));
+ assertEquals("+52 1 55", formatter.inputDigit('5'));
+ assertEquals("+52 1 55 1", formatter.inputDigit('1'));
+ assertEquals("+52 1 55 12", formatter.inputDigit('2'));
+ assertEquals("+52 1 55 123", formatter.inputDigit('3'));
+ assertEquals("+52 1 55 1234", formatter.inputDigit('4'));
+ assertEquals("+52 1 55 1234 5", formatter.inputDigit('5'));
+ assertEquals("+52 1 55 1234 56", formatter.inputDigit('6'));
+ assertEquals("+52 1 55 1234 567", formatter.inputDigit('7'));
+ assertEquals("+52 1 55 1234 5678", formatter.inputDigit('8'));
+
+ // +52 1 541 234 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 1", formatter.inputDigit('1'));
+ assertEquals("+52 15", formatter.inputDigit('5'));
+ assertEquals("+52 1 54", formatter.inputDigit('4'));
+ assertEquals("+52 1 541", formatter.inputDigit('1'));
+ assertEquals("+52 1 541 2", formatter.inputDigit('2'));
+ assertEquals("+52 1 541 23", formatter.inputDigit('3'));
+ assertEquals("+52 1 541 234", formatter.inputDigit('4'));
+ assertEquals("+52 1 541 234 5", formatter.inputDigit('5'));
+ assertEquals("+52 1 541 234 56", formatter.inputDigit('6'));
+ assertEquals("+52 1 541 234 567", formatter.inputDigit('7'));
+ 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);
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+81 ", formatter.inputDigit('1'));
+ assertEquals("+81 5", formatter.inputDigit('5'));
+ assertEquals("+81 50", formatter.inputDigit('0'));
+ assertEquals("+81 50 2", formatter.inputDigit('2'));
+ assertEquals("+81 50 23", formatter.inputDigit('3'));
+ assertEquals("+81 50 234", formatter.inputDigit('4'));
+ assertEquals("+81 50 2345", formatter.inputDigit('5'));
+ assertEquals("+81 50 2345 6", formatter.inputDigit('6'));
+ assertEquals("+81 50 2345 67", formatter.inputDigit('7'));
+ assertEquals("+81 50 2345 678", formatter.inputDigit('8'));
+ assertEquals("+81 50 2345 6789", formatter.inputDigit('9'));
+
+ // +81 222 12 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+81 ", formatter.inputDigit('1'));
+ assertEquals("+81 2", formatter.inputDigit('2'));
+ assertEquals("+81 22", formatter.inputDigit('2'));
+ assertEquals("+81 22 2", formatter.inputDigit('2'));
+ assertEquals("+81 22 21", formatter.inputDigit('1'));
+ assertEquals("+81 2221 2", formatter.inputDigit('2'));
+ assertEquals("+81 222 12 5", formatter.inputDigit('5'));
+ assertEquals("+81 222 12 56", formatter.inputDigit('6'));
+ assertEquals("+81 222 12 567", formatter.inputDigit('7'));
+ assertEquals("+81 222 12 5678", formatter.inputDigit('8'));
+
+ // 011113
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011", formatter.inputDigit('1'));
+ assertEquals("011 1", formatter.inputDigit('1'));
+ assertEquals("011 11", formatter.inputDigit('1'));
+ assertEquals("011113", formatter.inputDigit('3'));
+
+ // +81 3332 2 5678
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+81 ", formatter.inputDigit('1'));
+ assertEquals("+81 3", formatter.inputDigit('3'));
+ assertEquals("+81 33", formatter.inputDigit('3'));
+ assertEquals("+81 33 3", formatter.inputDigit('3'));
+ assertEquals("+81 3332", formatter.inputDigit('2'));
+ assertEquals("+81 3332 2", formatter.inputDigit('2'));
+ assertEquals("+81 3332 2 5", formatter.inputDigit('5'));
+ assertEquals("+81 3332 2 56", formatter.inputDigit('6'));
+ assertEquals("+81 3332 2 567", formatter.inputDigit('7'));
+ assertEquals("+81 3332 2 5678", formatter.inputDigit('8'));
+ }
+
+ public void testAYTFLongIDD_AU() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.AU);
+ // 0011 1 650 253 2250
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("001", formatter.inputDigit('1'));
+ assertEquals("0011", formatter.inputDigit('1'));
+ assertEquals("0011 1 ", formatter.inputDigit('1'));
+ assertEquals("0011 1 6", formatter.inputDigit('6'));
+ assertEquals("0011 1 65", formatter.inputDigit('5'));
+ assertEquals("0011 1 650", formatter.inputDigit('0'));
+ assertEquals("0011 1 650 2", formatter.inputDigit('2'));
+ assertEquals("0011 1 650 25", formatter.inputDigit('5'));
+ assertEquals("0011 1 650 253", formatter.inputDigit('3'));
+ assertEquals("0011 1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("0011 1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("0011 1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("0011 1 650 253 2222", formatter.inputDigit('2'));
+
+ // 0011 81 3332 2 5678
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("001", formatter.inputDigit('1'));
+ assertEquals("0011", formatter.inputDigit('1'));
+ assertEquals("00118", formatter.inputDigit('8'));
+ assertEquals("0011 81 ", formatter.inputDigit('1'));
+ assertEquals("0011 81 3", formatter.inputDigit('3'));
+ assertEquals("0011 81 33", formatter.inputDigit('3'));
+ assertEquals("0011 81 33 3", formatter.inputDigit('3'));
+ assertEquals("0011 81 3332", formatter.inputDigit('2'));
+ assertEquals("0011 81 3332 2", formatter.inputDigit('2'));
+ assertEquals("0011 81 3332 2 5", formatter.inputDigit('5'));
+ assertEquals("0011 81 3332 2 56", formatter.inputDigit('6'));
+ assertEquals("0011 81 3332 2 567", formatter.inputDigit('7'));
+ assertEquals("0011 81 3332 2 5678", formatter.inputDigit('8'));
+
+ // 0011 244 250 253 222
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("001", formatter.inputDigit('1'));
+ assertEquals("0011", formatter.inputDigit('1'));
+ assertEquals("00112", formatter.inputDigit('2'));
+ assertEquals("001124", formatter.inputDigit('4'));
+ assertEquals("0011 244 ", formatter.inputDigit('4'));
+ assertEquals("0011 244 2", formatter.inputDigit('2'));
+ assertEquals("0011 244 25", formatter.inputDigit('5'));
+ assertEquals("0011 244 250", formatter.inputDigit('0'));
+ assertEquals("0011 244 250 2", formatter.inputDigit('2'));
+ assertEquals("0011 244 250 25", formatter.inputDigit('5'));
+ assertEquals("0011 244 250 253", formatter.inputDigit('3'));
+ assertEquals("0011 244 250 253 2", formatter.inputDigit('2'));
+ assertEquals("0011 244 250 253 22", formatter.inputDigit('2'));
+ assertEquals("0011 244 250 253 222", formatter.inputDigit('2'));
+ }
+
+ public void testAYTFLongIDD_KR() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.KR);
+ // 00300 1 650 253 2222
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("003", formatter.inputDigit('3'));
+ assertEquals("0030", formatter.inputDigit('0'));
+ assertEquals("00300", formatter.inputDigit('0'));
+ assertEquals("00300 1 ", formatter.inputDigit('1'));
+ assertEquals("00300 1 6", formatter.inputDigit('6'));
+ assertEquals("00300 1 65", formatter.inputDigit('5'));
+ assertEquals("00300 1 650", formatter.inputDigit('0'));
+ assertEquals("00300 1 650 2", formatter.inputDigit('2'));
+ assertEquals("00300 1 650 25", formatter.inputDigit('5'));
+ assertEquals("00300 1 650 253", formatter.inputDigit('3'));
+ assertEquals("00300 1 650 253 2", formatter.inputDigit('2'));
+ assertEquals("00300 1 650 253 22", formatter.inputDigit('2'));
+ assertEquals("00300 1 650 253 222", formatter.inputDigit('2'));
+ assertEquals("00300 1 650 253 2222", formatter.inputDigit('2'));
+ }
+
+ public void testAYTFLongNDD_KR() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.KR);
+ // 08811-9876-7890
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("08", formatter.inputDigit('8'));
+ assertEquals("088", formatter.inputDigit('8'));
+ assertEquals("0881", formatter.inputDigit('1'));
+ assertEquals("08811", formatter.inputDigit('1'));
+ assertEquals("08811-9", formatter.inputDigit('9'));
+ assertEquals("08811-98", formatter.inputDigit('8'));
+ assertEquals("08811-987", formatter.inputDigit('7'));
+ assertEquals("08811-9876", formatter.inputDigit('6'));
+ assertEquals("08811-9876-7", formatter.inputDigit('7'));
+ assertEquals("08811-9876-78", formatter.inputDigit('8'));
+ assertEquals("08811-9876-789", formatter.inputDigit('9'));
+ assertEquals("08811-9876-7890", formatter.inputDigit('0'));
+
+ // 08500 11-9876-7890
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("08", formatter.inputDigit('8'));
+ assertEquals("085", formatter.inputDigit('5'));
+ assertEquals("0850", formatter.inputDigit('0'));
+ assertEquals("08500 ", formatter.inputDigit('0'));
+ assertEquals("08500 1", formatter.inputDigit('1'));
+ assertEquals("08500 11", formatter.inputDigit('1'));
+ assertEquals("08500 11-9", formatter.inputDigit('9'));
+ assertEquals("08500 11-98", formatter.inputDigit('8'));
+ assertEquals("08500 11-987", formatter.inputDigit('7'));
+ assertEquals("08500 11-9876", formatter.inputDigit('6'));
+ assertEquals("08500 11-9876-7", formatter.inputDigit('7'));
+ assertEquals("08500 11-9876-78", formatter.inputDigit('8'));
+ assertEquals("08500 11-9876-789", formatter.inputDigit('9'));
+ assertEquals("08500 11-9876-7890", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFLongNDD_SG() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.SG);
+ // 777777 9876 7890
+ assertEquals("7", formatter.inputDigit('7'));
+ assertEquals("77", formatter.inputDigit('7'));
+ assertEquals("777", formatter.inputDigit('7'));
+ assertEquals("7777", formatter.inputDigit('7'));
+ assertEquals("77777", formatter.inputDigit('7'));
+ assertEquals("777777 ", formatter.inputDigit('7'));
+ assertEquals("777777 9", formatter.inputDigit('9'));
+ assertEquals("777777 98", formatter.inputDigit('8'));
+ assertEquals("777777 987", formatter.inputDigit('7'));
+ assertEquals("777777 9876", formatter.inputDigit('6'));
+ assertEquals("777777 9876 7", formatter.inputDigit('7'));
+ assertEquals("777777 9876 78", formatter.inputDigit('8'));
+ assertEquals("777777 9876 789", formatter.inputDigit('9'));
+ assertEquals("777777 9876 7890", formatter.inputDigit('0'));
+ }
+
+ public void testAYTFShortNumberFormattingFix_AU() {
+ // For Australia, the national prefix is not optional when formatting.
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.AU);
+
+ // 1234567890 - For leading digit 1, the national prefix formatting rule has first group only.
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("12", formatter.inputDigit('2'));
+ assertEquals("123", formatter.inputDigit('3'));
+ assertEquals("1234", formatter.inputDigit('4'));
+ assertEquals("1234 5", formatter.inputDigit('5'));
+ assertEquals("1234 56", formatter.inputDigit('6'));
+ assertEquals("1234 567", formatter.inputDigit('7'));
+ assertEquals("1234 567 8", formatter.inputDigit('8'));
+ assertEquals("1234 567 89", formatter.inputDigit('9'));
+ assertEquals("1234 567 890", formatter.inputDigit('0'));
+
+ // +61 1234 567 890 - Test the same number, but with the country code.
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+6", formatter.inputDigit('6'));
+ assertEquals("+61 ", formatter.inputDigit('1'));
+ assertEquals("+61 1", formatter.inputDigit('1'));
+ assertEquals("+61 12", formatter.inputDigit('2'));
+ assertEquals("+61 123", formatter.inputDigit('3'));
+ assertEquals("+61 1234", formatter.inputDigit('4'));
+ assertEquals("+61 1234 5", formatter.inputDigit('5'));
+ assertEquals("+61 1234 56", formatter.inputDigit('6'));
+ assertEquals("+61 1234 567", formatter.inputDigit('7'));
+ assertEquals("+61 1234 567 8", formatter.inputDigit('8'));
+ assertEquals("+61 1234 567 89", formatter.inputDigit('9'));
+ assertEquals("+61 1234 567 890", formatter.inputDigit('0'));
+
+ // 212345678 - For leading digit 2, the national prefix formatting rule puts the national prefix
+ // before the first group.
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("021", formatter.inputDigit('1'));
+ assertEquals("02 12", formatter.inputDigit('2'));
+ assertEquals("02 123", formatter.inputDigit('3'));
+ assertEquals("02 1234", formatter.inputDigit('4'));
+ assertEquals("02 1234 5", formatter.inputDigit('5'));
+ assertEquals("02 1234 56", formatter.inputDigit('6'));
+ assertEquals("02 1234 567", formatter.inputDigit('7'));
+ assertEquals("02 1234 5678", formatter.inputDigit('8'));
+
+ // 212345678 - Test the same number, but without the leading 0.
+ formatter.clear();
+ assertEquals("2", formatter.inputDigit('2'));
+ assertEquals("21", formatter.inputDigit('1'));
+ assertEquals("212", formatter.inputDigit('2'));
+ assertEquals("2123", formatter.inputDigit('3'));
+ assertEquals("21234", formatter.inputDigit('4'));
+ assertEquals("212345", formatter.inputDigit('5'));
+ assertEquals("2123456", formatter.inputDigit('6'));
+ assertEquals("21234567", formatter.inputDigit('7'));
+ assertEquals("212345678", formatter.inputDigit('8'));
+
+ // +61 2 1234 5678 - Test the same number, but with the country code.
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+6", formatter.inputDigit('6'));
+ assertEquals("+61 ", formatter.inputDigit('1'));
+ assertEquals("+61 2", formatter.inputDigit('2'));
+ assertEquals("+61 21", formatter.inputDigit('1'));
+ assertEquals("+61 2 12", formatter.inputDigit('2'));
+ assertEquals("+61 2 123", formatter.inputDigit('3'));
+ assertEquals("+61 2 1234", formatter.inputDigit('4'));
+ assertEquals("+61 2 1234 5", formatter.inputDigit('5'));
+ assertEquals("+61 2 1234 56", formatter.inputDigit('6'));
+ assertEquals("+61 2 1234 567", formatter.inputDigit('7'));
+ assertEquals("+61 2 1234 5678", formatter.inputDigit('8'));
+ }
+
+ public void testAYTFShortNumberFormattingFix_KR() {
+ // For Korea, the national prefix is not optional when formatting, and the national prefix
+ // formatting rule doesn't consist of only the first group.
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.KR);
+
+ // 111
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("11", formatter.inputDigit('1'));
+ assertEquals("111", formatter.inputDigit('1'));
+
+ // 114
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("11", formatter.inputDigit('1'));
+ assertEquals("114", formatter.inputDigit('4'));
+
+ // 13121234 - Test a mobile number without the national prefix. Even though it is not an
+ // emergency number, it should be formatted as a block.
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("13", formatter.inputDigit('3'));
+ assertEquals("131", formatter.inputDigit('1'));
+ assertEquals("1312", formatter.inputDigit('2'));
+ assertEquals("13121", formatter.inputDigit('1'));
+ assertEquals("131212", formatter.inputDigit('2'));
+ assertEquals("1312123", formatter.inputDigit('3'));
+ assertEquals("13121234", formatter.inputDigit('4'));
+
+ // +82 131-2-1234 - Test the same number, but with the country code.
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+82 ", formatter.inputDigit('2'));
+ assertEquals("+82 1", formatter.inputDigit('1'));
+ assertEquals("+82 13", formatter.inputDigit('3'));
+ assertEquals("+82 131", formatter.inputDigit('1'));
+ assertEquals("+82 131-2", formatter.inputDigit('2'));
+ assertEquals("+82 131-2-1", formatter.inputDigit('1'));
+ assertEquals("+82 131-2-12", formatter.inputDigit('2'));
+ assertEquals("+82 131-2-123", formatter.inputDigit('3'));
+ assertEquals("+82 131-2-1234", formatter.inputDigit('4'));
+ }
+
+ public void testAYTFShortNumberFormattingFix_MX() {
+ // For Mexico, the national prefix is optional when formatting.
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.MX);
+
+ // 911
+ assertEquals("9", formatter.inputDigit('9'));
+ assertEquals("91", formatter.inputDigit('1'));
+ assertEquals("911", formatter.inputDigit('1'));
+
+ // 800 123 4567 - Test a toll-free number, which should have a formatting rule applied to it
+ // even though it doesn't begin with the national prefix.
+ formatter.clear();
+ 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 123 4", formatter.inputDigit('4'));
+ assertEquals("800 123 45", formatter.inputDigit('5'));
+ assertEquals("800 123 456", formatter.inputDigit('6'));
+ assertEquals("800 123 4567", formatter.inputDigit('7'));
+
+ // +52 800 123 4567 - Test the same number, but with the country code.
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+5", formatter.inputDigit('5'));
+ assertEquals("+52 ", formatter.inputDigit('2'));
+ assertEquals("+52 8", formatter.inputDigit('8'));
+ assertEquals("+52 80", formatter.inputDigit('0'));
+ assertEquals("+52 800", formatter.inputDigit('0'));
+ assertEquals("+52 800 1", formatter.inputDigit('1'));
+ assertEquals("+52 800 12", formatter.inputDigit('2'));
+ assertEquals("+52 800 123", formatter.inputDigit('3'));
+ assertEquals("+52 800 123 4", formatter.inputDigit('4'));
+ assertEquals("+52 800 123 45", formatter.inputDigit('5'));
+ assertEquals("+52 800 123 456", formatter.inputDigit('6'));
+ assertEquals("+52 800 123 4567", formatter.inputDigit('7'));
+ }
+
+ public void testAYTFNoNationalPrefix() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.IT);
+
+ assertEquals("3", formatter.inputDigit('3'));
+ assertEquals("33", formatter.inputDigit('3'));
+ assertEquals("333", formatter.inputDigit('3'));
+ assertEquals("333 3", formatter.inputDigit('3'));
+ assertEquals("333 33", formatter.inputDigit('3'));
+ assertEquals("333 333", formatter.inputDigit('3'));
+ }
+
+ public void testAYTFNoNationalPrefixFormattingRule() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.AO);
+
+ assertEquals("3", formatter.inputDigit('3'));
+ assertEquals("33", formatter.inputDigit('3'));
+ assertEquals("333", formatter.inputDigit('3'));
+ assertEquals("333 3", formatter.inputDigit('3'));
+ assertEquals("333 33", formatter.inputDigit('3'));
+ assertEquals("333 333", formatter.inputDigit('3'));
+ }
+
+ public void testAYTFShortNumberFormattingFix_US() {
+ // For the US, an initial 1 is treated specially.
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.US);
+
+ // 101 - Test that the initial 1 is not treated as a national prefix.
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("10", formatter.inputDigit('0'));
+ assertEquals("101", formatter.inputDigit('1'));
+
+ // 112 - Test that the initial 1 is not treated as a national prefix.
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("11", formatter.inputDigit('1'));
+ assertEquals("112", formatter.inputDigit('2'));
+
+ // 122 - Test that the initial 1 is treated as a national prefix.
+ formatter.clear();
+ assertEquals("1", formatter.inputDigit('1'));
+ assertEquals("12", formatter.inputDigit('2'));
+ assertEquals("1 22", formatter.inputDigit('2'));
+ }
+
+ public void testAYTFClearNDDAfterIDDExtraction() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.KR);
+
+ // Check that when we have successfully extracted an IDD, the previously extracted NDD is
+ // cleared since it is no longer valid.
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("00", formatter.inputDigit('0'));
+ assertEquals("007", formatter.inputDigit('7'));
+ assertEquals("0070", formatter.inputDigit('0'));
+ assertEquals("00700", formatter.inputDigit('0'));
+ assertEquals("0", formatter.getExtractedNationalPrefix());
+
+ // Once the IDD "00700" has been extracted, it no longer makes sense for the initial "0" to be
+ // treated as an NDD.
+ assertEquals("00700 1 ", formatter.inputDigit('1'));
+ assertEquals("", formatter.getExtractedNationalPrefix());
+
+ assertEquals("00700 1 2", formatter.inputDigit('2'));
+ assertEquals("00700 1 23", formatter.inputDigit('3'));
+ assertEquals("00700 1 234", formatter.inputDigit('4'));
+ assertEquals("00700 1 234 5", formatter.inputDigit('5'));
+ assertEquals("00700 1 234 56", formatter.inputDigit('6'));
+ assertEquals("00700 1 234 567", formatter.inputDigit('7'));
+ assertEquals("00700 1 234 567 8", formatter.inputDigit('8'));
+ assertEquals("00700 1 234 567 89", formatter.inputDigit('9'));
+ assertEquals("00700 1 234 567 890", formatter.inputDigit('0'));
+ assertEquals("00700 1 234 567 8901", formatter.inputDigit('1'));
+ assertEquals("00700123456789012", formatter.inputDigit('2'));
+ assertEquals("007001234567890123", formatter.inputDigit('3'));
+ assertEquals("0070012345678901234", formatter.inputDigit('4'));
+ assertEquals("00700123456789012345", formatter.inputDigit('5'));
+ assertEquals("007001234567890123456", formatter.inputDigit('6'));
+ assertEquals("0070012345678901234567", formatter.inputDigit('7'));
+ }
+
+ public void testAYTFNumberPatternsBecomingInvalidShouldNotResultInDigitLoss() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter(RegionCode.CN);
+
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+8", formatter.inputDigit('8'));
+ assertEquals("+86 ", formatter.inputDigit('6'));
+ assertEquals("+86 9", formatter.inputDigit('9'));
+ assertEquals("+86 98", formatter.inputDigit('8'));
+ assertEquals("+86 988", formatter.inputDigit('8'));
+ assertEquals("+86 988 1", formatter.inputDigit('1'));
+ // Now the number pattern is no longer valid because there are multiple leading digit patterns;
+ // when we try again to extract a country code we should ensure we use the last leading digit
+ // pattern, rather than the first one such that it *thinks* it's found a valid formatting rule
+ // again.
+ // https://code.google.com/p/libphonenumber/issues/detail?id=437
+ assertEquals("+8698812", formatter.inputDigit('2'));
+ assertEquals("+86988123", formatter.inputDigit('3'));
+ assertEquals("+869881234", formatter.inputDigit('4'));
+ assertEquals("+8698812345", formatter.inputDigit('5'));
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java b/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java
new file mode 100644
index 00000000..67612983
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/* This file is automatically generated by {@link BuildMetadataProtoFromXml}.
+ * Please don't modify it directly.
+ */
+
+package com.google.i18n.phonenumbers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CountryCodeToRegionCodeMapForTesting {
+ // A mapping from a country code to the region codes which denote the
+ // country/region represented by that country code. In the case of multiple
+ // countries sharing a calling code, such as the NANPA countries, the one
+ // indicated with "isMainCountryForCode" in the metadata should be first.
+ static Map<Integer, List<String>> getCountryCodeToRegionCodeMap() {
+ // The capacity is set to 30 as there are 23 different entries,
+ // and this offers a load factor of roughly 0.75.
+ Map<Integer, List<String>> countryCodeToRegionCodeMap =
+ new HashMap<Integer, List<String>>(30);
+
+ ArrayList<String> listWithRegionCode;
+
+ listWithRegionCode = new ArrayList<String>(4);
+ listWithRegionCode.add("US");
+ listWithRegionCode.add("BB");
+ listWithRegionCode.add("BS");
+ listWithRegionCode.add("CA");
+ countryCodeToRegionCodeMap.put(1, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("FR");
+ countryCodeToRegionCodeMap.put(33, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("HU");
+ countryCodeToRegionCodeMap.put(36, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("IT");
+ countryCodeToRegionCodeMap.put(39, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("GB");
+ listWithRegionCode.add("GG");
+ countryCodeToRegionCodeMap.put(44, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("PL");
+ countryCodeToRegionCodeMap.put(48, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("DE");
+ countryCodeToRegionCodeMap.put(49, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("MX");
+ countryCodeToRegionCodeMap.put(52, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AR");
+ countryCodeToRegionCodeMap.put(54, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BR");
+ countryCodeToRegionCodeMap.put(55, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(3);
+ listWithRegionCode.add("AU");
+ listWithRegionCode.add("CC");
+ listWithRegionCode.add("CX");
+ countryCodeToRegionCodeMap.put(61, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("NZ");
+ countryCodeToRegionCodeMap.put(64, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("SG");
+ countryCodeToRegionCodeMap.put(65, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("JP");
+ countryCodeToRegionCodeMap.put(81, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("KR");
+ countryCodeToRegionCodeMap.put(82, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("CN");
+ countryCodeToRegionCodeMap.put(86, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AO");
+ countryCodeToRegionCodeMap.put(244, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(2);
+ listWithRegionCode.add("RE");
+ listWithRegionCode.add("YT");
+ countryCodeToRegionCodeMap.put(262, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("BY");
+ countryCodeToRegionCodeMap.put(375, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AD");
+ countryCodeToRegionCodeMap.put(376, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(800, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("AE");
+ countryCodeToRegionCodeMap.put(971, listWithRegionCode);
+
+ listWithRegionCode = new ArrayList<String>(1);
+ listWithRegionCode.add("001");
+ countryCodeToRegionCodeMap.put(979, listWithRegionCode);
+
+ return countryCodeToRegionCodeMap;
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
new file mode 100644
index 00000000..b276eb9c
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Verifies all of the example numbers in the metadata are valid and of the correct type. If no
+ * example number exists for a particular type, the test still passes.
+ */
+public class ExampleNumbersTest extends TestCase {
+ private static final Logger LOGGER = Logger.getLogger(ExampleNumbersTest.class.getName());
+ private PhoneNumberUtil phoneNumberUtil =
+ PhoneNumberUtil.createInstance(PhoneNumberUtil.DEFAULT_METADATA_LOADER);
+ private ShortNumberInfo shortNumberInfo = ShortNumberInfo.getInstance();
+ private List<PhoneNumber> invalidCases = new ArrayList<PhoneNumber>();
+ private List<PhoneNumber> wrongTypeCases = new ArrayList<PhoneNumber>();
+
+ /**
+ * @param exampleNumberRequestedType type we are requesting an example number for
+ * @param possibleExpectedTypes acceptable types that this number should match, such as
+ * FIXED_LINE and FIXED_LINE_OR_MOBILE for a fixed line example number.
+ */
+ private void checkNumbersValidAndCorrectType(PhoneNumberType exampleNumberRequestedType,
+ Set<PhoneNumberType> possibleExpectedTypes) {
+ for (String regionCode : phoneNumberUtil.getSupportedRegions()) {
+ PhoneNumber exampleNumber =
+ phoneNumberUtil.getExampleNumberForType(regionCode, exampleNumberRequestedType);
+ if (exampleNumber != null) {
+ if (!phoneNumberUtil.isValidNumber(exampleNumber)) {
+ invalidCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString());
+ } else {
+ // We know the number is valid, now we check the type.
+ PhoneNumberType exampleNumberType = phoneNumberUtil.getNumberType(exampleNumber);
+ if (!possibleExpectedTypes.contains(exampleNumberType)) {
+ wrongTypeCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Wrong type for " +
+ exampleNumber.toString() +
+ ": got " + exampleNumberType);
+ LOGGER.log(Level.WARNING, "Expected types: ");
+ for (PhoneNumberType type : possibleExpectedTypes) {
+ LOGGER.log(Level.WARNING, type.toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void testFixedLine() throws Exception {
+ Set<PhoneNumberType> fixedLineTypes = EnumSet.of(PhoneNumberType.FIXED_LINE,
+ PhoneNumberType.FIXED_LINE_OR_MOBILE);
+ checkNumbersValidAndCorrectType(PhoneNumberType.FIXED_LINE, fixedLineTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testMobile() throws Exception {
+ Set<PhoneNumberType> mobileTypes = EnumSet.of(PhoneNumberType.MOBILE,
+ PhoneNumberType.FIXED_LINE_OR_MOBILE);
+ checkNumbersValidAndCorrectType(PhoneNumberType.MOBILE, mobileTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testTollFree() throws Exception {
+ Set<PhoneNumberType> tollFreeTypes = EnumSet.of(PhoneNumberType.TOLL_FREE);
+ checkNumbersValidAndCorrectType(PhoneNumberType.TOLL_FREE, tollFreeTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testPremiumRate() throws Exception {
+ Set<PhoneNumberType> premiumRateTypes = EnumSet.of(PhoneNumberType.PREMIUM_RATE);
+ checkNumbersValidAndCorrectType(PhoneNumberType.PREMIUM_RATE, premiumRateTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testVoip() throws Exception {
+ Set<PhoneNumberType> voipTypes = EnumSet.of(PhoneNumberType.VOIP);
+ checkNumbersValidAndCorrectType(PhoneNumberType.VOIP, voipTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testPager() throws Exception {
+ Set<PhoneNumberType> pagerTypes = EnumSet.of(PhoneNumberType.PAGER);
+ checkNumbersValidAndCorrectType(PhoneNumberType.PAGER, pagerTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testUan() throws Exception {
+ Set<PhoneNumberType> uanTypes = EnumSet.of(PhoneNumberType.UAN);
+ checkNumbersValidAndCorrectType(PhoneNumberType.UAN, uanTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testVoicemail() throws Exception {
+ Set<PhoneNumberType> voicemailTypes = EnumSet.of(PhoneNumberType.VOICEMAIL);
+ checkNumbersValidAndCorrectType(PhoneNumberType.VOICEMAIL, voicemailTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testSharedCost() throws Exception {
+ Set<PhoneNumberType> sharedCostTypes = EnumSet.of(PhoneNumberType.SHARED_COST);
+ checkNumbersValidAndCorrectType(PhoneNumberType.SHARED_COST, sharedCostTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testCanBeInternationallyDialled() throws Exception {
+ for (String regionCode : phoneNumberUtil.getSupportedRegions()) {
+ PhoneNumber exampleNumber = null;
+ PhoneNumberDesc desc =
+ phoneNumberUtil.getMetadataForRegion(regionCode).getNoInternationalDialling();
+ try {
+ if (desc.hasExampleNumber()) {
+ exampleNumber = phoneNumberUtil.parse(desc.getExampleNumber(), regionCode);
+ }
+ } catch (NumberParseException e) {
+ LOGGER.log(Level.SEVERE, e.toString());
+ }
+ if (exampleNumber != null && phoneNumberUtil.canBeInternationallyDialled(exampleNumber)) {
+ wrongTypeCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Number " + exampleNumber.toString()
+ + " should not be internationally diallable");
+ }
+ }
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testGlobalNetworkNumbers() throws Exception {
+ for (Integer callingCode : phoneNumberUtil.getSupportedGlobalNetworkCallingCodes()) {
+ PhoneNumber exampleNumber =
+ phoneNumberUtil.getExampleNumberForNonGeoEntity(callingCode);
+ assertNotNull("No example phone number for calling code " + callingCode, exampleNumber);
+ if (!phoneNumberUtil.isValidNumber(exampleNumber)) {
+ invalidCases.add(exampleNumber);
+ LOGGER.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString());
+ }
+ }
+ assertEquals(0, invalidCases.size());
+ }
+
+ public void testEveryRegionHasAnExampleNumber() throws Exception {
+ for (String regionCode : phoneNumberUtil.getSupportedRegions()) {
+ PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumber(regionCode);
+ assertNotNull("None found for region " + regionCode, exampleNumber);
+ }
+ }
+
+ public void testShortNumbersValidAndCorrectCost() throws Exception {
+ List<String> invalidStringCases = new ArrayList<String>();
+ for (String regionCode : shortNumberInfo.getSupportedRegions()) {
+ String exampleShortNumber = shortNumberInfo.getExampleShortNumber(regionCode);
+ if (!shortNumberInfo.isValidShortNumberForRegion(
+ phoneNumberUtil.parse(exampleShortNumber, regionCode), regionCode)) {
+ String invalidStringCase = "region_code: " + regionCode + ", national_number: " +
+ exampleShortNumber;
+ invalidStringCases.add(invalidStringCase);
+ LOGGER.log(Level.SEVERE, "Failed validation for string " + invalidStringCase);
+ }
+ PhoneNumber phoneNumber = phoneNumberUtil.parse(exampleShortNumber, regionCode);
+ if (!shortNumberInfo.isValidShortNumber(phoneNumber)) {
+ invalidCases.add(phoneNumber);
+ LOGGER.log(Level.SEVERE, "Failed validation for " + phoneNumber.toString());
+ }
+
+ for (ShortNumberInfo.ShortNumberCost cost : ShortNumberInfo.ShortNumberCost.values()) {
+ exampleShortNumber = shortNumberInfo.getExampleShortNumberForCost(regionCode, cost);
+ if (!exampleShortNumber.equals("")) {
+ if (cost != shortNumberInfo.getExpectedCostForRegion(
+ phoneNumberUtil.parse(exampleShortNumber, regionCode), regionCode)) {
+ wrongTypeCases.add(phoneNumber);
+ LOGGER.log(Level.SEVERE, "Wrong cost for " + phoneNumber.toString());
+ }
+ }
+ }
+ }
+ assertEquals(0, invalidStringCases.size());
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+
+ public void testEmergency() throws Exception {
+ int wrongTypeCounter = 0;
+ for (String regionCode : shortNumberInfo.getSupportedRegions()) {
+ PhoneNumberDesc desc =
+ MetadataManager.getShortNumberMetadataForRegion(regionCode).getEmergency();
+ if (desc.hasExampleNumber()) {
+ String exampleNumber = desc.getExampleNumber();
+ PhoneNumber phoneNumber = phoneNumberUtil.parse(exampleNumber, regionCode);
+ if (!shortNumberInfo.isPossibleShortNumberForRegion(phoneNumber, regionCode)
+ || !shortNumberInfo.isEmergencyNumber(exampleNumber, regionCode)) {
+ wrongTypeCounter++;
+ LOGGER.log(Level.SEVERE, "Emergency example number test failed for " + regionCode);
+ } else if (shortNumberInfo.getExpectedCostForRegion(phoneNumber, regionCode)
+ != ShortNumberInfo.ShortNumberCost.TOLL_FREE) {
+ wrongTypeCounter++;
+ LOGGER.log(Level.WARNING, "Emergency example number not toll free for " + regionCode);
+ }
+ }
+ }
+ assertEquals(0, wrongTypeCounter);
+ }
+
+ public void testCarrierSpecificShortNumbers() throws Exception {
+ int wrongTagCounter = 0;
+ for (String regionCode : shortNumberInfo.getSupportedRegions()) {
+ // Test the carrier-specific tag.
+ PhoneNumberDesc desc =
+ MetadataManager.getShortNumberMetadataForRegion(regionCode).getCarrierSpecific();
+ if (desc.hasExampleNumber()) {
+ String exampleNumber = desc.getExampleNumber();
+ PhoneNumber carrierSpecificNumber = phoneNumberUtil.parse(exampleNumber, regionCode);
+ if (!shortNumberInfo.isPossibleShortNumberForRegion(carrierSpecificNumber, regionCode)
+ || !shortNumberInfo.isCarrierSpecific(carrierSpecificNumber)) {
+ wrongTagCounter++;
+ LOGGER.log(Level.SEVERE, "Carrier-specific test failed for " + regionCode);
+ }
+ }
+ // TODO: Test other tags here.
+ }
+ assertEquals(0, wrongTagCounter);
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java
new file mode 100644
index 00000000..229d8f7d
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+
+import junit.framework.TestCase;
+
+/**
+ * Some basic tests to check that the phone number metadata can be correctly loaded.
+ */
+public class MetadataManagerTest extends TestCase {
+
+ public void testAlternateFormatsContainsData() throws Exception {
+ // We should have some data for Germany.
+ PhoneMetadata germanyAlternateFormats = MetadataManager.getAlternateFormatsForCountry(49);
+ assertNotNull(germanyAlternateFormats);
+ assertTrue(germanyAlternateFormats.numberFormats().size() > 0);
+ }
+
+ public void testShortNumberMetadataContainsData() throws Exception {
+ // We should have some data for France.
+ PhoneMetadata franceShortNumberMetadata = MetadataManager.getShortNumberMetadataForRegion("FR");
+ assertNotNull(franceShortNumberMetadata);
+ assertTrue(franceShortNumberMetadata.hasShortCode());
+ }
+
+ public void testAlternateFormatsFailsGracefully() throws Exception {
+ PhoneMetadata noAlternateFormats = MetadataManager.getAlternateFormatsForCountry(999);
+ assertNull(noAlternateFormats);
+ }
+
+ public void testShortNumberMetadataFailsGracefully() throws Exception {
+ PhoneMetadata noShortNumberMetadata = MetadataManager.getShortNumberMetadataForRegion("XXX");
+ assertNull(noShortNumberMetadata);
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java
new file mode 100644
index 00000000..408c759d
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 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;
+
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link PhoneNumberMatch}.
+ */
+public class PhoneNumberMatchTest extends TestCase {
+ /**
+ * Tests the value type semantics. Equality and hash code must be based on the covered range and
+ * corresponding phone number. Range and number correctness are tested by
+ * {@link PhoneNumberMatcherTest}.
+ */
+ public void testValueTypeSemantics() throws Exception {
+ PhoneNumber number = new PhoneNumber();
+ PhoneNumberMatch match1 = new PhoneNumberMatch(10, "1 800 234 45 67", number);
+ PhoneNumberMatch match2 = new PhoneNumberMatch(10, "1 800 234 45 67", number);
+
+ assertEquals(match1, match2);
+ assertEquals(match1.hashCode(), match2.hashCode());
+ assertEquals(match1.start(), match2.start());
+ assertEquals(match1.end(), match2.end());
+ assertEquals(match1.number(), match2.number());
+ assertEquals(match1.rawString(), match2.rawString());
+ assertEquals("1 800 234 45 67", match1.rawString());
+ }
+
+ /**
+ * Tests the value type semantics for matches with a null number.
+ */
+ public void testIllegalArguments() throws Exception {
+ try {
+ new PhoneNumberMatch(-110, "1 800 234 45 67", new PhoneNumber());
+ fail();
+ } catch (IllegalArgumentException e) { /* success */ }
+
+ try {
+ new PhoneNumberMatch(10, "1 800 234 45 67", null);
+ fail();
+ } catch (NullPointerException e) { /* success */ }
+
+ try {
+ new PhoneNumberMatch(10, null, new PhoneNumber());
+ fail();
+ } catch (NullPointerException e) { /* success */ }
+
+ try {
+ new PhoneNumberMatch(10, null, null);
+ fail();
+ } catch (NullPointerException e) { /* success */ }
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java
new file mode 100644
index 00000000..4a2dc11a
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java
@@ -0,0 +1,1090 @@
+/*
+ * Copyright (C) 2011 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;
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil.Leniency;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Tests for {@link PhoneNumberMatcher}. This only tests basic functionality based on test metadata.
+ *
+ * @see PhoneNumberUtilTest {@link PhoneNumberUtilTest} for the origin of the test data
+ */
+public class PhoneNumberMatcherTest extends TestMetadataTestCase {
+
+ public void testContainsMoreThanOneSlashInNationalNumber() throws Exception {
+ // A date should return true.
+ PhoneNumber number = new PhoneNumber();
+ number.setCountryCode(1);
+ number.setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY);
+ String candidate = "1/05/2013";
+ assertTrue(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ // Here, the country code source thinks it started with a country calling code, but this is not
+ // the same as the part before the slash, so it's still true.
+ number = new PhoneNumber();
+ number.setCountryCode(274);
+ number.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
+ candidate = "27/4/2013";
+ assertTrue(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ // Now it should be false, because the first slash is after the country calling code.
+ number = new PhoneNumber();
+ number.setCountryCode(49);
+ number.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+ candidate = "49/69/2013";
+ assertFalse(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ number = new PhoneNumber();
+ number.setCountryCode(49);
+ number.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN);
+ candidate = "+49/69/2013";
+ assertFalse(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ candidate = "+ 49/69/2013";
+ assertFalse(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ candidate = "+ 49/69/20/13";
+ assertTrue(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+
+ // Here, the first group is not assumed to be the country calling code, even though it is the
+ // same as it, so this should return true.
+ number = new PhoneNumber();
+ number.setCountryCode(49);
+ number.setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY);
+ candidate = "49/69/2013";
+ assertTrue(PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidate));
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseNationalNumber()}. */
+ public void testFindNationalNumber() throws Exception {
+ // same cases as in testParseNationalNumber
+ doTestFindInContext("033316005", RegionCode.NZ);
+ // ("33316005", RegionCode.NZ) is omitted since the national prefix is obligatory for these
+ // types of numbers in New Zealand.
+ // National prefix attached and some formatting present.
+ doTestFindInContext("03-331 6005", RegionCode.NZ);
+ doTestFindInContext("03 331 6005", RegionCode.NZ);
+ // Testing international prefixes.
+ // Should strip country code.
+ doTestFindInContext("0064 3 331 6005", RegionCode.NZ);
+ // Try again, but this time we have an international number with Region Code US. It should
+ // recognize the country code and parse accordingly.
+ doTestFindInContext("01164 3 331 6005", RegionCode.US);
+ doTestFindInContext("+64 3 331 6005", RegionCode.US);
+
+ doTestFindInContext("64(0)64123456", RegionCode.NZ);
+ // Check that using a "/" is fine in a phone number.
+ // Note that real Polish numbers do *not* start with a 0.
+ doTestFindInContext("0123/456789", RegionCode.PL);
+ doTestFindInContext("123-456-7890", RegionCode.US);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseWithInternationalPrefixes()}. */
+ public void testFindWithInternationalPrefixes() throws Exception {
+ doTestFindInContext("+1 (650) 333-6000", RegionCode.NZ);
+ doTestFindInContext("1-650-333-6000", RegionCode.US);
+ // Calling the US number from Singapore by using different service providers
+ // 1st test: calling using SingTel IDD service (IDD is 001)
+ doTestFindInContext("0011-650-333-6000", RegionCode.SG);
+ // 2nd test: calling using StarHub IDD service (IDD is 008)
+ doTestFindInContext("0081-650-333-6000", RegionCode.SG);
+ // 3rd test: calling using SingTel V019 service (IDD is 019)
+ doTestFindInContext("0191-650-333-6000", RegionCode.SG);
+ // Calling the US number from Poland
+ doTestFindInContext("0~01-650-333-6000", RegionCode.PL);
+ // Using "++" at the start.
+ doTestFindInContext("++1 (650) 333-6000", RegionCode.PL);
+ // Using a full-width plus sign.
+ doTestFindInContext("\uFF0B1 (650) 333-6000", RegionCode.SG);
+ // The whole number, including punctuation, is here represented in full-width form.
+ doTestFindInContext("\uFF0B\uFF11\u3000\uFF08\uFF16\uFF15\uFF10\uFF09" +
+ "\u3000\uFF13\uFF13\uFF13\uFF0D\uFF16\uFF10\uFF10\uFF10",
+ RegionCode.SG);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseWithLeadingZero()}. */
+ public void testFindWithLeadingZero() throws Exception {
+ doTestFindInContext("+39 02-36618 300", RegionCode.NZ);
+ doTestFindInContext("02-36618 300", RegionCode.IT);
+ doTestFindInContext("312 345 678", RegionCode.IT);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseNationalNumberArgentina()}. */
+ public void testFindNationalNumberArgentina() throws Exception {
+ // Test parsing mobile numbers of Argentina.
+ doTestFindInContext("+54 9 343 555 1212", RegionCode.AR);
+ doTestFindInContext("0343 15 555 1212", RegionCode.AR);
+
+ doTestFindInContext("+54 9 3715 65 4320", RegionCode.AR);
+ doTestFindInContext("03715 15 65 4320", RegionCode.AR);
+
+ // Test parsing fixed-line numbers of Argentina.
+ doTestFindInContext("+54 11 3797 0000", RegionCode.AR);
+ doTestFindInContext("011 3797 0000", RegionCode.AR);
+
+ doTestFindInContext("+54 3715 65 4321", RegionCode.AR);
+ doTestFindInContext("03715 65 4321", RegionCode.AR);
+
+ doTestFindInContext("+54 23 1234 0000", RegionCode.AR);
+ doTestFindInContext("023 1234 0000", RegionCode.AR);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseWithXInNumber()}. */
+ public void testFindWithXInNumber() throws Exception {
+ doTestFindInContext("(0xx) 123456789", RegionCode.AR);
+ // A case where x denotes both carrier codes and extension symbol.
+ doTestFindInContext("(0xx) 123456789 x 1234", RegionCode.AR);
+
+ // This test is intentionally constructed such that the number of digit after xx is larger than
+ // 7, so that the number won't be mistakenly treated as an extension, as we allow extensions up
+ // to 7 digits. This assumption is okay for now as all the countries where a carrier selection
+ // code is written in the form of xx have a national significant number of length larger than 7.
+ doTestFindInContext("011xx5481429712", RegionCode.US);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseNumbersMexico()}. */
+ public void testFindNumbersMexico() throws Exception {
+ // Test parsing fixed-line numbers of Mexico.
+ doTestFindInContext("+52 (449)978-0001", RegionCode.MX);
+ doTestFindInContext("01 (449)978-0001", RegionCode.MX);
+ doTestFindInContext("(449)978-0001", RegionCode.MX);
+
+ // Test parsing mobile numbers of Mexico.
+ doTestFindInContext("+52 1 33 1234-5678", RegionCode.MX);
+ doTestFindInContext("044 (33) 1234-5678", RegionCode.MX);
+ doTestFindInContext("045 33 1234-5678", RegionCode.MX);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseNumbersWithPlusWithNoRegion()}. */
+ public void testFindNumbersWithPlusWithNoRegion() throws Exception {
+ // RegionCode.ZZ is allowed only if the number starts with a '+' - then the country code can be
+ // calculated.
+ doTestFindInContext("+64 3 331 6005", RegionCode.ZZ);
+ // Null is also allowed for the region code in these cases.
+ doTestFindInContext("+64 3 331 6005", null);
+ }
+
+ /** See {@link PhoneNumberUtilTest#testParseExtensions()}. */
+ public void testFindExtensions() throws Exception {
+ doTestFindInContext("03 331 6005 ext 3456", RegionCode.NZ);
+ doTestFindInContext("03-3316005x3456", RegionCode.NZ);
+ doTestFindInContext("03-3316005 int.3456", RegionCode.NZ);
+ doTestFindInContext("03 3316005 #3456", RegionCode.NZ);
+ doTestFindInContext("0~0 1800 7493 524", RegionCode.PL);
+ doTestFindInContext("(1800) 7493.524", RegionCode.US);
+ // Check that the last instance of an extension token is matched.
+ doTestFindInContext("0~0 1800 7493 524 ~1234", RegionCode.PL);
+ // Verifying bug-fix where the last digit of a number was previously omitted if it was a 0 when
+ // extracting the extension. Also verifying a few different cases of extensions.
+ doTestFindInContext("+44 2034567890x456", RegionCode.NZ);
+ doTestFindInContext("+44 2034567890x456", RegionCode.GB);
+ doTestFindInContext("+44 2034567890 x456", RegionCode.GB);
+ doTestFindInContext("+44 2034567890 X456", RegionCode.GB);
+ doTestFindInContext("+44 2034567890 X 456", RegionCode.GB);
+ doTestFindInContext("+44 2034567890 X 456", RegionCode.GB);
+ doTestFindInContext("+44 2034567890 X 456", RegionCode.GB);
+
+ doTestFindInContext("(800) 901-3355 x 7246433", RegionCode.US);
+ doTestFindInContext("(800) 901-3355 , ext 7246433", RegionCode.US);
+ doTestFindInContext("(800) 901-3355 ,extension 7246433", RegionCode.US);
+ // The next test differs from PhoneNumberUtil -> when matching we don't consider a lone comma to
+ // indicate an extension, although we accept it when parsing.
+ doTestFindInContext("(800) 901-3355 ,x 7246433", RegionCode.US);
+ doTestFindInContext("(800) 901-3355 ext: 7246433", RegionCode.US);
+ }
+
+ public void testFindInterspersedWithSpace() throws Exception {
+ doTestFindInContext("0 3 3 3 1 6 0 0 5", RegionCode.NZ);
+ }
+
+ /**
+ * Test matching behavior when starting in the middle of a phone number.
+ */
+ public void testIntermediateParsePositions() throws Exception {
+ String text = "Call 033316005 or 032316005!";
+ // | | | | | |
+ // 0 5 10 15 20 25
+
+ // Iterate over all possible indices.
+ for (int i = 0; i <= 5; i++) {
+ assertEqualRange(text, i, 5, 14);
+ }
+ // 7 and 8 digits in a row are still parsed as number.
+ assertEqualRange(text, 6, 6, 14);
+ assertEqualRange(text, 7, 7, 14);
+ // Anything smaller is skipped to the second instance.
+ for (int i = 8; i <= 19; i++) {
+ assertEqualRange(text, i, 19, 28);
+ }
+ }
+
+ public void testFourMatchesInARow() throws Exception {
+ String number1 = "415-666-7777";
+ String number2 = "800-443-1223";
+ String number3 = "212-443-1223";
+ String number4 = "650-443-1223";
+ String text = number1 + " - " + number2 + " - " + number3 + " - " + number4;
+
+ Iterator<PhoneNumberMatch> iterator =
+ phoneUtil.findNumbers(text, RegionCode.US).iterator();
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number1, RegionCode.US);
+
+ match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number2, RegionCode.US);
+
+ match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number3, RegionCode.US);
+
+ match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number4, RegionCode.US);
+ }
+
+ public void testMatchesFoundWithMultipleSpaces() throws Exception {
+ String number1 = "(415) 666-7777";
+ String number2 = "(800) 443-1223";
+ String text = number1 + " " + number2;
+
+ Iterator<PhoneNumberMatch> iterator =
+ phoneUtil.findNumbers(text, RegionCode.US).iterator();
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number1, RegionCode.US);
+
+ match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, text, number2, RegionCode.US);
+ }
+
+ public void testMatchWithSurroundingZipcodes() throws Exception {
+ String number = "415-666-7777";
+ String zipPreceding = "My address is CA 34215 - " + number + " is my number.";
+
+ Iterator<PhoneNumberMatch> iterator =
+ phoneUtil.findNumbers(zipPreceding, RegionCode.US).iterator();
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(match, zipPreceding, number, RegionCode.US);
+
+ // Now repeat, but this time the phone number has spaces in it. It should still be found.
+ number = "(415) 666 7777";
+
+ String zipFollowing = "My number is " + number + ". 34215 is my zip-code.";
+ iterator = phoneUtil.findNumbers(zipFollowing, RegionCode.US).iterator();
+ PhoneNumberMatch matchWithSpaces = iterator.hasNext() ? iterator.next() : null;
+ assertMatchProperties(matchWithSpaces, zipFollowing, number, RegionCode.US);
+ }
+
+ public void testIsLatinLetter() throws Exception {
+ assertTrue(PhoneNumberMatcher.isLatinLetter('c'));
+ assertTrue(PhoneNumberMatcher.isLatinLetter('C'));
+ assertTrue(PhoneNumberMatcher.isLatinLetter('\u00C9'));
+ assertTrue(PhoneNumberMatcher.isLatinLetter('\u0301')); // Combining acute accent
+ // Punctuation, digits and white-space are not considered "latin letters".
+ assertFalse(PhoneNumberMatcher.isLatinLetter(':'));
+ assertFalse(PhoneNumberMatcher.isLatinLetter('5'));
+ assertFalse(PhoneNumberMatcher.isLatinLetter('-'));
+ assertFalse(PhoneNumberMatcher.isLatinLetter('.'));
+ assertFalse(PhoneNumberMatcher.isLatinLetter(' '));
+ assertFalse(PhoneNumberMatcher.isLatinLetter('\u6211')); // Chinese character
+ assertFalse(PhoneNumberMatcher.isLatinLetter('\u306E')); // Hiragana letter no
+ }
+
+ public void testMatchesWithSurroundingLatinChars() throws Exception {
+ ArrayList<NumberContext> possibleOnlyContexts = new ArrayList<NumberContext>();
+ possibleOnlyContexts.add(new NumberContext("abc", "def"));
+ possibleOnlyContexts.add(new NumberContext("abc", ""));
+ possibleOnlyContexts.add(new NumberContext("", "def"));
+ // Latin capital letter e with an acute accent.
+ possibleOnlyContexts.add(new NumberContext("\u00C9", ""));
+ // e with an acute accent decomposed (with combining mark).
+ possibleOnlyContexts.add(new NumberContext("e\u0301", ""));
+
+ // Numbers should not be considered valid, if they are surrounded by Latin characters, but
+ // should be considered possible.
+ findMatchesInContexts(possibleOnlyContexts, false, true);
+ }
+
+ public void testMoneyNotSeenAsPhoneNumber() throws Exception {
+ ArrayList<NumberContext> possibleOnlyContexts = new ArrayList<NumberContext>();
+ possibleOnlyContexts.add(new NumberContext("$", ""));
+ possibleOnlyContexts.add(new NumberContext("", "$"));
+ possibleOnlyContexts.add(new NumberContext("\u00A3", "")); // Pound sign
+ possibleOnlyContexts.add(new NumberContext("\u00A5", "")); // Yen sign
+ findMatchesInContexts(possibleOnlyContexts, false, true);
+ }
+
+ public void testPercentageNotSeenAsPhoneNumber() throws Exception {
+ ArrayList<NumberContext> possibleOnlyContexts = new ArrayList<NumberContext>();
+ possibleOnlyContexts.add(new NumberContext("", "%"));
+ // Numbers followed by % should be dropped.
+ findMatchesInContexts(possibleOnlyContexts, false, true);
+ }
+
+ public void testPhoneNumberWithLeadingOrTrailingMoneyMatches() throws Exception {
+ // Because of the space after the 20 (or before the 100) these dollar amounts should not stop
+ // the actual number from being found.
+ ArrayList<NumberContext> contexts = new ArrayList<NumberContext>();
+ contexts.add(new NumberContext("$20 ", ""));
+ contexts.add(new NumberContext("", " 100$"));
+ findMatchesInContexts(contexts, true, true);
+ }
+
+ public void testMatchesWithSurroundingLatinCharsAndLeadingPunctuation() throws Exception {
+ // Contexts with trailing characters. Leading characters are okay here since the numbers we will
+ // insert start with punctuation, but trailing characters are still not allowed.
+ ArrayList<NumberContext> possibleOnlyContexts = new ArrayList<NumberContext>();
+ possibleOnlyContexts.add(new NumberContext("abc", "def"));
+ possibleOnlyContexts.add(new NumberContext("", "def"));
+ possibleOnlyContexts.add(new NumberContext("", "\u00C9"));
+
+ // Numbers should not be considered valid, if they have trailing Latin characters, but should be
+ // considered possible.
+ String numberWithPlus = "+14156667777";
+ String numberWithBrackets = "(415)6667777";
+ findMatchesInContexts(possibleOnlyContexts, false, true, RegionCode.US, numberWithPlus);
+ findMatchesInContexts(possibleOnlyContexts, false, true, RegionCode.US, numberWithBrackets);
+
+ ArrayList<NumberContext> validContexts = new ArrayList<NumberContext>();
+ validContexts.add(new NumberContext("abc", ""));
+ validContexts.add(new NumberContext("\u00C9", ""));
+ validContexts.add(new NumberContext("\u00C9", ".")); // Trailing punctuation.
+ validContexts.add(new NumberContext("\u00C9", " def")); // Trailing white-space.
+
+ // Numbers should be considered valid, since they start with punctuation.
+ findMatchesInContexts(validContexts, true, true, RegionCode.US, numberWithPlus);
+ findMatchesInContexts(validContexts, true, true, RegionCode.US, numberWithBrackets);
+ }
+
+ public void testMatchesWithSurroundingChineseChars() throws Exception {
+ ArrayList<NumberContext> validContexts = new ArrayList<NumberContext>();
+ validContexts.add(new NumberContext("\u6211\u7684\u7535\u8BDD\u53F7\u7801\u662F", ""));
+ validContexts.add(new NumberContext("", "\u662F\u6211\u7684\u7535\u8BDD\u53F7\u7801"));
+ validContexts.add(new NumberContext("\u8BF7\u62E8\u6253", "\u6211\u5728\u660E\u5929"));
+
+ // Numbers should be considered valid, since they are surrounded by Chinese.
+ findMatchesInContexts(validContexts, true, true);
+ }
+
+ public void testMatchesWithSurroundingPunctuation() throws Exception {
+ ArrayList<NumberContext> validContexts = new ArrayList<NumberContext>();
+ validContexts.add(new NumberContext("My number-", "")); // At end of text.
+ validContexts.add(new NumberContext("", ".Nice day.")); // At start of text.
+ validContexts.add(new NumberContext("Tel:", ".")); // Punctuation surrounds number.
+ validContexts.add(new NumberContext("Tel: ", " on Saturdays.")); // White-space is also fine.
+
+ // Numbers should be considered valid, since they are surrounded by punctuation.
+ findMatchesInContexts(validContexts, true, true);
+ }
+
+ public void testMatchesMultiplePhoneNumbersSeparatedByPhoneNumberPunctuation() throws Exception {
+ String text = "Call 650-253-4561 -- 455-234-3451";
+ String region = RegionCode.US;
+
+ PhoneNumber number1 = new PhoneNumber();
+ number1.setCountryCode(phoneUtil.getCountryCodeForRegion(region));
+ number1.setNationalNumber(6502534561L);
+ PhoneNumberMatch match1 = new PhoneNumberMatch(5, "650-253-4561", number1);
+
+ PhoneNumber number2 = new PhoneNumber();
+ number2.setCountryCode(phoneUtil.getCountryCodeForRegion(region));
+ number2.setNationalNumber(4552343451L);
+ PhoneNumberMatch match2 = new PhoneNumberMatch(21, "455-234-3451", number2);
+
+ Iterator<PhoneNumberMatch> matches = phoneUtil.findNumbers(text, region).iterator();
+ assertEquals(match1, matches.next());
+ assertEquals(match2, matches.next());
+ }
+
+ public void testDoesNotMatchMultiplePhoneNumbersSeparatedWithNoWhiteSpace() throws Exception {
+ // No white-space found between numbers - neither is found.
+ String text = "Call 650-253-4561--455-234-3451";
+ String region = RegionCode.US;
+
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(text, region)));
+ }
+
+ /**
+ * Strings with number-like things that shouldn't be found under any level.
+ */
+ private static final NumberTest[] IMPOSSIBLE_CASES = {
+ new NumberTest("12345", RegionCode.US),
+ new NumberTest("23456789", RegionCode.US),
+ new NumberTest("234567890112", RegionCode.US),
+ new NumberTest("650+253+1234", RegionCode.US),
+ new NumberTest("3/10/1984", RegionCode.CA),
+ new NumberTest("03/27/2011", RegionCode.US),
+ 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),
+ new NumberTest("2012-01-02 08:00", RegionCode.US),
+ new NumberTest("2012/01/02 08:00", RegionCode.US),
+ new NumberTest("20120102 08:00", RegionCode.US),
+ new NumberTest("2014-04-12 04:04 PM", RegionCode.US),
+ new NumberTest("2014-04-12 &nbsp;04:04 PM", RegionCode.US),
+ new NumberTest("2014-04-12 &nbsp;04:04 PM", RegionCode.US),
+ new NumberTest("2014-04-12 04:04 PM", RegionCode.US),
+ };
+
+ /**
+ * Strings with number-like things that should only be found under "possible".
+ */
+ private static final NumberTest[] POSSIBLE_ONLY_CASES = {
+ // 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("6502531x234", RegionCode.US),
+ new NumberTest("(20) 3346 1234", RegionCode.GB), // Non-optional NP omitted
+ };
+
+ /**
+ * Strings with number-like things that should only be found up to and including the "valid"
+ * leniency level.
+ */
+ private static final NumberTest[] VALID_CASES = {
+ 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("12 7/8 - 14 12/34 - 5", RegionCode.US),
+ new NumberTest("12.1 - 23.71 - 23.45", 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", RegionCode.US),
+ new NumberTest("2012-0102 08", RegionCode.US), // Very strange formatting.
+ new NumberTest("2012-01-02 08", RegionCode.US),
+ // Breakdown assistance number with unexpected formatting.
+ new NumberTest("1800-1-0-10 22", RegionCode.AU),
+ new NumberTest("030-3-2 23 12 34", RegionCode.DE),
+ new NumberTest("03 0 -3 2 23 12 34", RegionCode.DE),
+ new NumberTest("(0)3 0 -3 2 23 12 34", RegionCode.DE),
+ new NumberTest("0 3 0 -3 2 23 12 34", RegionCode.DE),
+ };
+
+ /**
+ * Strings with number-like things that should only be found up to and including the
+ * "strict_grouping" leniency level.
+ */
+ private static final NumberTest[] STRICT_GROUPING_CASES = {
+ new NumberTest("(415) 6667777", RegionCode.US),
+ new NumberTest("415-6667777", RegionCode.US),
+ // Should be found by strict grouping but not exact grouping, as the last two groups are
+ // formatted together as a block.
+ new NumberTest("0800-2491234", RegionCode.DE),
+ // Doesn't match any formatting in the test file, but almost matches an alternate format (the
+ // last two groups have been squashed together here).
+ new NumberTest("0900-1 123123", RegionCode.DE),
+ new NumberTest("(0)900-1 123123", RegionCode.DE),
+ new NumberTest("0 900-1 123123", RegionCode.DE),
+ // NDC also found as part of the country calling code; this shouldn't ruin the grouping
+ // expectations.
+ new NumberTest("+33 3 34 2312", RegionCode.FR),
+ };
+
+ /**
+ * Strings with number-like things that should be found at all levels.
+ */
+ private static final NumberTest[] EXACT_GROUPING_CASES = {
+ new NumberTest("\uFF14\uFF11\uFF15\uFF16\uFF16\uFF16\uFF17\uFF17\uFF17\uFF17", RegionCode.US),
+ new NumberTest("\uFF14\uFF11\uFF15-\uFF16\uFF16\uFF16-\uFF17\uFF17\uFF17\uFF17", RegionCode.US),
+ new NumberTest("4156667777", RegionCode.US),
+ new NumberTest("4156667777 x 123", RegionCode.US),
+ new NumberTest("415-666-7777", RegionCode.US),
+ new NumberTest("415/666-7777", RegionCode.US),
+ new NumberTest("415-666-7777 ext. 503", RegionCode.US),
+ new NumberTest("1 415 666 7777 x 123", RegionCode.US),
+ new NumberTest("+1 415-666-7777", RegionCode.US),
+ new NumberTest("+494949 49", RegionCode.DE),
+ new NumberTest("+49-49-34", RegionCode.DE),
+ new NumberTest("+49-4931-49", RegionCode.DE),
+ new NumberTest("04931-49", RegionCode.DE), // With National Prefix
+ new NumberTest("+49-494949", RegionCode.DE), // One group with country code
+ new NumberTest("+49-494949 ext. 49", RegionCode.DE),
+ new NumberTest("+49494949 ext. 49", RegionCode.DE),
+ new NumberTest("0494949", RegionCode.DE),
+ new NumberTest("0494949 ext. 49", RegionCode.DE),
+ new NumberTest("01 (33) 3461 2234", RegionCode.MX), // Optional NP present
+ new NumberTest("(33) 3461 2234", RegionCode.MX), // Optional NP omitted
+ new NumberTest("1800-10-10 22", RegionCode.AU), // Breakdown assistance number.
+ // Doesn't match any formatting in the test file, but matches an alternate format exactly.
+ new NumberTest("0900-1 123 123", RegionCode.DE),
+ new NumberTest("(0)900-1 123 123", RegionCode.DE),
+ new NumberTest("0 900-1 123 123", RegionCode.DE),
+ new NumberTest("+33 3 34 23 12", RegionCode.FR),
+ };
+
+ public void testMatchesWithPossibleLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ 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<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES));
+ doTestNumberNonMatchesForLeniency(testCases, Leniency.POSSIBLE);
+ }
+
+ public void testMatchesWithValidLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ 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<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES));
+ testCases.addAll(Arrays.asList(POSSIBLE_ONLY_CASES));
+ doTestNumberNonMatchesForLeniency(testCases, Leniency.VALID);
+ }
+
+ public void testMatchesWithStrictGroupingLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(STRICT_GROUPING_CASES));
+ testCases.addAll(Arrays.asList(EXACT_GROUPING_CASES));
+ doTestNumberMatchesForLeniency(testCases, Leniency.STRICT_GROUPING);
+ }
+
+ public void testNonMatchesWithStrictGroupLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES));
+ testCases.addAll(Arrays.asList(POSSIBLE_ONLY_CASES));
+ testCases.addAll(Arrays.asList(VALID_CASES));
+ doTestNumberNonMatchesForLeniency(testCases, Leniency.STRICT_GROUPING);
+ }
+
+ public void testMatchesWithExactGroupingLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(EXACT_GROUPING_CASES));
+ doTestNumberMatchesForLeniency(testCases, Leniency.EXACT_GROUPING);
+ }
+
+ public void testNonMatchesExactGroupLeniency() throws Exception {
+ List<NumberTest> testCases = new ArrayList<NumberTest>();
+ testCases.addAll(Arrays.asList(IMPOSSIBLE_CASES));
+ testCases.addAll(Arrays.asList(POSSIBLE_ONLY_CASES));
+ testCases.addAll(Arrays.asList(VALID_CASES));
+ testCases.addAll(Arrays.asList(STRICT_GROUPING_CASES));
+ doTestNumberNonMatchesForLeniency(testCases, Leniency.EXACT_GROUPING);
+ }
+
+ private void doTestNumberMatchesForLeniency(List<NumberTest> testCases, Leniency leniency) {
+ int noMatchFoundCount = 0;
+ int wrongMatchFoundCount = 0;
+ for (NumberTest test : testCases) {
+ Iterator<PhoneNumberMatch> iterator =
+ findNumbersForLeniency(test.rawString, test.region, leniency);
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ if (match == null) {
+ noMatchFoundCount++;
+ System.err.println("No match found in " + test.toString() + " for leniency: " + leniency);
+ } else {
+ if (!test.rawString.equals(match.rawString())) {
+ wrongMatchFoundCount++;
+ System.err.println("Found wrong match in test " + test.toString() +
+ ". Found " + match.rawString());
+ }
+ }
+ }
+ assertEquals(0, noMatchFoundCount);
+ assertEquals(0, wrongMatchFoundCount);
+ }
+
+ private void doTestNumberNonMatchesForLeniency(List<NumberTest> testCases, Leniency leniency) {
+ int matchFoundCount = 0;
+ for (NumberTest test : testCases) {
+ Iterator<PhoneNumberMatch> iterator =
+ findNumbersForLeniency(test.rawString, test.region, leniency);
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ if (match != null) {
+ matchFoundCount++;
+ System.err.println("Match found in " + test.toString() + " for leniency: " + leniency);
+ }
+ }
+ assertEquals(0, matchFoundCount);
+ }
+
+ /**
+ * Helper method which tests the contexts provided and ensures that:
+ * -- if isValid is true, they all find a test number inserted in the middle when leniency of
+ * matching is set to VALID; else no test number should be extracted at that leniency level
+ * -- if isPossible is true, they all find a test number inserted in the middle when leniency of
+ * matching is set to POSSIBLE; else no test number should be extracted at that leniency level
+ */
+ private void findMatchesInContexts(List<NumberContext> contexts, boolean isValid,
+ boolean isPossible, String region, String number) {
+ if (isValid) {
+ doTestInContext(number, region, contexts, Leniency.VALID);
+ } else {
+ for (NumberContext context : contexts) {
+ String text = context.leadingText + number + context.trailingText;
+ assertTrue("Should not have found a number in " + text,
+ hasNoMatches(phoneUtil.findNumbers(text, region)));
+ }
+ }
+ if (isPossible) {
+ doTestInContext(number, region, contexts, Leniency.POSSIBLE);
+ } else {
+ for (NumberContext context : contexts) {
+ String text = context.leadingText + number + context.trailingText;
+ assertTrue("Should not have found a number in " + text,
+ hasNoMatches(phoneUtil.findNumbers(text, region, Leniency.POSSIBLE,
+ Long.MAX_VALUE)));
+ }
+ }
+ }
+
+ /**
+ * Variant of findMatchesInContexts that uses a default number and region.
+ */
+ private void findMatchesInContexts(List<NumberContext> contexts, boolean isValid,
+ boolean isPossible) {
+ String region = RegionCode.US;
+ String number = "415-666-7777";
+
+ findMatchesInContexts(contexts, isValid, isPossible, region, number);
+ }
+
+ public void testNonMatchingBracketsAreInvalid() throws Exception {
+ // The digits up to the ", " form a valid US number, but it shouldn't be matched as one since
+ // there was a non-matching bracket present.
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "80.585 [79.964, 81.191]", RegionCode.US)));
+
+ // The trailing "]" is thrown away before parsing, so the resultant number, while a valid US
+ // number, does not have matching brackets.
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "80.585 [79.964]", RegionCode.US)));
+
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "80.585 ((79.964)", RegionCode.US)));
+
+ // This case has too many sets of brackets to be valid.
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "(80).(585) (79).(9)64", RegionCode.US)));
+ }
+
+ public void testNoMatchIfRegionIsNull() throws Exception {
+ // Fail on non-international prefix if region code is null.
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "Random text body - number is 0331 6005, see you there", null)));
+ }
+
+ public void testNoMatchInEmptyString() throws Exception {
+ assertTrue(hasNoMatches(phoneUtil.findNumbers("", RegionCode.US)));
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(" ", RegionCode.US)));
+ }
+
+ public void testNoMatchIfNoNumber() throws Exception {
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(
+ "Random text body - number is foobar, see you there", RegionCode.US)));
+ }
+
+ public void testSequences() throws Exception {
+ // Test multiple occurrences.
+ String text = "Call 033316005 or 032316005!";
+ String region = RegionCode.NZ;
+
+ PhoneNumber number1 = new PhoneNumber();
+ number1.setCountryCode(phoneUtil.getCountryCodeForRegion(region));
+ number1.setNationalNumber(33316005);
+ PhoneNumberMatch match1 = new PhoneNumberMatch(5, "033316005", number1);
+
+ PhoneNumber number2 = new PhoneNumber();
+ number2.setCountryCode(phoneUtil.getCountryCodeForRegion(region));
+ number2.setNationalNumber(32316005);
+ PhoneNumberMatch match2 = new PhoneNumberMatch(19, "032316005", number2);
+
+ Iterator<PhoneNumberMatch> matches =
+ phoneUtil.findNumbers(text, region, Leniency.POSSIBLE, Long.MAX_VALUE).iterator();
+
+ assertEquals(match1, matches.next());
+ assertEquals(match2, matches.next());
+ }
+
+ public void testNullInput() throws Exception {
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(null, RegionCode.US)));
+ assertTrue(hasNoMatches(phoneUtil.findNumbers(null, null)));
+ }
+
+ public void testMaxMatches() throws Exception {
+ // Set up text with 100 valid phone numbers.
+ StringBuilder numbers = new StringBuilder();
+ for (int i = 0; i < 100; i++) {
+ numbers.append("My info: 415-666-7777,");
+ }
+
+ // Matches all 100. Max only applies to failed cases.
+ List<PhoneNumber> expected = new ArrayList<PhoneNumber>(100);
+ PhoneNumber number = phoneUtil.parse("+14156667777", null);
+ for (int i = 0; i < 100; i++) {
+ expected.add(number);
+ }
+
+ Iterable<PhoneNumberMatch> iterable =
+ phoneUtil.findNumbers(numbers.toString(), RegionCode.US, Leniency.VALID, 10);
+ List<PhoneNumber> actual = new ArrayList<PhoneNumber>(100);
+ for (PhoneNumberMatch match : iterable) {
+ actual.add(match.number());
+ }
+ assertEquals(expected, actual);
+ }
+
+ public void testMaxMatchesInvalid() throws Exception {
+ // Set up text with 10 invalid phone numbers followed by 100 valid.
+ StringBuilder numbers = new StringBuilder();
+ for (int i = 0; i < 10; i++) {
+ numbers.append("My address 949-8945-0");
+ }
+ for (int i = 0; i < 100; i++) {
+ numbers.append("My info: 415-666-7777,");
+ }
+
+ Iterable<PhoneNumberMatch> iterable =
+ phoneUtil.findNumbers(numbers.toString(), RegionCode.US, Leniency.VALID, 10);
+ assertFalse(iterable.iterator().hasNext());
+ }
+
+ public void testMaxMatchesMixed() throws Exception {
+ // Set up text with 100 valid numbers inside an invalid number.
+ StringBuilder numbers = new StringBuilder();
+ for (int i = 0; i < 100; i++) {
+ numbers.append("My info: 415-666-7777 123 fake street");
+ }
+
+ // Only matches the first 10 despite there being 100 numbers due to max matches.
+ List<PhoneNumber> expected = new ArrayList<PhoneNumber>(100);
+ PhoneNumber number = phoneUtil.parse("+14156667777", null);
+ for (int i = 0; i < 10; i++) {
+ expected.add(number);
+ }
+
+ Iterable<PhoneNumberMatch> iterable =
+ phoneUtil.findNumbers(numbers.toString(), RegionCode.US, Leniency.VALID, 10);
+ List<PhoneNumber> actual = new ArrayList<PhoneNumber>(100);
+ for (PhoneNumberMatch match : iterable) {
+ actual.add(match.number());
+ }
+ assertEquals(expected, actual);
+ }
+
+ public void testNonPlusPrefixedNumbersNotFoundForInvalidRegion() throws Exception {
+ // Does not start with a "+", we won't match it.
+ Iterable<PhoneNumberMatch> iterable = phoneUtil.findNumbers("1 456 764 156", RegionCode.ZZ);
+ Iterator<PhoneNumberMatch> iterator = iterable.iterator();
+
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ assertFalse(iterator.hasNext());
+ }
+
+ public void testEmptyIteration() throws Exception {
+ Iterable<PhoneNumberMatch> iterable = phoneUtil.findNumbers("", RegionCode.ZZ);
+ Iterator<PhoneNumberMatch> iterator = iterable.iterator();
+
+ assertFalse(iterator.hasNext());
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ assertFalse(iterator.hasNext());
+ }
+
+ public void testSingleIteration() throws Exception {
+ Iterable<PhoneNumberMatch> iterable = phoneUtil.findNumbers("+14156667777", RegionCode.ZZ);
+
+ // With hasNext() -> next().
+ Iterator<PhoneNumberMatch> iterator = iterable.iterator();
+ // Double hasNext() to ensure it does not advance.
+ assertTrue(iterator.hasNext());
+ assertTrue(iterator.hasNext());
+ assertNotNull(iterator.next());
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ assertFalse(iterator.hasNext());
+
+ // With next() only.
+ iterator = iterable.iterator();
+ assertNotNull(iterator.next());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ }
+
+ public void testDoubleIteration() throws Exception {
+ Iterable<PhoneNumberMatch> iterable =
+ phoneUtil.findNumbers("+14156667777 foobar +14156667777 ", RegionCode.ZZ);
+
+ // With hasNext() -> next().
+ Iterator<PhoneNumberMatch> iterator = iterable.iterator();
+ // Double hasNext() to ensure it does not advance.
+ assertTrue(iterator.hasNext());
+ assertTrue(iterator.hasNext());
+ assertNotNull(iterator.next());
+ assertTrue(iterator.hasNext());
+ assertTrue(iterator.hasNext());
+ assertNotNull(iterator.next());
+ assertFalse(iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ assertFalse(iterator.hasNext());
+
+ // With next() only.
+ iterator = iterable.iterator();
+ assertNotNull(iterator.next());
+ assertNotNull(iterator.next());
+ try {
+ iterator.next();
+ fail("Violation of the Iterator contract.");
+ } catch (NoSuchElementException e) { /* Success */ }
+ }
+
+ /**
+ * Ensures that {@link Iterator#remove()} is not supported and that calling it does not
+ * change iteration behavior.
+ */
+ public void testRemovalNotSupported() throws Exception {
+ Iterable<PhoneNumberMatch> iterable = phoneUtil.findNumbers("+14156667777", RegionCode.ZZ);
+
+ Iterator<PhoneNumberMatch> iterator = iterable.iterator();
+ try {
+ iterator.remove();
+ fail("Iterator must not support remove.");
+ } catch (UnsupportedOperationException e) { /* success */ }
+
+ assertTrue(iterator.hasNext());
+
+ try {
+ iterator.remove();
+ fail("Iterator must not support remove.");
+ } catch (UnsupportedOperationException e) { /* success */ }
+
+ assertNotNull(iterator.next());
+
+ try {
+ iterator.remove();
+ fail("Iterator must not support remove.");
+ } catch (UnsupportedOperationException e) { /* success */ }
+
+ assertFalse(iterator.hasNext());
+ }
+
+ /**
+ * Asserts that the expected match is non-null, and that the raw string and expected
+ * proto buffer are set appropriately.
+ */
+ private void assertMatchProperties(
+ PhoneNumberMatch match, String text, String number, String region) throws Exception {
+ PhoneNumber expectedResult = phoneUtil.parse(number, region);
+ assertNotNull("Did not find a number in '" + text + "'; expected " + number, match);
+ assertEquals(expectedResult, match.number());
+ assertEquals(number, match.rawString());
+ }
+
+ /**
+ * Asserts that another number can be found in {@code text} starting at {@code index}, and that
+ * its corresponding range is {@code [start, end)}.
+ */
+ private void assertEqualRange(CharSequence text, int index, int start, int end) {
+ CharSequence sub = text.subSequence(index, text.length());
+ Iterator<PhoneNumberMatch> matches =
+ phoneUtil.findNumbers(sub, RegionCode.NZ, Leniency.POSSIBLE, Long.MAX_VALUE).iterator();
+ assertTrue(matches.hasNext());
+ PhoneNumberMatch match = matches.next();
+ assertEquals(start - index, match.start());
+ assertEquals(end - index, match.end());
+ assertEquals(sub.subSequence(match.start(), match.end()).toString(), match.rawString());
+ }
+
+ /**
+ * Tests numbers found by {@link PhoneNumberUtil#findNumbers(CharSequence, String)} in various
+ * textual contexts.
+ *
+ * @param number the number to test and the corresponding region code to use
+ */
+ private void doTestFindInContext(String number, String defaultCountry) throws Exception {
+ findPossibleInContext(number, defaultCountry);
+
+ PhoneNumber parsed = phoneUtil.parse(number, defaultCountry);
+ if (phoneUtil.isValidNumber(parsed)) {
+ findValidInContext(number, defaultCountry);
+ }
+ }
+
+ /**
+ * Tests valid numbers in contexts that should pass for {@link Leniency#POSSIBLE}.
+ */
+ private void findPossibleInContext(String number, String defaultCountry) {
+ ArrayList<NumberContext> contextPairs = new ArrayList<NumberContext>();
+ contextPairs.add(new NumberContext("", "")); // no context
+ contextPairs.add(new NumberContext(" ", "\t")); // whitespace only
+ contextPairs.add(new NumberContext("Hello ", "")); // no context at end
+ contextPairs.add(new NumberContext("", " to call me!")); // no context at start
+ contextPairs.add(new NumberContext("Hi there, call ", " to reach me!")); // no context at start
+ contextPairs.add(new NumberContext("Hi there, call ", ", or don't")); // with commas
+ // Three examples without whitespace around the number.
+ contextPairs.add(new NumberContext("Hi call", ""));
+ contextPairs.add(new NumberContext("", "forme"));
+ contextPairs.add(new NumberContext("Hi call", "forme"));
+ // With other small numbers.
+ contextPairs.add(new NumberContext("It's cheap! Call ", " before 6:30"));
+ // With a second number later.
+ contextPairs.add(new NumberContext("Call ", " or +1800-123-4567!"));
+ contextPairs.add(new NumberContext("Call me on June 2 at", "")); // with a Month-Day date
+ // With publication pages.
+ contextPairs.add(new NumberContext(
+ "As quoted by Alfonso 12-15 (2009), you may call me at ", ""));
+ contextPairs.add(new NumberContext(
+ "As quoted by Alfonso et al. 12-15 (2009), you may call me at ", ""));
+ // With dates, written in the American style.
+ contextPairs.add(new NumberContext(
+ "As I said on 03/10/2011, you may call me at ", ""));
+ // With trailing numbers after a comma. The 45 should not be considered an extension.
+ contextPairs.add(new NumberContext("", ", 45 days a year"));
+ // With a postfix stripped off as it looks like the start of another number.
+ contextPairs.add(new NumberContext("Call ", "/x12 more"));
+
+ doTestInContext(number, defaultCountry, contextPairs, Leniency.POSSIBLE);
+ }
+
+ /**
+ * Tests valid numbers in contexts that fail for {@link Leniency#POSSIBLE} but are valid for
+ * {@link Leniency#VALID}.
+ */
+ private void findValidInContext(String number, String defaultCountry) {
+ ArrayList<NumberContext> contextPairs = new ArrayList<NumberContext>();
+ // With other small numbers.
+ contextPairs.add(new NumberContext("It's only 9.99! Call ", " to buy"));
+ // With a number Day.Month.Year date.
+ contextPairs.add(new NumberContext("Call me on 21.6.1984 at ", ""));
+ // With a number Month/Day date.
+ contextPairs.add(new NumberContext("Call me on 06/21 at ", ""));
+ // With a number Day.Month date.
+ contextPairs.add(new NumberContext("Call me on 21.6. at ", ""));
+ // With a number Month/Day/Year date.
+ contextPairs.add(new NumberContext("Call me on 06/21/84 at ", ""));
+
+ doTestInContext(number, defaultCountry, contextPairs, Leniency.VALID);
+ }
+
+ private void doTestInContext(String number, String defaultCountry,
+ List<NumberContext> contextPairs, Leniency leniency) {
+ for (NumberContext context : contextPairs) {
+ String prefix = context.leadingText;
+ String text = prefix + number + context.trailingText;
+
+ int start = prefix.length();
+ int end = start + number.length();
+ Iterator<PhoneNumberMatch> iterator =
+ phoneUtil.findNumbers(text, defaultCountry, leniency, Long.MAX_VALUE).iterator();
+
+ PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null;
+ assertNotNull("Did not find a number in '" + text + "'; expected '" + number + "'", match);
+
+ CharSequence extracted = text.subSequence(match.start(), match.end());
+ assertTrue("Unexpected phone region in '" + text + "'; extracted '" + extracted + "'",
+ start == match.start() && end == match.end());
+ assertTrue(number.contentEquals(extracted));
+ assertTrue(match.rawString().contentEquals(extracted));
+
+ ensureTermination(text, defaultCountry, leniency);
+ }
+ }
+
+ /**
+ * Exhaustively searches for phone numbers from each index within {@code text} to test that
+ * finding matches always terminates.
+ */
+ private void ensureTermination(String text, String defaultCountry, Leniency leniency) {
+ for (int index = 0; index <= text.length(); index++) {
+ String sub = text.substring(index);
+ StringBuilder matches = new StringBuilder();
+ // Iterates over all matches.
+ for (PhoneNumberMatch match :
+ phoneUtil.findNumbers(sub, defaultCountry, leniency, Long.MAX_VALUE)) {
+ matches.append(", ").append(match.toString());
+ }
+ }
+ }
+
+ private Iterator<PhoneNumberMatch> findNumbersForLeniency(
+ String text, String defaultCountry, Leniency leniency) {
+ return phoneUtil.findNumbers(text, defaultCountry, leniency, Long.MAX_VALUE).iterator();
+ }
+
+ private boolean hasNoMatches(Iterable<PhoneNumberMatch> iterable) {
+ return !iterable.iterator().hasNext();
+ }
+
+ /**
+ * Small class that holds the context of the number we are testing against. The test will
+ * insert the phone number to be found between leadingText and trailingText.
+ */
+ private static class NumberContext {
+ final String leadingText;
+ final String trailingText;
+
+ NumberContext(String leadingText, String trailingText) {
+ this.leadingText = leadingText;
+ this.trailingText = trailingText;
+ }
+ }
+
+ /**
+ * Small class that holds the number we want to test and the region for which it should be valid.
+ */
+ private static class NumberTest {
+ final String rawString;
+ final String region;
+
+ NumberTest(String rawString, String regionCode) {
+ this.rawString = rawString;
+ this.region = regionCode;
+ }
+
+ @Override
+ public String toString() {
+ return rawString + " (" + region.toString() + ")";
+ }
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
new file mode 100644
index 00000000..1f98c036
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
@@ -0,0 +1,2570 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
+import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Unit tests for PhoneNumberUtil.java
+ *
+ * Note that these tests use the test metadata, not the normal metadata file, so should not be used
+ * for regression test purposes - these tests are illustrative only and test functionality.
+ *
+ * @author Shaopeng Jia
+ */
+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 AE_UAN =
+ new PhoneNumber().setCountryCode(971).setNationalNumber(600123456L);
+ private static final PhoneNumber AR_MOBILE =
+ new PhoneNumber().setCountryCode(54).setNationalNumber(91187654321L);
+ private static final PhoneNumber AR_NUMBER =
+ new PhoneNumber().setCountryCode(54).setNationalNumber(1187654321);
+ private static final PhoneNumber AU_NUMBER =
+ new PhoneNumber().setCountryCode(61).setNationalNumber(236618300L);
+ private static final PhoneNumber BS_MOBILE =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(2423570000L);
+ private static final PhoneNumber BS_NUMBER =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(2423651234L);
+ // Note that this is the same as the example number for DE in the metadata.
+ private static final PhoneNumber DE_NUMBER =
+ new PhoneNumber().setCountryCode(49).setNationalNumber(30123456L);
+ private static final PhoneNumber DE_SHORT_NUMBER =
+ new PhoneNumber().setCountryCode(49).setNationalNumber(1234L);
+ private static final PhoneNumber GB_MOBILE =
+ new PhoneNumber().setCountryCode(44).setNationalNumber(7912345678L);
+ private static final PhoneNumber GB_NUMBER =
+ new PhoneNumber().setCountryCode(44).setNationalNumber(2070313000L);
+ private static final PhoneNumber IT_MOBILE =
+ new PhoneNumber().setCountryCode(39).setNationalNumber(345678901L);
+ private static final PhoneNumber IT_NUMBER =
+ new PhoneNumber().setCountryCode(39).setNationalNumber(236618300L).
+ setItalianLeadingZero(true);
+ private static final PhoneNumber JP_STAR_NUMBER =
+ new PhoneNumber().setCountryCode(81).setNationalNumber(2345);
+ // Numbers to test the formatting rules from Mexico.
+ private static final PhoneNumber MX_MOBILE1 =
+ new PhoneNumber().setCountryCode(52).setNationalNumber(12345678900L);
+ private static final PhoneNumber MX_MOBILE2 =
+ new PhoneNumber().setCountryCode(52).setNationalNumber(15512345678L);
+ private static final PhoneNumber MX_NUMBER1 =
+ new PhoneNumber().setCountryCode(52).setNationalNumber(3312345678L);
+ private static final PhoneNumber MX_NUMBER2 =
+ new PhoneNumber().setCountryCode(52).setNationalNumber(8211234567L);
+ private static final PhoneNumber NZ_NUMBER =
+ new PhoneNumber().setCountryCode(64).setNationalNumber(33316005L);
+ private static final PhoneNumber SG_NUMBER =
+ new PhoneNumber().setCountryCode(65).setNationalNumber(65218000L);
+ // A too-long and hence invalid US number.
+ private static final PhoneNumber US_LONG_NUMBER =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(65025300001L);
+ private static final PhoneNumber US_NUMBER =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(6502530000L);
+ private static final PhoneNumber US_PREMIUM =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(9002530000L);
+ // Too short, but still possible US numbers.
+ private static final PhoneNumber US_LOCAL_NUMBER =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(2530000L);
+ private static final PhoneNumber US_SHORT_BY_ONE_NUMBER =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(650253000L);
+ private static final PhoneNumber US_TOLLFREE =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(8002530000L);
+ private static final PhoneNumber US_SPOOF =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(0L);
+ 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);
+ // We set this to be the same length as numbers for the other non-geographical country prefix that
+ // we have in our test metadata. However, this is not considered valid because they differ in
+ // their country calling code.
+ private static final PhoneNumber INTERNATIONAL_TOLL_FREE_TOO_LONG =
+ 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);
+ }
+
+ public void testGetSupportedGlobalNetworkCallingCodes() {
+ Set<Integer> globalNetworkCallingCodes =
+ phoneUtil.getSupportedGlobalNetworkCallingCodes();
+ assertTrue(globalNetworkCallingCodes.size() > 0);
+ for (int callingCode : globalNetworkCallingCodes) {
+ assertTrue(callingCode > 0);
+ assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForCountryCode(callingCode));
+ }
+ }
+
+ public void testGetInstanceLoadBadMetadata() {
+ assertNull(phoneUtil.getMetadataForRegion("No Such Region"));
+ assertNull(phoneUtil.getMetadataForNonGeographicalRegion(-1));
+ }
+
+ public void testMissingMetadataFileThrowsRuntimeException() {
+ // In normal usage we should never get a state where we are asking to load metadata that doesn't
+ // exist. However if the library is packaged incorrectly in the jar, this could happen and the
+ // best we can do is make sure the exception has the file name in it.
+ try {
+ phoneUtil.loadMetadataFromFile(
+ "no/such/file", "XX", -1, PhoneNumberUtil.DEFAULT_METADATA_LOADER);
+ fail("expected exception");
+ } catch (RuntimeException e) {
+ assertTrue("Unexpected error: " + e, e.toString().contains("no/such/file_XX"));
+ }
+ try {
+ phoneUtil.loadMetadataFromFile("no/such/file", PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY,
+ 123, PhoneNumberUtil.DEFAULT_METADATA_LOADER);
+ fail("expected exception");
+ } catch (RuntimeException e) {
+ assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file_123"));
+ }
+ }
+
+ public void testGetInstanceLoadUSMetadata() {
+ PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US);
+ assertEquals("US", metadata.getId());
+ assertEquals(1, metadata.getCountryCode());
+ assertEquals("011", metadata.getInternationalPrefix());
+ assertTrue(metadata.hasNationalPrefix());
+ assertEquals(2, metadata.numberFormatSize());
+ assertEquals("(\\d{3})(\\d{3})(\\d{4})",
+ metadata.getNumberFormat(1).getPattern());
+ assertEquals("$1 $2 $3", metadata.getNumberFormat(1).getFormat());
+ assertEquals("[13-689]\\d{9}|2[0-35-9]\\d{8}",
+ metadata.getGeneralDesc().getNationalNumberPattern());
+ assertEquals("\\d{7}(?:\\d{3})?", metadata.getGeneralDesc().getPossibleNumberPattern());
+ assertTrue(metadata.getGeneralDesc().exactlySameAs(metadata.getFixedLine()));
+ assertEquals("\\d{10}", metadata.getTollFree().getPossibleNumberPattern());
+ assertEquals("900\\d{7}", metadata.getPremiumRate().getNationalNumberPattern());
+ // No shared-cost data is available, so it should be initialised to "NA".
+ assertEquals("NA", metadata.getSharedCost().getNationalNumberPattern());
+ assertEquals("NA", metadata.getSharedCost().getPossibleNumberPattern());
+ }
+
+ public void testGetInstanceLoadDEMetadata() {
+ PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.DE);
+ assertEquals("DE", metadata.getId());
+ assertEquals(49, metadata.getCountryCode());
+ assertEquals("00", metadata.getInternationalPrefix());
+ assertEquals("0", metadata.getNationalPrefix());
+ assertEquals(6, metadata.numberFormatSize());
+ assertEquals(1, metadata.getNumberFormat(5).leadingDigitsPatternSize());
+ assertEquals("900", metadata.getNumberFormat(5).getLeadingDigitsPattern(0));
+ assertEquals("(\\d{3})(\\d{3,4})(\\d{4})",
+ metadata.getNumberFormat(5).getPattern());
+ assertEquals("$1 $2 $3", metadata.getNumberFormat(5).getFormat());
+ assertEquals("(?:[24-6]\\d{2}|3[03-9]\\d|[789](?:[1-9]\\d|0[2-9]))\\d{1,8}",
+ metadata.getFixedLine().getNationalNumberPattern());
+ assertEquals("\\d{2,14}", metadata.getFixedLine().getPossibleNumberPattern());
+ assertEquals("30123456", metadata.getFixedLine().getExampleNumber());
+ assertEquals("\\d{10}", metadata.getTollFree().getPossibleNumberPattern());
+ assertEquals("900([135]\\d{6}|9\\d{7})", metadata.getPremiumRate().getNationalNumberPattern());
+ }
+
+ public void testGetInstanceLoadARMetadata() {
+ PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.AR);
+ assertEquals("AR", metadata.getId());
+ assertEquals(54, metadata.getCountryCode());
+ assertEquals("00", metadata.getInternationalPrefix());
+ assertEquals("0", metadata.getNationalPrefix());
+ assertEquals("0(?:(11|343|3715)15)?", metadata.getNationalPrefixForParsing());
+ assertEquals("9$1", metadata.getNationalPrefixTransformRule());
+ assertEquals("$2 15 $3-$4", metadata.getNumberFormat(2).getFormat());
+ assertEquals("(9)(\\d{4})(\\d{2})(\\d{4})",
+ metadata.getNumberFormat(3).getPattern());
+ assertEquals("(9)(\\d{4})(\\d{2})(\\d{4})",
+ metadata.getIntlNumberFormat(3).getPattern());
+ 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 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
+ 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.
+ }
+
+ public void testGetLengthOfGeographicalAreaCode() {
+ // Google MTV, which has area code "650".
+ assertEquals(3, phoneUtil.getLengthOfGeographicalAreaCode(US_NUMBER));
+
+ // A North America toll-free number, which has no area code.
+ assertEquals(0, phoneUtil.getLengthOfGeographicalAreaCode(US_TOLLFREE));
+
+ // Google London, which has area code "20".
+ assertEquals(2, phoneUtil.getLengthOfGeographicalAreaCode(GB_NUMBER));
+
+ // A UK mobile phone, which has no area code.
+ assertEquals(0, phoneUtil.getLengthOfGeographicalAreaCode(GB_MOBILE));
+
+ // Google Buenos Aires, which has area code "11".
+ assertEquals(2, phoneUtil.getLengthOfGeographicalAreaCode(AR_NUMBER));
+
+ // Google Sydney, which has area code "2".
+ assertEquals(1, phoneUtil.getLengthOfGeographicalAreaCode(AU_NUMBER));
+
+ // Italian numbers - there is no national prefix, but it still has an area code.
+ assertEquals(2, phoneUtil.getLengthOfGeographicalAreaCode(IT_NUMBER));
+
+ // Google Singapore. Singapore has no area code and no national prefix.
+ assertEquals(0, phoneUtil.getLengthOfGeographicalAreaCode(SG_NUMBER));
+
+ // 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() {
+ // Google MTV, which has national destination code (NDC) "650".
+ assertEquals(3, phoneUtil.getLengthOfNationalDestinationCode(US_NUMBER));
+
+ // A North America toll-free number, which has NDC "800".
+ assertEquals(3, phoneUtil.getLengthOfNationalDestinationCode(US_TOLLFREE));
+
+ // Google London, which has NDC "20".
+ assertEquals(2, phoneUtil.getLengthOfNationalDestinationCode(GB_NUMBER));
+
+ // A UK mobile phone, which has NDC "7912".
+ assertEquals(4, phoneUtil.getLengthOfNationalDestinationCode(GB_MOBILE));
+
+ // Google Buenos Aires, which has NDC "11".
+ assertEquals(2, phoneUtil.getLengthOfNationalDestinationCode(AR_NUMBER));
+
+ // An Argentinian mobile which has NDC "911".
+ assertEquals(3, phoneUtil.getLengthOfNationalDestinationCode(AR_MOBILE));
+
+ // Google Sydney, which has NDC "2".
+ assertEquals(1, phoneUtil.getLengthOfNationalDestinationCode(AU_NUMBER));
+
+ // Google Singapore, which has NDC "6521".
+ assertEquals(4, phoneUtil.getLengthOfNationalDestinationCode(SG_NUMBER));
+
+ // An invalid US number (1 digit shorter), which has no NDC.
+ assertEquals(0, phoneUtil.getLengthOfNationalDestinationCode(US_SHORT_BY_ONE_NUMBER));
+
+ // 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 testGetCountryMobileToken() {
+ assertEquals("1", PhoneNumberUtil.getCountryMobileToken(phoneUtil.getCountryCodeForRegion(
+ RegionCode.MX)));
+
+ // Country calling code for Sweden, which has no mobile token.
+ assertEquals("", PhoneNumberUtil.getCountryMobileToken(phoneUtil.getCountryCodeForRegion(
+ RegionCode.SE)));
+ }
+
+ public void testGetNationalSignificantNumber() {
+ assertEquals("6502530000", phoneUtil.getNationalSignificantNumber(US_NUMBER));
+
+ // An Italian mobile number.
+ assertEquals("345678901", phoneUtil.getNationalSignificantNumber(IT_MOBILE));
+
+ // An Italian fixed line number.
+ assertEquals("0236618300", phoneUtil.getNationalSignificantNumber(IT_NUMBER));
+
+ assertEquals("12345678", phoneUtil.getNationalSignificantNumber(INTERNATIONAL_TOLL_FREE));
+ }
+
+ public void testGetExampleNumber() {
+ assertEquals(DE_NUMBER, phoneUtil.getExampleNumber(RegionCode.DE));
+
+ assertEquals(DE_NUMBER,
+ phoneUtil.getExampleNumberForType(RegionCode.DE,
+ PhoneNumberUtil.PhoneNumberType.FIXED_LINE));
+ assertEquals(null,
+ phoneUtil.getExampleNumberForType(RegionCode.DE,
+ PhoneNumberUtil.PhoneNumberType.MOBILE));
+ // For the US, the example number is placed under general description, and hence should be used
+ // for both fixed line and mobile, so neither of these should return null.
+ assertNotNull(phoneUtil.getExampleNumberForType(RegionCode.US,
+ PhoneNumberUtil.PhoneNumberType.FIXED_LINE));
+ assertNotNull(phoneUtil.getExampleNumberForType(RegionCode.US,
+ PhoneNumberUtil.PhoneNumberType.MOBILE));
+ // 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));
+ assertEquals(UNIVERSAL_PREMIUM_RATE, phoneUtil.getExampleNumberForNonGeoEntity(979));
+ }
+
+ public void testConvertAlphaCharactersInNumber() {
+ String input = "1800-ABC-DEF";
+ // Alpha chars are converted to digits; everything else is left untouched.
+ String expectedOutput = "1800-222-333";
+ assertEquals(expectedOutput, PhoneNumberUtil.convertAlphaCharactersInNumber(input));
+ }
+
+ public void testNormaliseRemovePunctuation() {
+ String inputNumber = "034-56&+#2\u00AD34";
+ String expectedOutput = "03456234";
+ assertEquals("Conversion did not correctly remove punctuation",
+ expectedOutput,
+ PhoneNumberUtil.normalize(inputNumber));
+ }
+
+ public void testNormaliseReplaceAlphaCharacters() {
+ String inputNumber = "034-I-am-HUNGRY";
+ String expectedOutput = "034426486479";
+ assertEquals("Conversion did not correctly replace alpha characters",
+ expectedOutput,
+ PhoneNumberUtil.normalize(inputNumber));
+ }
+
+ public void testNormaliseOtherDigits() {
+ String inputNumber = "\uFF125\u0665";
+ String expectedOutput = "255";
+ assertEquals("Conversion did not correctly replace non-latin digits",
+ expectedOutput,
+ PhoneNumberUtil.normalize(inputNumber));
+ // Eastern-Arabic digits.
+ inputNumber = "\u06F52\u06F0";
+ expectedOutput = "520";
+ assertEquals("Conversion did not correctly replace non-latin digits",
+ expectedOutput,
+ PhoneNumberUtil.normalize(inputNumber));
+ }
+
+ public void testNormaliseStripAlphaCharacters() {
+ String inputNumber = "034-56&+a#234";
+ String expectedOutput = "03456234";
+ assertEquals("Conversion did not correctly remove alpha character",
+ expectedOutput,
+ PhoneNumberUtil.normalizeDigitsOnly(inputNumber));
+ }
+
+ public void testNormaliseStripNonDiallableCharacters() {
+ String inputNumber = "03*4-56&+a#234";
+ String expectedOutput = "03*456+234";
+ assertEquals("Conversion did not correctly remove non-diallable characters",
+ expectedOutput,
+ PhoneNumberUtil.normalizeDiallableCharsOnly(inputNumber));
+ }
+
+ public void testFormatUSNumber() {
+ assertEquals("650 253 0000", phoneUtil.format(US_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 650 253 0000", phoneUtil.format(US_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+
+ assertEquals("800 253 0000", phoneUtil.format(US_TOLLFREE, PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 800 253 0000", phoneUtil.format(US_TOLLFREE, PhoneNumberFormat.INTERNATIONAL));
+
+ assertEquals("900 253 0000", phoneUtil.format(US_PREMIUM, PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 900 253 0000", phoneUtil.format(US_PREMIUM, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("tel:+1-900-253-0000", phoneUtil.format(US_PREMIUM, PhoneNumberFormat.RFC3966));
+ // Numbers with all zeros in the national number part will be formatted by using the raw_input
+ // if that is available no matter which format is specified.
+ assertEquals("000-000-0000",
+ phoneUtil.format(US_SPOOF_WITH_RAW_INPUT, PhoneNumberFormat.NATIONAL));
+ assertEquals("0", phoneUtil.format(US_SPOOF, PhoneNumberFormat.NATIONAL));
+ }
+
+ public void testFormatBSNumber() {
+ assertEquals("242 365 1234", phoneUtil.format(BS_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 242 365 1234", phoneUtil.format(BS_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatGBNumber() {
+ assertEquals("(020) 7031 3000", phoneUtil.format(GB_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+44 20 7031 3000", phoneUtil.format(GB_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+
+ assertEquals("(07912) 345 678", phoneUtil.format(GB_MOBILE, PhoneNumberFormat.NATIONAL));
+ assertEquals("+44 7912 345 678", phoneUtil.format(GB_MOBILE, PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatDENumber() {
+ PhoneNumber deNumber = new PhoneNumber();
+ deNumber.setCountryCode(49).setNationalNumber(301234L);
+ assertEquals("030/1234", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 30/1234", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("tel:+49-30-1234", phoneUtil.format(deNumber, PhoneNumberFormat.RFC3966));
+
+ deNumber.clear();
+ deNumber.setCountryCode(49).setNationalNumber(291123L);
+ assertEquals("0291 123", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 291 123", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL));
+
+ deNumber.clear();
+ deNumber.setCountryCode(49).setNationalNumber(29112345678L);
+ assertEquals("0291 12345678", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 291 12345678", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL));
+
+ deNumber.clear();
+ deNumber.setCountryCode(49).setNationalNumber(912312345L);
+ assertEquals("09123 12345", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 9123 12345", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL));
+ deNumber.clear();
+ deNumber.setCountryCode(49).setNationalNumber(80212345L);
+ assertEquals("08021 2345", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 8021 2345", phoneUtil.format(deNumber, PhoneNumberFormat.INTERNATIONAL));
+ // Note this number is correctly formatted without national prefix. Most of the numbers that
+ // are treated as invalid numbers by the library are short numbers, and they are usually not
+ // dialed with national prefix.
+ assertEquals("1234", phoneUtil.format(DE_SHORT_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 1234", phoneUtil.format(DE_SHORT_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+
+ deNumber.clear();
+ deNumber.setCountryCode(49).setNationalNumber(41341234);
+ assertEquals("04134 1234", phoneUtil.format(deNumber, PhoneNumberFormat.NATIONAL));
+ }
+
+ public void testFormatITNumber() {
+ assertEquals("02 3661 8300", phoneUtil.format(IT_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+39 02 3661 8300", phoneUtil.format(IT_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+390236618300", phoneUtil.format(IT_NUMBER, PhoneNumberFormat.E164));
+
+ assertEquals("345 678 901", phoneUtil.format(IT_MOBILE, PhoneNumberFormat.NATIONAL));
+ assertEquals("+39 345 678 901", phoneUtil.format(IT_MOBILE, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+39345678901", phoneUtil.format(IT_MOBILE, PhoneNumberFormat.E164));
+ }
+
+ public void testFormatAUNumber() {
+ assertEquals("02 3661 8300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+61 2 3661 8300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+61236618300", phoneUtil.format(AU_NUMBER, PhoneNumberFormat.E164));
+
+ PhoneNumber auNumber = new PhoneNumber().setCountryCode(61).setNationalNumber(1800123456L);
+ assertEquals("1800 123 456", phoneUtil.format(auNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("+61 1800 123 456", phoneUtil.format(auNumber, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+611800123456", phoneUtil.format(auNumber, PhoneNumberFormat.E164));
+ }
+
+ public void testFormatARNumber() {
+ assertEquals("011 8765-4321", phoneUtil.format(AR_NUMBER, PhoneNumberFormat.NATIONAL));
+ assertEquals("+54 11 8765-4321", phoneUtil.format(AR_NUMBER, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+541187654321", phoneUtil.format(AR_NUMBER, PhoneNumberFormat.E164));
+
+ assertEquals("011 15 8765-4321", phoneUtil.format(AR_MOBILE, PhoneNumberFormat.NATIONAL));
+ assertEquals("+54 9 11 8765 4321", phoneUtil.format(AR_MOBILE,
+ PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+5491187654321", phoneUtil.format(AR_MOBILE, PhoneNumberFormat.E164));
+ }
+
+ public void testFormatMXNumber() {
+ assertEquals("045 234 567 8900", phoneUtil.format(MX_MOBILE1, PhoneNumberFormat.NATIONAL));
+ assertEquals("+52 1 234 567 8900", phoneUtil.format(
+ MX_MOBILE1, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+5212345678900", phoneUtil.format(MX_MOBILE1, PhoneNumberFormat.E164));
+
+ assertEquals("045 55 1234 5678", phoneUtil.format(MX_MOBILE2, PhoneNumberFormat.NATIONAL));
+ assertEquals("+52 1 55 1234 5678", phoneUtil.format(
+ MX_MOBILE2, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+5215512345678", phoneUtil.format(MX_MOBILE2, PhoneNumberFormat.E164));
+
+ assertEquals("01 33 1234 5678", phoneUtil.format(MX_NUMBER1, PhoneNumberFormat.NATIONAL));
+ assertEquals("+52 33 1234 5678", phoneUtil.format(MX_NUMBER1, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+523312345678", phoneUtil.format(MX_NUMBER1, PhoneNumberFormat.E164));
+
+ assertEquals("01 821 123 4567", phoneUtil.format(MX_NUMBER2, PhoneNumberFormat.NATIONAL));
+ assertEquals("+52 821 123 4567", phoneUtil.format(MX_NUMBER2, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+528211234567", phoneUtil.format(MX_NUMBER2, PhoneNumberFormat.E164));
+ }
+
+ public void testFormatOutOfCountryCallingNumber() {
+ assertEquals("00 1 900 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(US_PREMIUM, RegionCode.DE));
+
+ assertEquals("1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.BS));
+
+ assertEquals("00 1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.PL));
+
+ assertEquals("011 44 7912 345 678",
+ phoneUtil.formatOutOfCountryCallingNumber(GB_MOBILE, RegionCode.US));
+
+ assertEquals("00 49 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, RegionCode.GB));
+ // Note this number is correctly formatted without national prefix. Most of the numbers that
+ // are treated as invalid numbers by the library are short numbers, and they are usually not
+ // dialed with national prefix.
+ assertEquals("1234", phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, RegionCode.DE));
+
+ assertEquals("011 39 02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.US));
+ assertEquals("02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.IT));
+ assertEquals("+39 02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.SG));
+
+ assertEquals("6521 8000",
+ phoneUtil.formatOutOfCountryCallingNumber(SG_NUMBER, RegionCode.SG));
+
+ assertEquals("011 54 9 11 8765 4321",
+ phoneUtil.formatOutOfCountryCallingNumber(AR_MOBILE, RegionCode.US));
+ assertEquals("011 800 1234 5678",
+ phoneUtil.formatOutOfCountryCallingNumber(INTERNATIONAL_TOLL_FREE, RegionCode.US));
+
+ PhoneNumber arNumberWithExtn = new PhoneNumber().mergeFrom(AR_MOBILE).setExtension("1234");
+ assertEquals("011 54 9 11 8765 4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.US));
+ assertEquals("0011 54 9 11 8765 4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.AU));
+ assertEquals("011 15 8765-4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, RegionCode.AR));
+ }
+
+ public void testFormatOutOfCountryWithInvalidRegion() {
+ // 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, 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() {
+ // This should use 0011, since that is the preferred international prefix (both 0011 and 0012
+ // are accepted as possible international prefixes in our test metadta.)
+ assertEquals("0011 39 02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.AU));
+ }
+
+ public void testFormatOutOfCountryKeepingAlphaChars() {
+ PhoneNumber alphaNumericNumber = new PhoneNumber();
+ alphaNumericNumber.setCountryCode(1).setNationalNumber(8007493524L)
+ .setRawInput("1800 six-flag");
+ assertEquals("0011 1 800 SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ alphaNumericNumber.setRawInput("1-800-SIX-flag");
+ assertEquals("0011 1 800-SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ alphaNumericNumber.setRawInput("Call us from UK: 00 1 800 SIX-flag");
+ assertEquals("0011 1 800 SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ alphaNumericNumber.setRawInput("800 SIX-flag");
+ assertEquals("0011 1 800 SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ // Formatting from within the NANPA region.
+ assertEquals("1 800 SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.US));
+
+ assertEquals("1 800 SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.BS));
+
+ // Testing that if the raw input doesn't exist, it is formatted using
+ // formatOutOfCountryCallingNumber.
+ alphaNumericNumber.clearRawInput();
+ assertEquals("00 1 800 749 3524",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE));
+
+ // Testing AU alpha number formatted from Australia.
+ alphaNumericNumber.setCountryCode(61).setNationalNumber(827493524L)
+ .setRawInput("+61 82749-FLAG");
+ // This number should have the national prefix fixed.
+ assertEquals("082749-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ alphaNumericNumber.setRawInput("082749-FLAG");
+ assertEquals("082749-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ alphaNumericNumber.setNationalNumber(18007493524L).setRawInput("1-800-SIX-flag");
+ // This number should not have the national prefix prefixed, in accordance with the override for
+ // this specific formatting rule.
+ assertEquals("1-800-SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AU));
+
+ // The metadata should not be permanently changed, since we copied it before modifying patterns.
+ // Here we check this.
+ alphaNumericNumber.setNationalNumber(1800749352L);
+ assertEquals("1800 749 352",
+ phoneUtil.formatOutOfCountryCallingNumber(alphaNumericNumber, RegionCode.AU));
+
+ // Testing a region with multiple international prefixes.
+ assertEquals("+61 1-800-SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.SG));
+ // Testing the case of calling from a non-supported region.
+ assertEquals("+61 1-800-SIX-FLAG",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ));
+
+ // Testing the case with an invalid country calling code.
+ alphaNumericNumber.setCountryCode(0).setNationalNumber(18007493524L)
+ .setRawInput("1-800-SIX-flag");
+ // Uses the raw input only.
+ assertEquals("1-800-SIX-flag",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE));
+
+ // Testing the case of an invalid alpha number.
+ alphaNumericNumber.setCountryCode(1).setNationalNumber(80749L).setRawInput("180-SIX");
+ // No country-code stripping can be done.
+ assertEquals("00 1 180-SIX",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.DE));
+
+ // Testing the case of calling from a non-supported region.
+ alphaNumericNumber.setCountryCode(1).setNationalNumber(80749L).setRawInput("180-SIX");
+ // No country-code stripping can be done since the number is invalid.
+ assertEquals("+1 180-SIX",
+ phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ));
+ }
+
+ public void testFormatWithCarrierCode() {
+ // We only support this for AR in our test metadata, and only for mobile numbers starting with
+ // certain values.
+ PhoneNumber arMobile = new PhoneNumber().setCountryCode(54).setNationalNumber(92234654321L);
+ assertEquals("02234 65-4321", phoneUtil.format(arMobile, PhoneNumberFormat.NATIONAL));
+ // Here we force 14 as the carrier code.
+ assertEquals("02234 14 65-4321",
+ phoneUtil.formatNationalNumberWithCarrierCode(arMobile, "14"));
+ // Here we force the number to be shown with no carrier code.
+ assertEquals("02234 65-4321",
+ phoneUtil.formatNationalNumberWithCarrierCode(arMobile, ""));
+ // Here the international rule is used, so no carrier code should be present.
+ 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() {
+ // We only support this for AR in our test metadata.
+ PhoneNumber arNumber = new PhoneNumber();
+ arNumber.setCountryCode(54).setNationalNumber(91234125678L);
+ // Test formatting with no preferred carrier code stored in the number itself.
+ assertEquals("01234 15 12-5678",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(arNumber, "15"));
+ assertEquals("01234 12-5678",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(arNumber, ""));
+ // Test formatting with preferred carrier code present.
+ arNumber.setPreferredDomesticCarrierCode("19");
+ assertEquals("01234 12-5678", phoneUtil.format(arNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("01234 19 12-5678",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(arNumber, "15"));
+ assertEquals("01234 19 12-5678",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(arNumber, ""));
+ // When the preferred_domestic_carrier_code is present (even when it contains an empty string),
+ // use it instead of the default carrier code passed in.
+ arNumber.setPreferredDomesticCarrierCode("");
+ assertEquals("01234 12-5678",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(arNumber, "15"));
+ // We don't support this for the US so there should be no change.
+ PhoneNumber usNumber = new PhoneNumber();
+ usNumber.setCountryCode(1).setNationalNumber(4241231234L).setPreferredDomesticCarrierCode("99");
+ assertEquals("424 123 1234", phoneUtil.format(usNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals("424 123 1234",
+ phoneUtil.formatNationalNumberWithPreferredCarrierCode(usNumber, "15"));
+ }
+
+ public void testFormatNumberForMobileDialing() {
+ // Numbers are normally dialed in national format in-country, and international format from
+ // outside the country.
+ assertEquals("030123456",
+ phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.DE, false));
+ assertEquals("+4930123456",
+ phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.CH, false));
+ PhoneNumber deNumberWithExtn = new PhoneNumber().mergeFrom(DE_NUMBER).setExtension("1234");
+ assertEquals("030123456",
+ phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.DE, false));
+ assertEquals("+4930123456",
+ phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.CH, false));
+
+ // US toll free numbers are marked as noInternationalDialling in the test metadata for testing
+ // purposes. For such numbers, we expect nothing to be returned when the region code is not the
+ // same one.
+ assertEquals("800 253 0000",
+ phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.US,
+ true /* keep formatting */));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.CN, true));
+ assertEquals("+1 650 253 0000",
+ phoneUtil.formatNumberForMobileDialing(US_NUMBER, RegionCode.US, true));
+ PhoneNumber usNumberWithExtn = new PhoneNumber().mergeFrom(US_NUMBER).setExtension("1234");
+ assertEquals("+1 650 253 0000",
+ phoneUtil.formatNumberForMobileDialing(usNumberWithExtn, RegionCode.US, true));
+
+ assertEquals("8002530000",
+ phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.US,
+ false /* remove formatting */));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.CN, false));
+ assertEquals("+16502530000",
+ phoneUtil.formatNumberForMobileDialing(US_NUMBER, RegionCode.US, false));
+ assertEquals("+16502530000",
+ phoneUtil.formatNumberForMobileDialing(usNumberWithExtn, RegionCode.US, false));
+
+ // An invalid US number, which is one digit too long.
+ assertEquals("+165025300001",
+ phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER, RegionCode.US, false));
+ assertEquals("+1 65025300001",
+ phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER, RegionCode.US, true));
+
+ // Star numbers. In real life they appear in Israel, but we have them in JP in our test
+ // metadata.
+ assertEquals("*2345",
+ phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER, RegionCode.JP, false));
+ assertEquals("*2345",
+ phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER, RegionCode.JP, true));
+
+ assertEquals("+80012345678",
+ phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.JP, false));
+ assertEquals("+800 1234 5678",
+ phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.JP, true));
+
+ // UAE numbers beginning with 600 (classified as UAN) need to be dialled without +971 locally.
+ assertEquals("+971600123456",
+ phoneUtil.formatNumberForMobileDialing(AE_UAN, RegionCode.JP, false));
+ assertEquals("600123456",
+ phoneUtil.formatNumberForMobileDialing(AE_UAN, RegionCode.AE, false));
+
+ assertEquals("+523312345678",
+ phoneUtil.formatNumberForMobileDialing(MX_NUMBER1, RegionCode.MX, false));
+ assertEquals("+523312345678",
+ phoneUtil.formatNumberForMobileDialing(MX_NUMBER1, RegionCode.US, false));
+
+ // Non-geographical numbers should always be dialed in international format.
+ assertEquals("+80012345678",
+ phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.US, false));
+ assertEquals("+80012345678",
+ phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE, RegionCode.UN001, false));
+
+ // Test that a short number is formatted correctly for mobile dialing within the region,
+ // and is not diallable from outside the region.
+ PhoneNumber deShortNumber = new PhoneNumber().setCountryCode(49).setNationalNumber(123L);
+ assertEquals("123", phoneUtil.formatNumberForMobileDialing(deShortNumber, RegionCode.DE,
+ false));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(deShortNumber, RegionCode.IT, false));
+
+ // Test the special logic for Hungary, where the national prefix must be added before dialing
+ // from a mobile phone for regular length numbers, but not for short numbers.
+ PhoneNumber huRegularNumber = new PhoneNumber().setCountryCode(36)
+ .setNationalNumber(301234567L);
+ assertEquals("06301234567", phoneUtil.formatNumberForMobileDialing(huRegularNumber,
+ RegionCode.HU, false));
+ assertEquals("+36301234567", phoneUtil.formatNumberForMobileDialing(huRegularNumber,
+ RegionCode.JP, false));
+ PhoneNumber huShortNumber = new PhoneNumber().setCountryCode(36).setNationalNumber(104L);
+ assertEquals("104", phoneUtil.formatNumberForMobileDialing(huShortNumber, RegionCode.HU,
+ false));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(huShortNumber, RegionCode.JP, false));
+
+ // Test the special logic for NANPA countries, for which regular length phone numbers are always
+ // output in international format, but short numbers are in national format.
+ assertEquals("+16502530000", phoneUtil.formatNumberForMobileDialing(US_NUMBER,
+ RegionCode.US, false));
+ assertEquals("+16502530000", phoneUtil.formatNumberForMobileDialing(US_NUMBER,
+ RegionCode.CA, false));
+ assertEquals("+16502530000", phoneUtil.formatNumberForMobileDialing(US_NUMBER,
+ RegionCode.BR, false));
+ PhoneNumber usShortNumber = new PhoneNumber().setCountryCode(1).setNationalNumber(911L);
+ assertEquals("911", phoneUtil.formatNumberForMobileDialing(usShortNumber, RegionCode.US,
+ false));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(usShortNumber, RegionCode.CA, false));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(usShortNumber, RegionCode.BR, false));
+
+ // Test that the Australian emergency number 000 is formatted correctly.
+ PhoneNumber auNumber = new PhoneNumber().setCountryCode(61).setNationalNumber(0L)
+ .setItalianLeadingZero(true).setNumberOfLeadingZeros(2);
+ assertEquals("000", phoneUtil.formatNumberForMobileDialing(auNumber, RegionCode.AU, false));
+ assertEquals("", phoneUtil.formatNumberForMobileDialing(auNumber, RegionCode.NZ, false));
+ }
+
+ public void testFormatByPattern() {
+ NumberFormat newNumFormat = new NumberFormat();
+ newNumFormat.setPattern("(\\d{3})(\\d{3})(\\d{4})");
+ newNumFormat.setFormat("($1) $2-$3");
+ List<NumberFormat> newNumberFormats = new ArrayList<NumberFormat>();
+ newNumberFormats.add(newNumFormat);
+
+ assertEquals("(650) 253-0000", phoneUtil.formatByPattern(US_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ assertEquals("+1 (650) 253-0000", phoneUtil.formatByPattern(US_NUMBER,
+ PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+ assertEquals("tel:+1-650-253-0000", phoneUtil.formatByPattern(US_NUMBER,
+ PhoneNumberFormat.RFC3966,
+ newNumberFormats));
+
+ // $NP is set to '1' for the US. Here we check that for other NANPA countries the US rules are
+ // followed.
+ newNumFormat.setNationalPrefixFormattingRule("$NP ($FG)");
+ newNumFormat.setFormat("$1 $2-$3");
+ assertEquals("1 (242) 365-1234",
+ phoneUtil.formatByPattern(BS_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ assertEquals("+1 242 365-1234",
+ phoneUtil.formatByPattern(BS_NUMBER, PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+
+ newNumFormat.setPattern("(\\d{2})(\\d{5})(\\d{3})");
+ newNumFormat.setFormat("$1-$2 $3");
+ newNumberFormats.set(0, newNumFormat);
+
+ assertEquals("02-36618 300",
+ phoneUtil.formatByPattern(IT_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ assertEquals("+39 02-36618 300",
+ phoneUtil.formatByPattern(IT_NUMBER, PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+
+ newNumFormat.setNationalPrefixFormattingRule("$NP$FG");
+ newNumFormat.setPattern("(\\d{2})(\\d{4})(\\d{4})");
+ newNumFormat.setFormat("$1 $2 $3");
+ newNumberFormats.set(0, newNumFormat);
+ assertEquals("020 7031 3000",
+ phoneUtil.formatByPattern(GB_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+
+ newNumFormat.setNationalPrefixFormattingRule("($NP$FG)");
+ assertEquals("(020) 7031 3000",
+ phoneUtil.formatByPattern(GB_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+
+ newNumFormat.setNationalPrefixFormattingRule("");
+ assertEquals("20 7031 3000",
+ phoneUtil.formatByPattern(GB_NUMBER, PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+
+ assertEquals("+44 20 7031 3000",
+ phoneUtil.formatByPattern(GB_NUMBER, PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+ }
+
+ 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() {
+ PhoneNumber nzNumber = new PhoneNumber().mergeFrom(NZ_NUMBER).setExtension("1234");
+ // Uses default extension prefix:
+ assertEquals("03-331 6005 ext. 1234", phoneUtil.format(nzNumber, PhoneNumberFormat.NATIONAL));
+ // Uses RFC 3966 syntax.
+ assertEquals("tel:+64-3-331-6005;ext=1234",
+ phoneUtil.format(nzNumber, PhoneNumberFormat.RFC3966));
+ // Extension prefix overridden in the territory information for the US:
+ PhoneNumber usNumberWithExtension = new PhoneNumber().mergeFrom(US_NUMBER).setExtension("4567");
+ assertEquals("650 253 0000 extn. 4567", phoneUtil.format(usNumberWithExtension,
+ PhoneNumberFormat.NATIONAL));
+ }
+
+ public void testFormatInOriginalFormat() throws Exception {
+ PhoneNumber number1 = phoneUtil.parseAndKeepRawInput("+442087654321", RegionCode.GB);
+ assertEquals("+44 20 8765 4321", phoneUtil.formatInOriginalFormat(number1, RegionCode.GB));
+
+ PhoneNumber number2 = phoneUtil.parseAndKeepRawInput("02087654321", RegionCode.GB);
+ assertEquals("(020) 8765 4321", phoneUtil.formatInOriginalFormat(number2, RegionCode.GB));
+
+ PhoneNumber number3 = phoneUtil.parseAndKeepRawInput("011442087654321", RegionCode.US);
+ assertEquals("011 44 20 8765 4321", phoneUtil.formatInOriginalFormat(number3, RegionCode.US));
+
+ PhoneNumber number4 = phoneUtil.parseAndKeepRawInput("442087654321", RegionCode.GB);
+ assertEquals("44 20 8765 4321", phoneUtil.formatInOriginalFormat(number4, RegionCode.GB));
+
+ PhoneNumber number5 = phoneUtil.parse("+442087654321", RegionCode.GB);
+ assertEquals("(020) 8765 4321", phoneUtil.formatInOriginalFormat(number5, RegionCode.GB));
+
+ // Invalid numbers that we have a formatting pattern for should be formatted properly. Note area
+ // codes starting with 7 are intentionally excluded in the test metadata for testing purposes.
+ PhoneNumber number6 = phoneUtil.parseAndKeepRawInput("7345678901", RegionCode.US);
+ assertEquals("734 567 8901", phoneUtil.formatInOriginalFormat(number6, RegionCode.US));
+
+ // 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("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));
+ // Make sure no metadata is modified as a result of the previous function call.
+ assertEquals("(020) 8765 4321", phoneUtil.formatInOriginalFormat(number5, 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));
+
+ // Test the star sign is not removed from or added to the original input by this method.
+ PhoneNumber starNumber = phoneUtil.parseAndKeepRawInput("*1234", RegionCode.JP);
+ 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() {
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE, phoneUtil.getNumberType(US_PREMIUM));
+
+ PhoneNumber premiumRateNumber = new PhoneNumber();
+ premiumRateNumber.setCountryCode(39).setNationalNumber(892123L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber));
+
+ premiumRateNumber.clear();
+ premiumRateNumber.setCountryCode(44).setNationalNumber(9187654321L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber));
+
+ premiumRateNumber.clear();
+ premiumRateNumber.setCountryCode(49).setNationalNumber(9001654321L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber));
+
+ premiumRateNumber.clear();
+ premiumRateNumber.setCountryCode(49).setNationalNumber(90091234567L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber));
+
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(UNIVERSAL_PREMIUM_RATE));
+ }
+
+ public void testIsTollFree() {
+ PhoneNumber tollFreeNumber = new PhoneNumber();
+
+ tollFreeNumber.setCountryCode(1).setNationalNumber(8881234567L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber));
+
+ tollFreeNumber.clear();
+ tollFreeNumber.setCountryCode(39).setNationalNumber(803123L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber));
+
+ tollFreeNumber.clear();
+ tollFreeNumber.setCountryCode(44).setNationalNumber(8012345678L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber));
+
+ tollFreeNumber.clear();
+ 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() {
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE, phoneUtil.getNumberType(BS_MOBILE));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE, phoneUtil.getNumberType(GB_MOBILE));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE, phoneUtil.getNumberType(IT_MOBILE));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE, phoneUtil.getNumberType(AR_MOBILE));
+
+ PhoneNumber mobileNumber = new PhoneNumber();
+ mobileNumber.setCountryCode(49).setNationalNumber(15123456789L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE, phoneUtil.getNumberType(mobileNumber));
+ }
+
+ public void testIsFixedLine() {
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE, phoneUtil.getNumberType(BS_NUMBER));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE, phoneUtil.getNumberType(IT_NUMBER));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE, phoneUtil.getNumberType(GB_NUMBER));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE, phoneUtil.getNumberType(DE_NUMBER));
+ }
+
+ public void testIsFixedLineAndMobile() {
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE_OR_MOBILE,
+ phoneUtil.getNumberType(US_NUMBER));
+
+ PhoneNumber fixedLineAndMobileNumber = new PhoneNumber().
+ setCountryCode(54).setNationalNumber(1987654321L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE_OR_MOBILE,
+ phoneUtil.getNumberType(fixedLineAndMobileNumber));
+ }
+
+ public void testIsSharedCost() {
+ PhoneNumber gbNumber = new PhoneNumber();
+ gbNumber.setCountryCode(44).setNationalNumber(8431231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.SHARED_COST, phoneUtil.getNumberType(gbNumber));
+ }
+
+ public void testIsVoip() {
+ PhoneNumber gbNumber = new PhoneNumber();
+ gbNumber.setCountryCode(44).setNationalNumber(5631231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.VOIP, phoneUtil.getNumberType(gbNumber));
+ }
+
+ public void testIsPersonalNumber() {
+ PhoneNumber gbNumber = new PhoneNumber();
+ gbNumber.setCountryCode(44).setNationalNumber(7031231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PERSONAL_NUMBER,
+ phoneUtil.getNumberType(gbNumber));
+ }
+
+ public void testIsUnknown() {
+ // Invalid numbers should be of type UNKNOWN.
+ assertEquals(PhoneNumberUtil.PhoneNumberType.UNKNOWN, phoneUtil.getNumberType(US_LOCAL_NUMBER));
+ }
+
+ public void testIsValidNumber() {
+ assertTrue(phoneUtil.isValidNumber(US_NUMBER));
+ assertTrue(phoneUtil.isValidNumber(IT_NUMBER));
+ assertTrue(phoneUtil.isValidNumber(GB_MOBILE));
+ assertTrue(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE));
+ assertTrue(phoneUtil.isValidNumber(UNIVERSAL_PREMIUM_RATE));
+
+ PhoneNumber nzNumber = new PhoneNumber().setCountryCode(64).setNationalNumber(21387835L);
+ assertTrue(phoneUtil.isValidNumber(nzNumber));
+ }
+
+ public void testIsValidForRegion() {
+ // This number is valid for the Bahamas, but is not a valid US number.
+ assertTrue(phoneUtil.isValidNumber(BS_NUMBER));
+ assertTrue(phoneUtil.isValidNumberForRegion(BS_NUMBER, RegionCode.BS));
+ assertFalse(phoneUtil.isValidNumberForRegion(BS_NUMBER, RegionCode.US));
+ PhoneNumber bsInvalidNumber =
+ new PhoneNumber().setCountryCode(1).setNationalNumber(2421232345L);
+ // This number is no longer valid.
+ assertFalse(phoneUtil.isValidNumber(bsInvalidNumber));
+
+ // La Mayotte and Reunion use 'leadingDigits' to differentiate them.
+ PhoneNumber reNumber = new PhoneNumber();
+ reNumber.setCountryCode(262).setNationalNumber(262123456L);
+ assertTrue(phoneUtil.isValidNumber(reNumber));
+ assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE));
+ assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT));
+ // Now change the number to be a number for La Mayotte.
+ reNumber.setNationalNumber(269601234L);
+ assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT));
+ assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE));
+ // This number is no longer valid for La Reunion.
+ reNumber.setNationalNumber(269123456L);
+ assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT));
+ assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE));
+ assertFalse(phoneUtil.isValidNumber(reNumber));
+ // However, it should be recognised as from La Mayotte, since it is valid for this region.
+ assertEquals(RegionCode.YT, phoneUtil.getRegionCodeForNumber(reNumber));
+ // This number is valid in both places.
+ 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));
+ assertFalse(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE, RegionCode.ZZ));
+
+ PhoneNumber invalidNumber = new PhoneNumber();
+ // Invalid country calling codes.
+ invalidNumber.setCountryCode(3923).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.ZZ));
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.UN001));
+ invalidNumber.setCountryCode(0);
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.UN001));
+ assertFalse(phoneUtil.isValidNumberForRegion(invalidNumber, RegionCode.ZZ));
+ }
+
+ public void testIsNotValidNumber() {
+ assertFalse(phoneUtil.isValidNumber(US_LOCAL_NUMBER));
+
+ PhoneNumber invalidNumber = new PhoneNumber();
+ invalidNumber.setCountryCode(39).setNationalNumber(23661830000L).setItalianLeadingZero(true);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+
+ invalidNumber.clear();
+ invalidNumber.setCountryCode(44).setNationalNumber(791234567L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+
+ invalidNumber.clear();
+ invalidNumber.setCountryCode(49).setNationalNumber(1234L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+
+ invalidNumber.clear();
+ invalidNumber.setCountryCode(64).setNationalNumber(3316005L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+
+ invalidNumber.clear();
+ // Invalid country calling codes.
+ invalidNumber.setCountryCode(3923).setNationalNumber(2366L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber));
+ invalidNumber.setCountryCode(0);
+ 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));
+ assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForCountryCode(979));
+ }
+
+ 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));
+ 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));
+ 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));
+ }
+
+ public void testGetNationalDiallingPrefixForRegion() {
+ assertEquals("1", phoneUtil.getNddPrefixForRegion(RegionCode.US, false));
+ // Test non-main country to see it gets the national dialling prefix for the main country with
+ // that country calling code.
+ assertEquals("1", phoneUtil.getNddPrefixForRegion(RegionCode.BS, false));
+ assertEquals("0", phoneUtil.getNddPrefixForRegion(RegionCode.NZ, false));
+ // Test case with non digit in the national prefix.
+ assertEquals("0~0", phoneUtil.getNddPrefixForRegion(RegionCode.AO, false));
+ assertEquals("00", phoneUtil.getNddPrefixForRegion(RegionCode.AO, true));
+ // 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));
+ }
+
+ public void testIsNANPACountry() {
+ assertTrue(phoneUtil.isNANPACountry(RegionCode.US));
+ assertTrue(phoneUtil.isNANPACountry(RegionCode.BS));
+ assertFalse(phoneUtil.isNANPACountry(RegionCode.DE));
+ assertFalse(phoneUtil.isNANPACountry(RegionCode.ZZ));
+ assertFalse(phoneUtil.isNANPACountry(RegionCode.UN001));
+ assertFalse(phoneUtil.isNANPACountry(null));
+ }
+
+ public void testIsPossibleNumber() {
+ 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));
+ assertTrue(phoneUtil.isPossibleNumber("(650) 253-0000", RegionCode.US));
+ assertTrue(phoneUtil.isPossibleNumber("253-0000", RegionCode.US));
+ assertTrue(phoneUtil.isPossibleNumber("+1 650 253 0000", RegionCode.GB));
+ assertTrue(phoneUtil.isPossibleNumber("+44 20 7031 3000", RegionCode.GB));
+ 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() {
+ // National numbers for country calling code +1 that are within 7 to 10 digits are possible.
+ assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE,
+ phoneUtil.isPossibleNumberWithReason(US_NUMBER));
+
+ assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE,
+ phoneUtil.isPossibleNumberWithReason(US_LOCAL_NUMBER));
+
+ assertEquals(PhoneNumberUtil.ValidationResult.TOO_LONG,
+ phoneUtil.isPossibleNumberWithReason(US_LONG_NUMBER));
+
+ PhoneNumber number = new PhoneNumber();
+ number.setCountryCode(0).setNationalNumber(2530000L);
+ assertEquals(PhoneNumberUtil.ValidationResult.INVALID_COUNTRY_CODE,
+ phoneUtil.isPossibleNumberWithReason(number));
+
+ number.clear();
+ number.setCountryCode(1).setNationalNumber(253000L);
+ assertEquals(PhoneNumberUtil.ValidationResult.TOO_SHORT,
+ phoneUtil.isPossibleNumberWithReason(number));
+
+ number.clear();
+ number.setCountryCode(65).setNationalNumber(1234567890L);
+ assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE,
+ phoneUtil.isPossibleNumberWithReason(number));
+
+ assertEquals(PhoneNumberUtil.ValidationResult.TOO_LONG,
+ phoneUtil.isPossibleNumberWithReason(INTERNATIONAL_TOLL_FREE_TOO_LONG));
+ }
+
+ 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);
+ assertFalse(phoneUtil.isPossibleNumber(number));
+
+ 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() {
+ // GB number 080 1234 5678, but entered with 4 extra digits at the end.
+ PhoneNumber tooLongNumber = new PhoneNumber();
+ tooLongNumber.setCountryCode(44).setNationalNumber(80123456780123L);
+ PhoneNumber validNumber = new PhoneNumber();
+ validNumber.setCountryCode(44).setNationalNumber(8012345678L);
+ assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
+ assertEquals(validNumber, tooLongNumber);
+
+ // IT number 022 3456 7890, but entered with 3 extra digits at the end.
+ tooLongNumber.clear();
+ tooLongNumber.setCountryCode(39).setNationalNumber(2234567890123L).setItalianLeadingZero(true);
+ validNumber.clear();
+ validNumber.setCountryCode(39).setNationalNumber(2234567890L).setItalianLeadingZero(true);
+ assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
+ assertEquals(validNumber, tooLongNumber);
+
+ // US number 650-253-0000, but entered with one additional digit at the end.
+ tooLongNumber.clear();
+ tooLongNumber.mergeFrom(US_LONG_NUMBER);
+ assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
+ assertEquals(US_NUMBER, tooLongNumber);
+
+ tooLongNumber.clear();
+ tooLongNumber.mergeFrom(INTERNATIONAL_TOLL_FREE_TOO_LONG);
+ assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
+ assertEquals(INTERNATIONAL_TOLL_FREE, tooLongNumber);
+
+ // Tests what happens when a valid number is passed in.
+ PhoneNumber validNumberCopy = new PhoneNumber().mergeFrom(validNumber);
+ assertTrue(phoneUtil.truncateTooLongNumber(validNumber));
+ // Tests the number is not modified.
+ assertEquals(validNumberCopy, validNumber);
+
+ // Tests what happens when a number with invalid prefix is passed in.
+ PhoneNumber numberWithInvalidPrefix = new PhoneNumber();
+ // The test metadata says US numbers cannot have prefix 240.
+ numberWithInvalidPrefix.setCountryCode(1).setNationalNumber(2401234567L);
+ PhoneNumber invalidNumberCopy = new PhoneNumber().mergeFrom(numberWithInvalidPrefix);
+ assertFalse(phoneUtil.truncateTooLongNumber(numberWithInvalidPrefix));
+ // Tests the number is not modified.
+ assertEquals(invalidNumberCopy, numberWithInvalidPrefix);
+
+ // Tests what happens when a too short number is passed in.
+ PhoneNumber tooShortNumber = new PhoneNumber().setCountryCode(1).setNationalNumber(1234L);
+ PhoneNumber tooShortNumberCopy = new PhoneNumber().mergeFrom(tooShortNumber);
+ assertFalse(phoneUtil.truncateTooLongNumber(tooShortNumber));
+ // Tests the number is not modified.
+ assertEquals(tooShortNumberCopy, tooShortNumber);
+ }
+
+ public void testIsViablePhoneNumber() {
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("1"));
+ // Only one or two digits before strange non-possible punctuation.
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("1+1+1"));
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("80+0"));
+ // Two digits is viable.
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("00"));
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("111"));
+ // Alpha numbers.
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("0800-4-pizza"));
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("0800-4-PIZZA"));
+ // We need at least three digits before any alpha characters.
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("08-PIZZA"));
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("8-PIZZA"));
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("12. March"));
+ }
+
+ public void testIsViablePhoneNumberNonAscii() {
+ // Only one or two digits before possible punctuation followed by more digits.
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("1\u300034"));
+ assertFalse(PhoneNumberUtil.isViablePhoneNumber("1\u30003+4"));
+ // Unicode variants of possible starting character and other allowed punctuation/digits.
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("\uFF081\uFF09\u30003456789"));
+ // Testing a leading + is okay.
+ assertTrue(PhoneNumberUtil.isViablePhoneNumber("+1\uFF09\u30003456789"));
+ }
+
+ public void testExtractPossibleNumber() {
+ // Removes preceding funky punctuation and letters but leaves the rest untouched.
+ assertEquals("0800-345-600", PhoneNumberUtil.extractPossibleNumber("Tel:0800-345-600"));
+ assertEquals("0800 FOR PIZZA", PhoneNumberUtil.extractPossibleNumber("Tel:0800 FOR PIZZA"));
+ // Should not remove plus sign
+ assertEquals("+800-345-600", PhoneNumberUtil.extractPossibleNumber("Tel:+800-345-600"));
+ // Should recognise wide digits as possible start values.
+ assertEquals("\uFF10\uFF12\uFF13",
+ PhoneNumberUtil.extractPossibleNumber("\uFF10\uFF12\uFF13"));
+ // Dashes are not possible start values and should be removed.
+ assertEquals("\uFF11\uFF12\uFF13",
+ PhoneNumberUtil.extractPossibleNumber("Num-\uFF11\uFF12\uFF13"));
+ // If not possible number present, return empty string.
+ assertEquals("", PhoneNumberUtil.extractPossibleNumber("Num-...."));
+ // Leading brackets are stripped - these are not used when parsing.
+ assertEquals("650) 253-0000", PhoneNumberUtil.extractPossibleNumber("(650) 253-0000"));
+
+ // Trailing non-alpha-numeric characters should be removed.
+ assertEquals("650) 253-0000", PhoneNumberUtil.extractPossibleNumber("(650) 253-0000..- .."));
+ assertEquals("650) 253-0000", PhoneNumberUtil.extractPossibleNumber("(650) 253-0000."));
+ // This case has a trailing RTL char.
+ assertEquals("650) 253-0000", PhoneNumberUtil.extractPossibleNumber("(650) 253-0000\u200F"));
+ }
+
+ public void testMaybeStripNationalPrefix() {
+ PhoneMetadata metadata = new PhoneMetadata();
+ metadata.setNationalPrefixForParsing("34");
+ metadata.setGeneralDesc(new PhoneNumberDesc().setNationalNumberPattern("\\d{4,8}"));
+ StringBuilder numberToStrip = new StringBuilder("34356778");
+ String strippedNumber = "356778";
+ assertTrue(phoneUtil.maybeStripNationalPrefixAndCarrierCode(numberToStrip, metadata, null));
+ assertEquals("Should have had national prefix stripped.",
+ strippedNumber, numberToStrip.toString());
+ // Retry stripping - now the number should not start with the national prefix, so no more
+ // stripping should occur.
+ assertFalse(phoneUtil.maybeStripNationalPrefixAndCarrierCode(numberToStrip, metadata, null));
+ assertEquals("Should have had no change - no national prefix present.",
+ strippedNumber, numberToStrip.toString());
+ // Some countries have no national prefix. Repeat test with none specified.
+ metadata.setNationalPrefixForParsing("");
+ assertFalse(phoneUtil.maybeStripNationalPrefixAndCarrierCode(numberToStrip, metadata, null));
+ assertEquals("Should not strip anything with empty national prefix.",
+ strippedNumber, numberToStrip.toString());
+ // If the resultant number doesn't match the national rule, it shouldn't be stripped.
+ metadata.setNationalPrefixForParsing("3");
+ numberToStrip = new StringBuilder("3123");
+ strippedNumber = "3123";
+ assertFalse(phoneUtil.maybeStripNationalPrefixAndCarrierCode(numberToStrip, metadata, null));
+ assertEquals("Should have had no change - after stripping, it wouldn't have matched " +
+ "the national rule.",
+ strippedNumber, numberToStrip.toString());
+ // Test extracting carrier selection code.
+ metadata.setNationalPrefixForParsing("0(81)?");
+ numberToStrip = new StringBuilder("08122123456");
+ strippedNumber = "22123456";
+ StringBuilder carrierCode = new StringBuilder();
+ assertTrue(phoneUtil.maybeStripNationalPrefixAndCarrierCode(
+ numberToStrip, metadata, carrierCode));
+ assertEquals("81", carrierCode.toString());
+ assertEquals("Should have had national prefix and carrier code stripped.",
+ strippedNumber, numberToStrip.toString());
+ // If there was a transform rule, check it was applied.
+ metadata.setNationalPrefixTransformRule("5$15");
+ // Note that a capturing group is present here.
+ metadata.setNationalPrefixForParsing("0(\\d{2})");
+ numberToStrip = new StringBuilder("031123");
+ String transformedNumber = "5315123";
+ assertTrue(phoneUtil.maybeStripNationalPrefixAndCarrierCode(numberToStrip, metadata, null));
+ assertEquals("Should transform the 031 to a 5315.",
+ transformedNumber, numberToStrip.toString());
+ }
+
+ public void testMaybeStripInternationalPrefix() {
+ String internationalPrefix = "00[39]";
+ StringBuilder numberToStrip = new StringBuilder("0034567700-3898003");
+ // Note the dash is removed as part of the normalization.
+ StringBuilder strippedNumber = new StringBuilder("45677003898003");
+ assertEquals(CountryCodeSource.FROM_NUMBER_WITH_IDD,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ assertEquals("The number supplied was not stripped of its international prefix.",
+ strippedNumber.toString(), numberToStrip.toString());
+ // Now the number no longer starts with an IDD prefix, so it should now report
+ // FROM_DEFAULT_COUNTRY.
+ assertEquals(CountryCodeSource.FROM_DEFAULT_COUNTRY,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+
+ numberToStrip = new StringBuilder("00945677003898003");
+ assertEquals(CountryCodeSource.FROM_NUMBER_WITH_IDD,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ assertEquals("The number supplied was not stripped of its international prefix.",
+ strippedNumber.toString(), numberToStrip.toString());
+ // Test it works when the international prefix is broken up by spaces.
+ numberToStrip = new StringBuilder("00 9 45677003898003");
+ assertEquals(CountryCodeSource.FROM_NUMBER_WITH_IDD,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ assertEquals("The number supplied was not stripped of its international prefix.",
+ strippedNumber.toString(), numberToStrip.toString());
+ // Now the number no longer starts with an IDD prefix, so it should now report
+ // FROM_DEFAULT_COUNTRY.
+ assertEquals(CountryCodeSource.FROM_DEFAULT_COUNTRY,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+
+ // Test the + symbol is also recognised and stripped.
+ numberToStrip = new StringBuilder("+45677003898003");
+ strippedNumber = new StringBuilder("45677003898003");
+ assertEquals(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ assertEquals("The number supplied was not stripped of the plus symbol.",
+ strippedNumber.toString(), numberToStrip.toString());
+
+ // If the number afterwards is a zero, we should not strip this - no country calling code begins
+ // with 0.
+ numberToStrip = new StringBuilder("0090112-3123");
+ strippedNumber = new StringBuilder("00901123123");
+ assertEquals(CountryCodeSource.FROM_DEFAULT_COUNTRY,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ assertEquals("The number supplied had a 0 after the match so shouldn't be stripped.",
+ strippedNumber.toString(), numberToStrip.toString());
+ // Here the 0 is separated by a space from the IDD.
+ numberToStrip = new StringBuilder("009 0-112-3123");
+ assertEquals(CountryCodeSource.FROM_DEFAULT_COUNTRY,
+ phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ }
+
+ public void testMaybeExtractCountryCode() {
+ PhoneNumber number = new PhoneNumber();
+ PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US);
+ // Note that for the US, the IDD is 011.
+ try {
+ String phoneNumber = "011112-3456789";
+ String strippedNumber = "123456789";
+ int countryCallingCode = 1;
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.",
+ countryCallingCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true,
+ number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_NUMBER_WITH_IDD, number.getCountryCodeSource());
+ // Should strip and normalize national significant number.
+ assertEquals("Did not strip off the country calling code correctly.",
+ strippedNumber,
+ numberToFill.toString());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "+6423456789";
+ int countryCallingCode = 64;
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.",
+ countryCallingCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true,
+ number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN, number.getCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "+80012345678";
+ int countryCallingCode = 800;
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Did not extract country calling code " + countryCallingCode + " correctly.",
+ countryCallingCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true,
+ number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN, number.getCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "2345-6789";
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals(
+ "Should not have extracted a country calling code - no international prefix present.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_DEFAULT_COUNTRY, number.getCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "0119991123456789";
+ StringBuilder numberToFill = new StringBuilder();
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number);
+ fail("Should have thrown an exception, no valid country calling code present.");
+ } catch (NumberParseException e) {
+ // Expected.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "(1 610) 619 4466";
+ int countryCallingCode = 1;
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Should have extracted the country calling code of the region passed in",
+ countryCallingCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true,
+ number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN,
+ number.getCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "(1 610) 619 4466";
+ int countryCallingCode = 1;
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Should have extracted the country calling code of the region passed in",
+ countryCallingCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false,
+ number));
+ assertFalse("Should not contain CountryCodeSource.", number.hasCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "(1 610) 619 446";
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Should not have extracted a country calling code - invalid number after " +
+ "extraction of uncertain country calling code.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false,
+ number));
+ assertFalse("Should not contain CountryCodeSource.", number.hasCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ number.clear();
+ try {
+ String phoneNumber = "(1 610) 619";
+ StringBuilder numberToFill = new StringBuilder();
+ assertEquals("Should not have extracted a country calling code - too short number both " +
+ "before and after extraction of uncertain country calling code.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true,
+ number));
+ assertEquals("Did not figure out CountryCodeSource correctly",
+ CountryCodeSource.FROM_DEFAULT_COUNTRY, number.getCountryCodeSource());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ }
+
+ public void testParseNationalNumber() throws Exception {
+ // National prefix attached.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("033316005", RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("33316005", RegionCode.NZ));
+ // National prefix attached and some formatting present.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("03-331 6005", RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("03 331 6005", RegionCode.NZ));
+ // Test parsing RFC3966 format with a phone context.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64", RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:331-6005;phone-context=+64-3", RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:331-6005;phone-context=+64-3", RegionCode.US));
+ assertEquals(NZ_NUMBER, phoneUtil.parse(
+ "My number is tel:03-331-6005;phone-context=+64", RegionCode.NZ));
+ // Test parsing RFC3966 format with optional user-defined parameters. The parameters will appear
+ // after the context if present.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64;a=%A1",
+ RegionCode.NZ));
+ // Test parsing RFC3966 with an ISDN subaddress.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;isub=12345;phone-context=+64",
+ RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:+64-3-331-6005;isub=12345", RegionCode.NZ));
+ // Test parsing RFC3966 with "tel:" missing.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("03-331-6005;phone-context=+64", RegionCode.NZ));
+ // Testing international prefixes.
+ // Should strip country calling code.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("0064 3 331 6005", RegionCode.NZ));
+ // Try again, but this time we have an international number with Region Code US. It should
+ // recognise the country calling code and parse accordingly.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("01164 3 331 6005", RegionCode.US));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", RegionCode.US));
+ // We should ignore the leading plus here, since it is not followed by a valid country code but
+ // instead is followed by the IDD for the US.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+01164 3 331 6005", RegionCode.US));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+0064 3 331 6005", RegionCode.NZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+ 00 64 3 331 6005", RegionCode.NZ));
+
+ assertEquals(US_LOCAL_NUMBER,
+ phoneUtil.parse("tel:253-0000;phone-context=www.google.com", RegionCode.US));
+ assertEquals(US_LOCAL_NUMBER,
+ phoneUtil.parse("tel:253-0000;isub=12345;phone-context=www.google.com", RegionCode.US));
+ // This is invalid because no "+" sign is present as part of phone-context. The phone context
+ // is simply ignored in this case just as if it contains a domain.
+ assertEquals(US_LOCAL_NUMBER,
+ phoneUtil.parse("tel:2530000;isub=12345;phone-context=1-650", RegionCode.US));
+ assertEquals(US_LOCAL_NUMBER,
+ phoneUtil.parse("tel:2530000;isub=12345;phone-context=1234.com", RegionCode.US));
+
+ PhoneNumber nzNumber = new PhoneNumber();
+ nzNumber.setCountryCode(64).setNationalNumber(64123456L);
+ assertEquals(nzNumber, phoneUtil.parse("64(0)64123456", RegionCode.NZ));
+ // Check that using a "/" is fine in a phone number.
+ assertEquals(DE_NUMBER, phoneUtil.parse("301/23456", RegionCode.DE));
+
+ PhoneNumber usNumber = new PhoneNumber();
+ // Check it doesn't use the '1' as a country calling code when parsing if the phone number was
+ // already possible.
+ usNumber.setCountryCode(1).setNationalNumber(1234567890L);
+ assertEquals(usNumber, phoneUtil.parse("123-456-7890", RegionCode.US));
+
+ // Test star numbers. Although this is not strictly valid, we would like to make sure we can
+ // parse the output we produce when formatting the number.
+ assertEquals(JP_STAR_NUMBER, phoneUtil.parse("+81 *2345", RegionCode.JP));
+
+ PhoneNumber shortNumber = new PhoneNumber();
+ shortNumber.setCountryCode(64).setNationalNumber(12L);
+ assertEquals(shortNumber, phoneUtil.parse("12", RegionCode.NZ));
+ }
+
+ public void testParseNumberWithAlphaCharacters() throws Exception {
+ // Test case with alpha characters.
+ PhoneNumber tollfreeNumber = new PhoneNumber();
+ tollfreeNumber.setCountryCode(64).setNationalNumber(800332005L);
+ assertEquals(tollfreeNumber, phoneUtil.parse("0800 DDA 005", RegionCode.NZ));
+ PhoneNumber premiumNumber = new PhoneNumber();
+ premiumNumber.setCountryCode(64).setNationalNumber(9003326005L);
+ assertEquals(premiumNumber, phoneUtil.parse("0900 DDA 6005", RegionCode.NZ));
+ // Not enough alpha characters for them to be considered intentional, so they are stripped.
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 6005a", RegionCode.NZ));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 600a5", RegionCode.NZ));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 600A5", RegionCode.NZ));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 a332 600A5", RegionCode.NZ));
+ }
+
+ public void testParseMaliciousInput() throws Exception {
+ // Lots of leading + signs before the possible number.
+ StringBuilder maliciousNumber = new StringBuilder(6000);
+ for (int i = 0; i < 6000; i++) {
+ maliciousNumber.append('+');
+ }
+ maliciousNumber.append("12222-33-244 extensioB 343+");
+ try {
+ phoneUtil.parse(maliciousNumber.toString(), RegionCode.US);
+ fail("This should not parse without throwing an exception " + maliciousNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_LONG,
+ e.getErrorType());
+ }
+ StringBuilder maliciousNumberWithAlmostExt = new StringBuilder(6000);
+ for (int i = 0; i < 350; i++) {
+ maliciousNumberWithAlmostExt.append("200");
+ }
+ maliciousNumberWithAlmostExt.append(" extensiOB 345");
+ try {
+ phoneUtil.parse(maliciousNumberWithAlmostExt.toString(), RegionCode.US);
+ fail("This should not parse without throwing an exception " + maliciousNumberWithAlmostExt);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_LONG,
+ e.getErrorType());
+ }
+ }
+
+ 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)
+ assertEquals(US_NUMBER, phoneUtil.parse("0011-650-253-0000", RegionCode.SG));
+ // 2nd test: calling using StarHub IDD service (IDD is 008)
+ assertEquals(US_NUMBER, phoneUtil.parse("0081-650-253-0000", RegionCode.SG));
+ // 3rd test: calling using SingTel V019 service (IDD is 019)
+ assertEquals(US_NUMBER, phoneUtil.parse("0191-650-253-0000", RegionCode.SG));
+ // Calling the US number from Poland
+ assertEquals(US_NUMBER, phoneUtil.parse("0~01-650-253-0000", RegionCode.PL));
+ // Using "++" at the start.
+ assertEquals(US_NUMBER, phoneUtil.parse("++1 (650) 253-0000", RegionCode.PL));
+ }
+
+ public void testParseNonAscii() throws Exception {
+ // Using a full-width plus sign.
+ assertEquals(US_NUMBER, phoneUtil.parse("\uFF0B1 (650) 253-0000", RegionCode.SG));
+ // Using a soft hyphen U+00AD.
+ assertEquals(US_NUMBER, phoneUtil.parse("1 (650) 253\u00AD-0000", RegionCode.US));
+ // The whole number, including punctuation, is here represented in full-width form.
+ assertEquals(US_NUMBER, phoneUtil.parse("\uFF0B\uFF11\u3000\uFF08\uFF16\uFF15\uFF10\uFF09" +
+ "\u3000\uFF12\uFF15\uFF13\uFF0D\uFF10\uFF10\uFF10" +
+ "\uFF10",
+ RegionCode.SG));
+ // Using U+30FC dash instead.
+ assertEquals(US_NUMBER, phoneUtil.parse("\uFF0B\uFF11\u3000\uFF08\uFF16\uFF15\uFF10\uFF09" +
+ "\u3000\uFF12\uFF15\uFF13\u30FC\uFF10\uFF10\uFF10" +
+ "\uFF10",
+ RegionCode.SG));
+
+ // Using a very strange decimal digit range (Mongolian digits).
+ assertEquals(US_NUMBER, phoneUtil.parse("\u1811 \u1816\u1815\u1810 " +
+ "\u1812\u1815\u1813 \u1810\u1810\u1810\u1810",
+ RegionCode.US));
+ }
+
+ public void testParseWithLeadingZero() throws Exception {
+ assertEquals(IT_NUMBER, phoneUtil.parse("+39 02-36618 300", RegionCode.NZ));
+ assertEquals(IT_NUMBER, phoneUtil.parse("02-36618 300", RegionCode.IT));
+
+ assertEquals(IT_MOBILE, phoneUtil.parse("345 678 901", RegionCode.IT));
+ }
+
+ public void testParseNationalNumberArgentina() throws Exception {
+ // Test parsing mobile numbers of Argentina.
+ PhoneNumber arNumber = new PhoneNumber();
+ arNumber.setCountryCode(54).setNationalNumber(93435551212L);
+ assertEquals(arNumber, phoneUtil.parse("+54 9 343 555 1212", RegionCode.AR));
+ assertEquals(arNumber, phoneUtil.parse("0343 15 555 1212", RegionCode.AR));
+
+ arNumber.clear();
+ arNumber.setCountryCode(54).setNationalNumber(93715654320L);
+ assertEquals(arNumber, phoneUtil.parse("+54 9 3715 65 4320", RegionCode.AR));
+ assertEquals(arNumber, phoneUtil.parse("03715 15 65 4320", RegionCode.AR));
+ assertEquals(AR_MOBILE, phoneUtil.parse("911 876 54321", RegionCode.AR));
+
+ // Test parsing fixed-line numbers of Argentina.
+ assertEquals(AR_NUMBER, phoneUtil.parse("+54 11 8765 4321", RegionCode.AR));
+ assertEquals(AR_NUMBER, phoneUtil.parse("011 8765 4321", RegionCode.AR));
+
+ arNumber.clear();
+ arNumber.setCountryCode(54).setNationalNumber(3715654321L);
+ assertEquals(arNumber, phoneUtil.parse("+54 3715 65 4321", RegionCode.AR));
+ assertEquals(arNumber, phoneUtil.parse("03715 65 4321", RegionCode.AR));
+
+ arNumber.clear();
+ arNumber.setCountryCode(54).setNationalNumber(2312340000L);
+ assertEquals(arNumber, phoneUtil.parse("+54 23 1234 0000", RegionCode.AR));
+ assertEquals(arNumber, phoneUtil.parse("023 1234 0000", RegionCode.AR));
+ }
+
+ public void testParseWithXInNumber() throws Exception {
+ // Test that having an 'x' in the phone number at the start is ok and that it just gets removed.
+ assertEquals(AR_NUMBER, phoneUtil.parse("01187654321", RegionCode.AR));
+ assertEquals(AR_NUMBER, phoneUtil.parse("(0) 1187654321", RegionCode.AR));
+ assertEquals(AR_NUMBER, phoneUtil.parse("0 1187654321", RegionCode.AR));
+ assertEquals(AR_NUMBER, phoneUtil.parse("(0xx) 1187654321", RegionCode.AR));
+ PhoneNumber arFromUs = new PhoneNumber();
+ arFromUs.setCountryCode(54).setNationalNumber(81429712L);
+ // This test is intentionally constructed such that the number of digit after xx is larger than
+ // 7, so that the number won't be mistakenly treated as an extension, as we allow extensions up
+ // to 7 digits. This assumption is okay for now as all the countries where a carrier selection
+ // code is written in the form of xx have a national significant number of length larger than 7.
+ assertEquals(arFromUs, phoneUtil.parse("011xx5481429712", RegionCode.US));
+ }
+
+ public void testParseNumbersMexico() throws Exception {
+ // Test parsing fixed-line numbers of Mexico.
+ PhoneNumber mxNumber = new PhoneNumber();
+ mxNumber.setCountryCode(52).setNationalNumber(4499780001L);
+ assertEquals(mxNumber, phoneUtil.parse("+52 (449)978-0001", RegionCode.MX));
+ assertEquals(mxNumber, phoneUtil.parse("01 (449)978-0001", RegionCode.MX));
+ assertEquals(mxNumber, phoneUtil.parse("(449)978-0001", RegionCode.MX));
+
+ // Test parsing mobile numbers of Mexico.
+ mxNumber.clear();
+ mxNumber.setCountryCode(52).setNationalNumber(13312345678L);
+ assertEquals(mxNumber, phoneUtil.parse("+52 1 33 1234-5678", RegionCode.MX));
+ assertEquals(mxNumber, phoneUtil.parse("044 (33) 1234-5678", RegionCode.MX));
+ assertEquals(mxNumber, phoneUtil.parse("045 33 1234-5678", RegionCode.MX));
+ }
+
+ public void testFailedParseOnInvalidNumbers() {
+ try {
+ String sentencePhoneNumber = "This is not a phone number";
+ phoneUtil.parse(sentencePhoneNumber, RegionCode.NZ);
+ fail("This should not parse without throwing an exception " + sentencePhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String sentencePhoneNumber = "1 Still not a number";
+ phoneUtil.parse(sentencePhoneNumber, RegionCode.NZ);
+ fail("This should not parse without throwing an exception " + sentencePhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String sentencePhoneNumber = "1 MICROSOFT";
+ phoneUtil.parse(sentencePhoneNumber, RegionCode.NZ);
+ fail("This should not parse without throwing an exception " + sentencePhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String sentencePhoneNumber = "12 MICROSOFT";
+ phoneUtil.parse(sentencePhoneNumber, RegionCode.NZ);
+ fail("This should not parse without throwing an exception " + sentencePhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String tooLongPhoneNumber = "01495 72553301873 810104";
+ phoneUtil.parse(tooLongPhoneNumber, RegionCode.GB);
+ fail("This should not parse without throwing an exception " + tooLongPhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_LONG,
+ e.getErrorType());
+ }
+ try {
+ String plusMinusPhoneNumber = "+---";
+ phoneUtil.parse(plusMinusPhoneNumber, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + plusMinusPhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String plusStar = "+***";
+ phoneUtil.parse(plusStar, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + plusStar);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String plusStarPhoneNumber = "+*******91";
+ phoneUtil.parse(plusStarPhoneNumber, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + plusStarPhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String tooShortPhoneNumber = "+49 0";
+ phoneUtil.parse(tooShortPhoneNumber, RegionCode.DE);
+ fail("This should not parse without throwing an exception " + tooShortPhoneNumber);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_SHORT_NSN,
+ e.getErrorType());
+ }
+ try {
+ String invalidCountryCode = "+210 3456 56789";
+ phoneUtil.parse(invalidCountryCode, RegionCode.NZ);
+ fail("This is not a recognised region code: should fail: " + invalidCountryCode);
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String plusAndIddAndInvalidCountryCode = "+ 00 210 3 331 6005";
+ phoneUtil.parse(plusAndIddAndInvalidCountryCode, RegionCode.NZ);
+ fail("This should not parse without throwing an exception.");
+ } catch (NumberParseException e) {
+ // Expected this exception. 00 is a correct IDD, but 210 is not a valid country code.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "123 456 7890";
+ phoneUtil.parse(someNumber, RegionCode.ZZ);
+ fail("'Unknown' region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "123 456 7890";
+ phoneUtil.parse(someNumber, RegionCode.CS);
+ fail("Deprecated region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "123 456 7890";
+ phoneUtil.parse(someNumber, null);
+ fail("Null region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "0044------";
+ phoneUtil.parse(someNumber, RegionCode.GB);
+ fail("No number provided, only region code: should fail");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "0044";
+ phoneUtil.parse(someNumber, RegionCode.GB);
+ fail("No number provided, only region code: should fail");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "011";
+ phoneUtil.parse(someNumber, RegionCode.US);
+ fail("Only IDD provided - should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD,
+ e.getErrorType());
+ }
+ try {
+ String someNumber = "0119";
+ phoneUtil.parse(someNumber, RegionCode.US);
+ fail("Only IDD provided and then 9 - should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD,
+ e.getErrorType());
+ }
+ try {
+ String emptyNumber = "";
+ // Invalid region.
+ phoneUtil.parse(emptyNumber, RegionCode.ZZ);
+ fail("Empty string - should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ }
+ try {
+ String nullNumber = null;
+ // Invalid region.
+ phoneUtil.parse(nullNumber, RegionCode.ZZ);
+ fail("Null string - should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ } catch (NullPointerException e) {
+ fail("Null string - but should not throw a null pointer exception.");
+ }
+ try {
+ String nullNumber = null;
+ phoneUtil.parse(nullNumber, RegionCode.US);
+ fail("Null string - should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.NOT_A_NUMBER,
+ e.getErrorType());
+ } catch (NullPointerException e) {
+ fail("Null string - but should not throw a null pointer exception.");
+ }
+ try {
+ String domainRfcPhoneContext = "tel:555-1234;phone-context=www.google.com";
+ phoneUtil.parse(domainRfcPhoneContext, RegionCode.ZZ);
+ fail("'Unknown' region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ // This is invalid because no "+" sign is present as part of phone-context. This should not
+ // succeed in being parsed.
+ String invalidRfcPhoneContext = "tel:555-1234;phone-context=1-331";
+ phoneUtil.parse(invalidRfcPhoneContext, RegionCode.ZZ);
+ fail("'Unknown' region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ }
+
+ public void testParseNumbersWithPlusWithNoRegion() throws Exception {
+ // RegionCode.ZZ is allowed only if the number starts with a '+' - then the country calling code
+ // can be calculated.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", RegionCode.ZZ));
+ // Test with full-width plus.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("\uFF0B64 3 331 6005", RegionCode.ZZ));
+ // Test with normal plus but leading characters that need to be stripped.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("Tel: +64 3 331 6005", RegionCode.ZZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("+64 3 331 6005", null));
+ assertEquals(INTERNATIONAL_TOLL_FREE, phoneUtil.parse("+800 1234 5678", null));
+ assertEquals(UNIVERSAL_PREMIUM_RATE, phoneUtil.parse("+979 123 456 789", null));
+
+ // Test parsing RFC3966 format with a phone context.
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;phone-context=+64", RegionCode.ZZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse(" tel:03-331-6005;phone-context=+64", RegionCode.ZZ));
+ assertEquals(NZ_NUMBER, phoneUtil.parse("tel:03-331-6005;isub=12345;phone-context=+64",
+ RegionCode.ZZ));
+
+ // It is important that we set the carrier code to an empty string, since we used
+ // ParseAndKeepRawInput and no carrier code was found.
+ PhoneNumber nzNumberWithRawInput = new PhoneNumber().mergeFrom(NZ_NUMBER).
+ setRawInput("+64 3 331 6005").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN).
+ setPreferredDomesticCarrierCode("");
+ assertEquals(nzNumberWithRawInput, phoneUtil.parseAndKeepRawInput("+64 3 331 6005",
+ RegionCode.ZZ));
+ // Null is also allowed for the region code in these cases.
+ assertEquals(nzNumberWithRawInput, phoneUtil.parseAndKeepRawInput("+64 3 331 6005", null));
+ }
+
+ public void testParseNumberTooShortIfNationalPrefixStripped() throws Exception {
+ // Test that a number whose first digits happen to coincide with the national prefix does not
+ // get them stripped if doing so would result in a number too short to be a possible (regular
+ // length) phone number for that region.
+ PhoneNumber byNumber = new PhoneNumber().setCountryCode(375).setNationalNumber(8123L);
+ assertEquals(byNumber, phoneUtil.parse("8123", RegionCode.BY));
+ byNumber.setNationalNumber(81234L);
+ assertEquals(byNumber, phoneUtil.parse("81234", RegionCode.BY));
+
+ // The prefix doesn't get stripped, since the input is a viable 6-digit number, whereas the
+ // result of stripping is only 5 digits.
+ byNumber.setNationalNumber(812345L);
+ assertEquals(byNumber, phoneUtil.parse("812345", RegionCode.BY));
+
+ // The prefix gets stripped, since only 6-digit numbers are possible.
+ byNumber.setNationalNumber(123456L);
+ assertEquals(byNumber, phoneUtil.parse("8123456", RegionCode.BY));
+ }
+
+ public void testParseExtensions() throws Exception {
+ PhoneNumber nzNumber = new PhoneNumber();
+ nzNumber.setCountryCode(64).setNationalNumber(33316005L).setExtension("3456");
+ assertEquals(nzNumber, phoneUtil.parse("03 331 6005 ext 3456", RegionCode.NZ));
+ assertEquals(nzNumber, phoneUtil.parse("03-3316005x3456", RegionCode.NZ));
+ assertEquals(nzNumber, phoneUtil.parse("03-3316005 int.3456", RegionCode.NZ));
+ assertEquals(nzNumber, phoneUtil.parse("03 3316005 #3456", RegionCode.NZ));
+ // Test the following do not extract extensions:
+ assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("1800 six-flags", RegionCode.US));
+ assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("1800 SIX FLAGS", RegionCode.US));
+ assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("0~0 1800 7493 5247", RegionCode.PL));
+ assertEquals(ALPHA_NUMERIC_NUMBER, phoneUtil.parse("(1800) 7493.5247", RegionCode.US));
+ // Check that the last instance of an extension token is matched.
+ PhoneNumber extnNumber = new PhoneNumber().mergeFrom(ALPHA_NUMERIC_NUMBER).setExtension("1234");
+ assertEquals(extnNumber, phoneUtil.parse("0~0 1800 7493 5247 ~1234", RegionCode.PL));
+ // Verifying bug-fix where the last digit of a number was previously omitted if it was a 0 when
+ // extracting the extension. Also verifying a few different cases of extensions.
+ PhoneNumber ukNumber = new PhoneNumber();
+ ukNumber.setCountryCode(44).setNationalNumber(2034567890L).setExtension("456");
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", RegionCode.NZ));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x 456 ", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("+44-2034567890;ext=456", RegionCode.GB));
+ assertEquals(ukNumber, phoneUtil.parse("tel:2034567890;ext=456;phone-context=+44",
+ RegionCode.ZZ));
+ // Full-width extension, "extn" only.
+ assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF45\uFF58\uFF54\uFF4E456",
+ RegionCode.GB));
+ // "xtn" only.
+ assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF58\uFF54\uFF4E456",
+ RegionCode.GB));
+ // "xt" only.
+ assertEquals(ukNumber, phoneUtil.parse("+442034567890\uFF58\uFF54456",
+ RegionCode.GB));
+
+ PhoneNumber usWithExtension = new PhoneNumber();
+ usWithExtension.setCountryCode(1).setNationalNumber(8009013355L).setExtension("7246433");
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 x 7246433", RegionCode.US));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , ext 7246433", RegionCode.US));
+ assertEquals(usWithExtension,
+ phoneUtil.parse("(800) 901-3355 ,extension 7246433", RegionCode.US));
+ assertEquals(usWithExtension,
+ phoneUtil.parse("(800) 901-3355 ,extensi\u00F3n 7246433", RegionCode.US));
+ // Repeat with the small letter o with acute accent created by combining characters.
+ assertEquals(usWithExtension,
+ phoneUtil.parse("(800) 901-3355 ,extensio\u0301n 7246433", RegionCode.US));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , 7246433", RegionCode.US));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ext: 7246433", RegionCode.US));
+
+ // Test that if a number has two extensions specified, we ignore the second.
+ PhoneNumber usWithTwoExtensionsNumber = new PhoneNumber();
+ usWithTwoExtensionsNumber.setCountryCode(1).setNationalNumber(2121231234L).setExtension("508");
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/x1234",
+ RegionCode.US));
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/ x1234",
+ RegionCode.US));
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508\\x1234",
+ RegionCode.US));
+
+ // Test parsing numbers in the form (645) 123-1234-910# works, where the last 3 digits before
+ // the # are an extension.
+ usWithExtension.clear();
+ usWithExtension.setCountryCode(1).setNationalNumber(6451231234L).setExtension("910");
+ assertEquals(usWithExtension, phoneUtil.parse("+1 (645) 123 1234-910#", RegionCode.US));
+ // Retry with the same number in a slightly different format.
+ assertEquals(usWithExtension, phoneUtil.parse("+1 (645) 123 1234 ext. 910#", RegionCode.US));
+ }
+
+ public void testParseAndKeepRaw() throws Exception {
+ PhoneNumber alphaNumericNumber = new PhoneNumber().mergeFrom(ALPHA_NUMERIC_NUMBER).
+ setRawInput("800 six-flags").
+ setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY).
+ setPreferredDomesticCarrierCode("");
+ assertEquals(alphaNumericNumber,
+ phoneUtil.parseAndKeepRawInput("800 six-flags", RegionCode.US));
+
+ PhoneNumber shorterAlphaNumber = new PhoneNumber().
+ setCountryCode(1).setNationalNumber(8007493524L).
+ setRawInput("1800 six-flag").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN).
+ setPreferredDomesticCarrierCode("");
+ assertEquals(shorterAlphaNumber,
+ phoneUtil.parseAndKeepRawInput("1800 six-flag", RegionCode.US));
+
+ shorterAlphaNumber.setRawInput("+1800 six-flag").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+ assertEquals(shorterAlphaNumber,
+ phoneUtil.parseAndKeepRawInput("+1800 six-flag", RegionCode.NZ));
+
+ shorterAlphaNumber.setRawInput("001800 six-flag").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_IDD);
+ assertEquals(shorterAlphaNumber,
+ phoneUtil.parseAndKeepRawInput("001800 six-flag", RegionCode.NZ));
+
+ // Invalid region code supplied.
+ try {
+ phoneUtil.parseAndKeepRawInput("123 456 7890", RegionCode.CS);
+ fail("Deprecated region code not allowed: should fail.");
+ } catch (NumberParseException e) {
+ // Expected this exception.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+
+ PhoneNumber koreanNumber = new PhoneNumber();
+ koreanNumber.setCountryCode(82).setNationalNumber(22123456).setRawInput("08122123456").
+ setCountryCodeSource(CountryCodeSource.FROM_DEFAULT_COUNTRY).
+ setPreferredDomesticCarrierCode("81");
+ assertEquals(koreanNumber, phoneUtil.parseAndKeepRawInput("08122123456", RegionCode.KR));
+ }
+
+ public void testParseItalianLeadingZeros() throws Exception {
+ // Test the number "011".
+ PhoneNumber oneZero = new PhoneNumber();
+ oneZero.setCountryCode(61).setNationalNumber(11L).setItalianLeadingZero(true);
+ assertEquals(oneZero, phoneUtil.parse("011", RegionCode.AU));
+
+ // Test the number "001".
+ PhoneNumber twoZeros = new PhoneNumber();
+ twoZeros.setCountryCode(61).setNationalNumber(1).setItalianLeadingZero(true)
+ .setNumberOfLeadingZeros(2);
+ assertEquals(twoZeros, phoneUtil.parse("001", RegionCode.AU));
+
+ // Test the number "000". This number has 2 leading zeros.
+ PhoneNumber stillTwoZeros = new PhoneNumber();
+ stillTwoZeros.setCountryCode(61).setNationalNumber(0L).setItalianLeadingZero(true)
+ .setNumberOfLeadingZeros(2);
+ assertEquals(stillTwoZeros, phoneUtil.parse("000", RegionCode.AU));
+
+ // Test the number "0000". This number has 3 leading zeros.
+ PhoneNumber threeZeros = new PhoneNumber();
+ threeZeros.setCountryCode(61).setNationalNumber(0L).setItalianLeadingZero(true)
+ .setNumberOfLeadingZeros(3);
+ assertEquals(threeZeros, phoneUtil.parse("0000", RegionCode.AU));
+ }
+
+ public void testCountryWithNoNumberDesc() {
+ // Andorra is a country where we don't have PhoneNumberDesc info in the metadata.
+ PhoneNumber adNumber = new PhoneNumber();
+ adNumber.setCountryCode(376).setNationalNumber(12345L);
+ assertEquals("+376 12345", phoneUtil.format(adNumber, PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+37612345", phoneUtil.format(adNumber, PhoneNumberFormat.E164));
+ assertEquals("12345", phoneUtil.format(adNumber, PhoneNumberFormat.NATIONAL));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.UNKNOWN, phoneUtil.getNumberType(adNumber));
+ assertFalse(phoneUtil.isValidNumber(adNumber));
+
+ // Test dialing a US number from within Andorra.
+ assertEquals("00 1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.AD));
+ }
+
+ 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 {
+ // Test simple matches where formatting is different, or leading zeros, or country calling code
+ // 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,
+ phoneUtil.isNumberMatch("+643 331-6005", "+64033316005"));
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch("+643 331-6005", "+6433316005"));
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "+6433316005"));
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "tel:+64-3-331-6005;isub=123"));
+ // Test alpha numbers.
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch("+1800 siX-Flags", "+1 800 7493 5247"));
+ // Test numbers with extensions.
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005 extn 1234", "+6433316005#1234"));
+ // Test proto buffers.
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(NZ_NUMBER, "+6403 331 6005"));
+
+ PhoneNumber nzNumber = new PhoneNumber().mergeFrom(NZ_NUMBER).setExtension("3456");
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber, "+643 331 6005 ext 3456"));
+ // Check empty extensions are ignored.
+ nzNumber.setExtension("");
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber, "+6403 331 6005"));
+ // Check variant with two proto buffers.
+ assertEquals("Number " + nzNumber.toString() + " did not match " + NZ_NUMBER.toString(),
+ PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber, NZ_NUMBER));
+
+ // Check raw_input, country_code_source and preferred_domestic_carrier_code are ignored.
+ PhoneNumber brNumberOne = new PhoneNumber();
+ PhoneNumber brNumberTwo = new PhoneNumber();
+ brNumberOne.setCountryCode(55).setNationalNumber(3121286979L)
+ .setCountryCodeSource(PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)
+ .setPreferredDomesticCarrierCode("12").setRawInput("012 3121286979");
+ brNumberTwo.setCountryCode(55).setNationalNumber(3121286979L)
+ .setCountryCodeSource(PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY)
+ .setPreferredDomesticCarrierCode("14").setRawInput("143121286979");
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(brNumberOne, brNumberTwo));
+ }
+
+ public void testIsNumberMatchNonMatches() throws Exception {
+ // 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"));
+ // Different country calling code, same number.
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "+6133316005"));
+ // Extension different, all else the same.
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005 extn 1234", "0116433316005#1235"));
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch(
+ "+64 3 331-6005 extn 1234", "tel:+64-3-331-6005;ext=1235"));
+ // NSN matches, but extension is different - not the same number.
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005 ext.1235", "3 331 6005#1234"));
+
+ // Invalid numbers that can't be parsed.
+ assertEquals(PhoneNumberUtil.MatchType.NOT_A_NUMBER,
+ phoneUtil.isNumberMatch("4", "3 331 6043"));
+ assertEquals(PhoneNumberUtil.MatchType.NOT_A_NUMBER,
+ phoneUtil.isNumberMatch("+43", "+64 3 331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.NOT_A_NUMBER,
+ phoneUtil.isNumberMatch("+43", "64 3 331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.NOT_A_NUMBER,
+ phoneUtil.isNumberMatch("Dog", "64 3 331 6005"));
+ }
+
+ public void testIsNumberMatchNsnMatches() throws Exception {
+ // NSN matches.
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "03 331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(
+ "+64 3 331-6005", "tel:03-331-6005;isub=1234;phone-context=abc.nz"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(NZ_NUMBER, "03 331 6005"));
+ // Here the second number possibly starts with the country calling code for New Zealand,
+ // although we are unsure.
+ PhoneNumber unchangedNzNumber = new PhoneNumber().mergeFrom(NZ_NUMBER);
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(unchangedNzNumber, "(64-3) 331 6005"));
+ // Check the phone number proto was not edited during the method call.
+ assertEquals(NZ_NUMBER, unchangedNzNumber);
+
+ // Here, the 1 might be a national prefix, if we compare it to the US number, so the resultant
+ // match is an NSN match.
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(US_NUMBER, "1-650-253-0000"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(US_NUMBER, "6502530000"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch("+1 650-253 0000", "1 650 253 0000"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch("1 650-253 0000", "1 650 253 0000"));
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch("1 650-253 0000", "+1 650 253 0000"));
+ // For this case, the match will be a short NSN match, because we cannot assume that the 1 might
+ // be a national prefix, so don't remove it when parsing.
+ PhoneNumber randomNumber = new PhoneNumber();
+ randomNumber.setCountryCode(41).setNationalNumber(6502530000L);
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch(randomNumber, "1-650-253-0000"));
+ }
+
+ public void testIsNumberMatchShortNsnMatches() throws Exception {
+ // Short NSN matches with the country not specified for either one or both numbers.
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "tel:331-6005;phone-context=abc.nz"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005",
+ "tel:331-6005;isub=1234;phone-context=abc.nz"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005",
+ "tel:331-6005;isub=1234;phone-context=abc.nz;a=%A1"));
+ // We did not know that the "0" was a national prefix since neither number has a country code,
+ // so this is considered a SHORT_NSN_MATCH.
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("3 331-6005", "03 331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("3 331-6005", "331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("3 331-6005", "tel:331-6005;phone-context=abc.nz"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("3 331-6005", "+64 331 6005"));
+ // Short NSN match with the country specified.
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("03 331-6005", "331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("1 234 345 6789", "345 6789"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+1 (234) 345 6789", "345 6789"));
+ // NSN matches, country calling code omitted for one number, extension missing for one.
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "3 331 6005#1234"));
+ // One has Italian leading zero, one does not.
+ PhoneNumber italianNumberOne = new PhoneNumber();
+ italianNumberOne.setCountryCode(39).setNationalNumber(1234L).setItalianLeadingZero(true);
+ PhoneNumber italianNumberTwo = new PhoneNumber();
+ italianNumberTwo.setCountryCode(39).setNationalNumber(1234L);
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch(italianNumberOne, italianNumberTwo));
+ // One has an extension, the other has an extension of "".
+ italianNumberOne.setExtension("1234").clearItalianLeadingZero();
+ italianNumberTwo.setExtension("");
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch(italianNumberOne, italianNumberTwo));
+ }
+
+ public void testCanBeInternationallyDialled() throws Exception {
+ // We have no-international-dialling rules for the US in our test metadata that say that
+ // toll-free numbers cannot be dialled internationally.
+ assertFalse(phoneUtil.canBeInternationallyDialled(US_TOLLFREE));
+
+ // Normal US numbers can be internationally dialled.
+ assertTrue(phoneUtil.canBeInternationallyDialled(US_NUMBER));
+
+ // Invalid number.
+ assertTrue(phoneUtil.canBeInternationallyDialled(US_LOCAL_NUMBER));
+
+ // 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"));
+ assertTrue(phoneUtil.isAlphaNumber("180 six-flags"));
+ assertFalse(phoneUtil.isAlphaNumber("1800 123-1234"));
+ assertFalse(phoneUtil.isAlphaNumber("1 six-flags"));
+ assertFalse(phoneUtil.isAlphaNumber("18 six-flags"));
+ assertFalse(phoneUtil.isAlphaNumber("1800 123-1234 extension: 1234"));
+ assertFalse(phoneUtil.isAlphaNumber("+800 1234-1234"));
+ }
+
+ public void testIsMobileNumberPortableRegion() {
+ assertTrue(phoneUtil.isMobileNumberPortableRegion(RegionCode.US));
+ assertTrue(phoneUtil.isMobileNumberPortableRegion(RegionCode.GB));
+ assertFalse(phoneUtil.isMobileNumberPortableRegion(RegionCode.AE));
+ assertFalse(phoneUtil.isMobileNumberPortableRegion(RegionCode.BS));
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java
new file mode 100644
index 00000000..466a0e34
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the Phonenumber.PhoneNumber object itself.
+ *
+ * @author Lara Rennie
+ */
+public class PhonenumberTest extends TestCase {
+
+ public void testEqualSimpleNumber() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L);
+
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setCountryCode(1).setNationalNumber(6502530000L);
+
+ assertEquals(numberA, numberB);
+ assertEquals(numberA.hashCode(), numberB.hashCode());
+ }
+
+ public void testEqualWithItalianLeadingZeroSetToDefault() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(false);
+
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setCountryCode(1).setNationalNumber(6502530000L);
+
+ // These should still be equal, since the default value for this field is false.
+ assertEquals(numberA, numberB);
+ assertEquals(numberA.hashCode(), numberB.hashCode());
+ }
+
+ public void testEqualWithCountryCodeSourceSet() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setRawInput("+1 650 253 00 00").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setRawInput("+1 650 253 00 00").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+ assertEquals(numberA, numberB);
+ assertEquals(numberA.hashCode(), numberB.hashCode());
+ }
+
+ public void testNonEqualWithItalianLeadingZeroSetToTrue() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L).setItalianLeadingZero(true);
+
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setCountryCode(1).setNationalNumber(6502530000L);
+
+ assertFalse(numberA.equals(numberB));
+ assertFalse(numberA.hashCode() == numberB.hashCode());
+ }
+
+ public void testNonEqualWithDifferingRawInput() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1 650 253 00 00").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+
+ PhoneNumber numberB = new PhoneNumber();
+ // Although these numbers would pass an isNumberMatch test, they are not considered "equal" as
+ // objects, since their raw input is different.
+ numberB.setCountryCode(1).setNationalNumber(6502530000L).setRawInput("+1-650-253-00-00").
+ setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN);
+
+ assertFalse(numberA.equals(numberB));
+ assertFalse(numberA.hashCode() == numberB.hashCode());
+ }
+
+ public void testNonEqualWithPreferredDomesticCarrierCodeSetToDefault() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode("");
+
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setCountryCode(1).setNationalNumber(6502530000L);
+
+ assertFalse(numberA.equals(numberB));
+ assertFalse(numberA.hashCode() == numberB.hashCode());
+ }
+
+ public void testEqualWithPreferredDomesticCarrierCodeSetToDefault() throws Exception {
+ PhoneNumber numberA = new PhoneNumber();
+ numberA.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode("");
+
+ PhoneNumber numberB = new PhoneNumber();
+ numberB.setCountryCode(1).setNationalNumber(6502530000L).setPreferredDomesticCarrierCode("");
+
+ assertEquals(numberA, numberB);
+ assertEquals(numberA.hashCode(), numberB.hashCode());
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java
new file mode 100644
index 00000000..a2839d3a
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 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;
+
+import junit.framework.TestCase;
+
+/**
+ * Unittests for LRU Cache for compiled regular expressions used by the libphonenumbers libary.
+ *
+ * @author Shaopeng Jia
+ */
+
+public class RegexCacheTest extends TestCase {
+ private RegexCache regexCache;
+
+ public RegexCacheTest() {
+ regexCache = new RegexCache(2);
+ }
+
+ public void testRegexInsertion() {
+ final String regex1 = "[1-5]";
+ final String regex2 = "(?:12|34)";
+ final String regex3 = "[1-3][58]";
+
+ regexCache.getPatternForRegex(regex1);
+ assertTrue(regexCache.containsRegex(regex1));
+
+ regexCache.getPatternForRegex(regex2);
+ assertTrue(regexCache.containsRegex(regex2));
+ assertTrue(regexCache.containsRegex(regex1));
+
+ regexCache.getPatternForRegex(regex1);
+ assertTrue(regexCache.containsRegex(regex1));
+
+ regexCache.getPatternForRegex(regex3);
+ assertTrue(regexCache.containsRegex(regex3));
+
+ assertFalse(regexCache.containsRegex(regex2));
+ assertTrue(regexCache.containsRegex(regex1));
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java b/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java
new file mode 100644
index 00000000..a5939fe9
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 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;
+
+/**
+ * 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 AE = "AE";
+ static final String AM = "AM";
+ static final String AO = "AO";
+ static final String AQ = "AQ";
+ static final String AR = "AR";
+ static final String AU = "AU";
+ static final String BB = "BB";
+ static final String BR = "BR";
+ static final String BS = "BS";
+ static final String BY = "BY";
+ static final String CA = "CA";
+ static final String CH = "CH";
+ static final String CL = "CL";
+ static final String CN = "CN";
+ static final String CS = "CS";
+ static final String CX = "CX";
+ static final String DE = "DE";
+ static final String FR = "FR";
+ static final String GB = "GB";
+ static final String HU = "HU";
+ static final String IT = "IT";
+ static final String JP = "JP";
+ static final String KR = "KR";
+ static final String MX = "MX";
+ static final String NZ = "NZ";
+ static final String PG = "PG";
+ static final String PL = "PL";
+ static final String RE = "RE";
+ static final String SE = "SE";
+ static final String SG = "SG";
+ static final String US = "US";
+ static final String YT = "YT";
+ static final String ZW = "ZW";
+ // Official code for the unknown region.
+ static final String ZZ = "ZZ";
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java
new file mode 100644
index 00000000..63661a90
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2013 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;
+
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
+/**
+ * Unit tests for ShortNumberInfo.java
+ *
+ * @author Shaopeng Jia
+ */
+public class ShortNumberInfoTest extends TestMetadataTestCase {
+ private static final ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
+
+ public void testIsPossibleShortNumber() {
+ PhoneNumber possibleNumber = new PhoneNumber();
+ possibleNumber.setCountryCode(33).setNationalNumber(123456L);
+ assertTrue(shortInfo.isPossibleShortNumber(possibleNumber));
+ assertTrue(
+ shortInfo.isPossibleShortNumberForRegion(parse("123456", RegionCode.FR), RegionCode.FR));
+
+ PhoneNumber impossibleNumber = new PhoneNumber();
+ impossibleNumber.setCountryCode(33).setNationalNumber(9L);
+ assertFalse(shortInfo.isPossibleShortNumber(impossibleNumber));
+
+ // Note that GB and GG share the country calling code 44, and that this number is possible but
+ // not valid.
+ assertTrue(shortInfo.isPossibleShortNumber(
+ new PhoneNumber().setCountryCode(44).setNationalNumber(11001L)));
+ }
+
+ public void testIsValidShortNumber() {
+ assertTrue(shortInfo.isValidShortNumber(
+ new PhoneNumber().setCountryCode(33).setNationalNumber(1010L)));
+ assertTrue(shortInfo.isValidShortNumberForRegion(parse("1010", RegionCode.FR), RegionCode.FR));
+ assertFalse(shortInfo.isValidShortNumber(
+ new PhoneNumber().setCountryCode(33).setNationalNumber(123456L)));
+ assertFalse(
+ shortInfo.isValidShortNumberForRegion(parse("123456", RegionCode.FR), RegionCode.FR));
+
+ // Note that GB and GG share the country calling code 44.
+ assertTrue(shortInfo.isValidShortNumber(
+ new PhoneNumber().setCountryCode(44).setNationalNumber(18001L)));
+ }
+
+ public void testGetExpectedCost() {
+ String premiumRateExample = shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.PREMIUM_RATE);
+ assertEquals(ShortNumberInfo.ShortNumberCost.PREMIUM_RATE, shortInfo.getExpectedCostForRegion(
+ parse(premiumRateExample, RegionCode.FR), RegionCode.FR));
+ PhoneNumber premiumRateNumber = new PhoneNumber();
+ premiumRateNumber.setCountryCode(33).setNationalNumber(Integer.parseInt(premiumRateExample));
+ assertEquals(ShortNumberInfo.ShortNumberCost.PREMIUM_RATE,
+ shortInfo.getExpectedCost(premiumRateNumber));
+
+ String standardRateExample = shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.STANDARD_RATE);
+ assertEquals(ShortNumberInfo.ShortNumberCost.STANDARD_RATE, shortInfo.getExpectedCostForRegion(
+ parse(standardRateExample, RegionCode.FR), RegionCode.FR));
+ PhoneNumber standardRateNumber = new PhoneNumber();
+ standardRateNumber.setCountryCode(33).setNationalNumber(Integer.parseInt(standardRateExample));
+ assertEquals(ShortNumberInfo.ShortNumberCost.STANDARD_RATE,
+ shortInfo.getExpectedCost(standardRateNumber));
+
+ String tollFreeExample = shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.TOLL_FREE);
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCostForRegion(parse(tollFreeExample, RegionCode.FR), RegionCode.FR));
+ PhoneNumber tollFreeNumber = new PhoneNumber();
+ tollFreeNumber.setCountryCode(33).setNationalNumber(Integer.parseInt(tollFreeExample));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCost(tollFreeNumber));
+
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCostForRegion(parse("12345", RegionCode.FR), RegionCode.FR));
+ PhoneNumber unknownCostNumber = new PhoneNumber();
+ unknownCostNumber.setCountryCode(33).setNationalNumber(12345L);
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCost(unknownCostNumber));
+
+ // Test that an invalid number may nevertheless have a cost other than UNKNOWN_COST.
+ assertFalse(
+ shortInfo.isValidShortNumberForRegion(parse("116123", RegionCode.FR), RegionCode.FR));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCostForRegion(parse("116123", RegionCode.FR), RegionCode.FR));
+ PhoneNumber invalidNumber = new PhoneNumber();
+ invalidNumber.setCountryCode(33).setNationalNumber(116123L);
+ assertFalse(shortInfo.isValidShortNumber(invalidNumber));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCost(invalidNumber));
+
+ // Test a nonexistent country code.
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCostForRegion(parse("911", RegionCode.US), RegionCode.ZZ));
+ unknownCostNumber.clear();
+ unknownCostNumber.setCountryCode(123).setNationalNumber(911L);
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCost(unknownCostNumber));
+ }
+
+ public void testGetExpectedCostForSharedCountryCallingCode() {
+ // Test some numbers which have different costs in countries sharing the same country calling
+ // code. In Australia, 1234 is premium-rate, 1194 is standard-rate, and 733 is toll-free. These
+ // are not known to be valid numbers in the Christmas Islands.
+ String ambiguousPremiumRateString = "1234";
+ PhoneNumber ambiguousPremiumRateNumber =
+ new PhoneNumber().setCountryCode(61).setNationalNumber(1234L);
+ String ambiguousStandardRateString = "1194";
+ PhoneNumber ambiguousStandardRateNumber =
+ new PhoneNumber().setCountryCode(61).setNationalNumber(1194L);
+ String ambiguousTollFreeString = "733";
+ PhoneNumber ambiguousTollFreeNumber =
+ new PhoneNumber().setCountryCode(61).setNationalNumber(733L);
+
+ assertTrue(shortInfo.isValidShortNumber(ambiguousPremiumRateNumber));
+ assertTrue(shortInfo.isValidShortNumber(ambiguousStandardRateNumber));
+ assertTrue(shortInfo.isValidShortNumber(ambiguousTollFreeNumber));
+
+ assertTrue(shortInfo.isValidShortNumberForRegion(
+ parse(ambiguousPremiumRateString, RegionCode.AU), RegionCode.AU));
+ assertEquals(ShortNumberInfo.ShortNumberCost.PREMIUM_RATE, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousPremiumRateString, RegionCode.AU), RegionCode.AU));
+ assertFalse(shortInfo.isValidShortNumberForRegion(
+ parse(ambiguousPremiumRateString, RegionCode.CX), RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousPremiumRateString, RegionCode.CX), RegionCode.CX));
+ // PREMIUM_RATE takes precedence over UNKNOWN_COST.
+ assertEquals(ShortNumberInfo.ShortNumberCost.PREMIUM_RATE,
+ shortInfo.getExpectedCost(ambiguousPremiumRateNumber));
+
+ assertTrue(shortInfo.isValidShortNumberForRegion(
+ parse(ambiguousStandardRateString, RegionCode.AU), RegionCode.AU));
+ assertEquals(ShortNumberInfo.ShortNumberCost.STANDARD_RATE, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousStandardRateString, RegionCode.AU), RegionCode.AU));
+ assertFalse(shortInfo.isValidShortNumberForRegion(
+ parse(ambiguousStandardRateString, RegionCode.CX), RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousStandardRateString, RegionCode.CX), RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCost(ambiguousStandardRateNumber));
+
+ assertTrue(shortInfo.isValidShortNumberForRegion(parse(ambiguousTollFreeString, RegionCode.AU),
+ RegionCode.AU));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousTollFreeString, RegionCode.AU), RegionCode.AU));
+ assertFalse(shortInfo.isValidShortNumberForRegion(parse(ambiguousTollFreeString, RegionCode.CX),
+ RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST, shortInfo.getExpectedCostForRegion(
+ parse(ambiguousTollFreeString, RegionCode.CX), RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCost(ambiguousTollFreeNumber));
+ }
+
+ public void testGetExampleShortNumber() {
+ assertEquals("8711", shortInfo.getExampleShortNumber(RegionCode.AM));
+ assertEquals("1010", shortInfo.getExampleShortNumber(RegionCode.FR));
+ assertEquals("", shortInfo.getExampleShortNumber(RegionCode.UN001));
+ assertEquals("", shortInfo.getExampleShortNumber(null));
+ }
+
+ public void testGetExampleShortNumberForCost() {
+ assertEquals("3010", shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.TOLL_FREE));
+ assertEquals("1023", shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.STANDARD_RATE));
+ assertEquals("42000", shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.PREMIUM_RATE));
+ assertEquals("", shortInfo.getExampleShortNumberForCost(RegionCode.FR,
+ ShortNumberInfo.ShortNumberCost.UNKNOWN_COST));
+ }
+
+ public void testConnectsToEmergencyNumber_US() {
+ assertTrue(shortInfo.connectsToEmergencyNumber("911", RegionCode.US));
+ assertTrue(shortInfo.connectsToEmergencyNumber("112", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("999", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberLongNumber_US() {
+ assertTrue(shortInfo.connectsToEmergencyNumber("9116666666", RegionCode.US));
+ assertTrue(shortInfo.connectsToEmergencyNumber("1126666666", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("9996666666", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberWithFormatting_US() {
+ assertTrue(shortInfo.connectsToEmergencyNumber("9-1-1", RegionCode.US));
+ assertTrue(shortInfo.connectsToEmergencyNumber("1-1-2", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("9-9-9", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberWithPlusSign_US() {
+ assertFalse(shortInfo.connectsToEmergencyNumber("+911", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("\uFF0B911", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber(" +911", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("+112", RegionCode.US));
+ assertFalse(shortInfo.connectsToEmergencyNumber("+999", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumber_BR() {
+ assertTrue(shortInfo.connectsToEmergencyNumber("911", RegionCode.BR));
+ assertTrue(shortInfo.connectsToEmergencyNumber("190", RegionCode.BR));
+ assertFalse(shortInfo.connectsToEmergencyNumber("999", RegionCode.BR));
+ }
+
+ public void testConnectsToEmergencyNumberLongNumber_BR() {
+ // Brazilian emergency numbers don't work when additional digits are appended.
+ assertFalse(shortInfo.connectsToEmergencyNumber("9111", RegionCode.BR));
+ assertFalse(shortInfo.connectsToEmergencyNumber("1900", RegionCode.BR));
+ assertFalse(shortInfo.connectsToEmergencyNumber("9996", RegionCode.BR));
+ }
+
+ public void testConnectsToEmergencyNumber_CL() {
+ assertTrue(shortInfo.connectsToEmergencyNumber("131", RegionCode.CL));
+ assertTrue(shortInfo.connectsToEmergencyNumber("133", RegionCode.CL));
+ }
+
+ public void testConnectsToEmergencyNumberLongNumber_CL() {
+ // Chilean emergency numbers don't work when additional digits are appended.
+ assertFalse(shortInfo.connectsToEmergencyNumber("1313", RegionCode.CL));
+ assertFalse(shortInfo.connectsToEmergencyNumber("1330", RegionCode.CL));
+ }
+
+ public void testConnectsToEmergencyNumber_AO() {
+ // Angola doesn't have any metadata for emergency numbers in the test metadata.
+ assertFalse(shortInfo.connectsToEmergencyNumber("911", RegionCode.AO));
+ assertFalse(shortInfo.connectsToEmergencyNumber("222123456", RegionCode.AO));
+ assertFalse(shortInfo.connectsToEmergencyNumber("923123456", RegionCode.AO));
+ }
+
+ public void testConnectsToEmergencyNumber_ZW() {
+ // Zimbabwe doesn't have any metadata in the test metadata.
+ assertFalse(shortInfo.connectsToEmergencyNumber("911", RegionCode.ZW));
+ assertFalse(shortInfo.connectsToEmergencyNumber("01312345", RegionCode.ZW));
+ assertFalse(shortInfo.connectsToEmergencyNumber("0711234567", RegionCode.ZW));
+ }
+
+ public void testIsEmergencyNumber_US() {
+ assertTrue(shortInfo.isEmergencyNumber("911", RegionCode.US));
+ assertTrue(shortInfo.isEmergencyNumber("112", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberLongNumber_US() {
+ assertFalse(shortInfo.isEmergencyNumber("9116666666", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("1126666666", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("9996666666", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberWithFormatting_US() {
+ assertTrue(shortInfo.isEmergencyNumber("9-1-1", RegionCode.US));
+ assertTrue(shortInfo.isEmergencyNumber("*911", RegionCode.US));
+ assertTrue(shortInfo.isEmergencyNumber("1-1-2", RegionCode.US));
+ assertTrue(shortInfo.isEmergencyNumber("*112", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("9-9-9", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("*999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberWithPlusSign_US() {
+ assertFalse(shortInfo.isEmergencyNumber("+911", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("\uFF0B911", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber(" +911", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("+112", RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("+999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumber_BR() {
+ assertTrue(shortInfo.isEmergencyNumber("911", RegionCode.BR));
+ assertTrue(shortInfo.isEmergencyNumber("190", RegionCode.BR));
+ assertFalse(shortInfo.isEmergencyNumber("999", RegionCode.BR));
+ }
+
+ public void testIsEmergencyNumberLongNumber_BR() {
+ assertFalse(shortInfo.isEmergencyNumber("9111", RegionCode.BR));
+ assertFalse(shortInfo.isEmergencyNumber("1900", RegionCode.BR));
+ assertFalse(shortInfo.isEmergencyNumber("9996", RegionCode.BR));
+ }
+
+ public void testIsEmergencyNumber_AO() {
+ // Angola doesn't have any metadata for emergency numbers in the test metadata.
+ assertFalse(shortInfo.isEmergencyNumber("911", RegionCode.AO));
+ assertFalse(shortInfo.isEmergencyNumber("222123456", RegionCode.AO));
+ assertFalse(shortInfo.isEmergencyNumber("923123456", RegionCode.AO));
+ }
+
+ public void testIsEmergencyNumber_ZW() {
+ // Zimbabwe doesn't have any metadata in the test metadata.
+ assertFalse(shortInfo.isEmergencyNumber("911", RegionCode.ZW));
+ assertFalse(shortInfo.isEmergencyNumber("01312345", RegionCode.ZW));
+ assertFalse(shortInfo.isEmergencyNumber("0711234567", RegionCode.ZW));
+ }
+
+ public void testEmergencyNumberForSharedCountryCallingCode() {
+ // Test the emergency number 112, which is valid in both Australia and the Christmas Islands.
+ assertTrue(shortInfo.isEmergencyNumber("112", RegionCode.AU));
+ assertTrue(shortInfo.isValidShortNumberForRegion(parse("112", RegionCode.AU), RegionCode.AU));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCostForRegion(parse("112", RegionCode.AU), RegionCode.AU));
+ assertTrue(shortInfo.isEmergencyNumber("112", RegionCode.CX));
+ assertTrue(shortInfo.isValidShortNumberForRegion(parse("112", RegionCode.CX), RegionCode.CX));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCostForRegion(parse("112", RegionCode.CX), RegionCode.CX));
+ PhoneNumber sharedEmergencyNumber =
+ new PhoneNumber().setCountryCode(61).setNationalNumber(112L);
+ assertTrue(shortInfo.isValidShortNumber(sharedEmergencyNumber));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCost(sharedEmergencyNumber));
+ }
+
+ public void testOverlappingNANPANumber() {
+ // 211 is an emergency number in Barbados, while it is a toll-free information line in Canada
+ // and the USA.
+ assertTrue(shortInfo.isEmergencyNumber("211", RegionCode.BB));
+ assertEquals(ShortNumberInfo.ShortNumberCost.TOLL_FREE,
+ shortInfo.getExpectedCostForRegion(parse("211", RegionCode.BB), RegionCode.BB));
+ assertFalse(shortInfo.isEmergencyNumber("211", RegionCode.US));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCostForRegion(parse("211", RegionCode.US), RegionCode.US));
+ assertFalse(shortInfo.isEmergencyNumber("211", RegionCode.CA));
+ assertEquals(ShortNumberInfo.ShortNumberCost.UNKNOWN_COST,
+ shortInfo.getExpectedCostForRegion(parse("211", RegionCode.CA), RegionCode.CA));
+ }
+
+ private PhoneNumber parse(String number, String regionCode) {
+ try {
+ return phoneUtil.parse(number, regionCode);
+ } catch (NumberParseException e) {
+ throw new AssertionError(
+ "Test input data should always parse correctly: " + number + " (" + regionCode + ")", e);
+ }
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java b/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java
new file mode 100644
index 00000000..f4787141
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 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;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for ShortNumberUtil.java
+ *
+ * @author Shaopeng Jia
+ */
+public class ShortNumberUtilTest extends TestCase {
+ private ShortNumberUtil shortUtil;
+
+ public ShortNumberUtilTest() {
+ shortUtil = new ShortNumberUtil();
+ }
+
+ public void testConnectsToEmergencyNumber_US() {
+ assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.US));
+ assertTrue(shortUtil.connectsToEmergencyNumber("112", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberLongNumber_US() {
+ assertTrue(shortUtil.connectsToEmergencyNumber("9116666666", RegionCode.US));
+ assertTrue(shortUtil.connectsToEmergencyNumber("1126666666", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("9996666666", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberWithFormatting_US() {
+ assertTrue(shortUtil.connectsToEmergencyNumber("9-1-1", RegionCode.US));
+ assertTrue(shortUtil.connectsToEmergencyNumber("1-1-2", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("9-9-9", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumberWithPlusSign_US() {
+ assertFalse(shortUtil.connectsToEmergencyNumber("+911", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("\uFF0B911", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber(" +911", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("+112", RegionCode.US));
+ assertFalse(shortUtil.connectsToEmergencyNumber("+999", RegionCode.US));
+ }
+
+ public void testConnectsToEmergencyNumber_BR() {
+ assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.BR));
+ assertTrue(shortUtil.connectsToEmergencyNumber("190", RegionCode.BR));
+ assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.BR));
+ }
+
+ public void testConnectsToEmergencyNumberLongNumber_BR() {
+ // Brazilian emergency numbers don't work when additional digits are appended.
+ assertFalse(shortUtil.connectsToEmergencyNumber("9111", RegionCode.BR));
+ assertFalse(shortUtil.connectsToEmergencyNumber("1900", RegionCode.BR));
+ assertFalse(shortUtil.connectsToEmergencyNumber("9996", RegionCode.BR));
+ }
+
+ public void testConnectsToEmergencyNumber_AO() {
+ // Angola doesn't have any metadata for emergency numbers in the test metadata.
+ assertFalse(shortUtil.connectsToEmergencyNumber("911", RegionCode.AO));
+ assertFalse(shortUtil.connectsToEmergencyNumber("222123456", RegionCode.AO));
+ assertFalse(shortUtil.connectsToEmergencyNumber("923123456", RegionCode.AO));
+ }
+
+ public void testConnectsToEmergencyNumber_ZW() {
+ // Zimbabwe doesn't have any metadata in the test metadata.
+ assertFalse(shortUtil.connectsToEmergencyNumber("911", RegionCode.ZW));
+ assertFalse(shortUtil.connectsToEmergencyNumber("01312345", RegionCode.ZW));
+ assertFalse(shortUtil.connectsToEmergencyNumber("0711234567", RegionCode.ZW));
+ }
+
+ public void testIsEmergencyNumber_US() {
+ assertTrue(shortUtil.isEmergencyNumber("911", RegionCode.US));
+ assertTrue(shortUtil.isEmergencyNumber("112", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberLongNumber_US() {
+ assertFalse(shortUtil.isEmergencyNumber("9116666666", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("1126666666", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("9996666666", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberWithFormatting_US() {
+ assertTrue(shortUtil.isEmergencyNumber("9-1-1", RegionCode.US));
+ assertTrue(shortUtil.isEmergencyNumber("*911", RegionCode.US));
+ assertTrue(shortUtil.isEmergencyNumber("1-1-2", RegionCode.US));
+ assertTrue(shortUtil.isEmergencyNumber("*112", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("9-9-9", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("*999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumberWithPlusSign_US() {
+ assertFalse(shortUtil.isEmergencyNumber("+911", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("\uFF0B911", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber(" +911", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("+112", RegionCode.US));
+ assertFalse(shortUtil.isEmergencyNumber("+999", RegionCode.US));
+ }
+
+ public void testIsEmergencyNumber_BR() {
+ assertTrue(shortUtil.isEmergencyNumber("911", RegionCode.BR));
+ assertTrue(shortUtil.isEmergencyNumber("190", RegionCode.BR));
+ assertFalse(shortUtil.isEmergencyNumber("999", RegionCode.BR));
+ }
+
+ public void testIsEmergencyNumberLongNumber_BR() {
+ assertFalse(shortUtil.isEmergencyNumber("9111", RegionCode.BR));
+ assertFalse(shortUtil.isEmergencyNumber("1900", RegionCode.BR));
+ assertFalse(shortUtil.isEmergencyNumber("9996", RegionCode.BR));
+ }
+
+ public void testIsEmergencyNumber_AO() {
+ // Angola doesn't have any metadata for emergency numbers in the test metadata.
+ assertFalse(shortUtil.isEmergencyNumber("911", RegionCode.AO));
+ assertFalse(shortUtil.isEmergencyNumber("222123456", RegionCode.AO));
+ assertFalse(shortUtil.isEmergencyNumber("923123456", RegionCode.AO));
+ }
+
+ public void testIsEmergencyNumber_ZW() {
+ // Zimbabwe doesn't have any metadata in the test metadata.
+ assertFalse(shortUtil.isEmergencyNumber("911", RegionCode.ZW));
+ assertFalse(shortUtil.isEmergencyNumber("01312345", RegionCode.ZW));
+ assertFalse(shortUtil.isEmergencyNumber("0711234567", RegionCode.ZW));
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java b/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java
new file mode 100644
index 00000000..8845eb0c
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import junit.framework.TestCase;
+
+/**
+ * Root class for PhoneNumberUtil tests that depend on the test metadata file.
+ * <p>
+ * Note since tests that extend this class do not use the normal metadata file, they should not be
+ * used for regression test purposes.
+ *
+ * @author Shaopeng Jia
+ */
+public class TestMetadataTestCase extends TestCase {
+ private static final String TEST_META_DATA_FILE_PREFIX =
+ "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting";
+
+ protected final PhoneNumberUtil phoneUtil;
+
+ public TestMetadataTestCase() {
+ phoneUtil = initializePhoneUtilForTesting();
+ }
+
+ static PhoneNumberUtil initializePhoneUtilForTesting() {
+ PhoneNumberUtil phoneUtil = new PhoneNumberUtil(
+ TEST_META_DATA_FILE_PREFIX, PhoneNumberUtil.DEFAULT_METADATA_LOADER,
+ CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap());
+ PhoneNumberUtil.setInstance(phoneUtil);
+ return phoneUtil;
+ }
+}
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800 b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800
new file mode 100644
index 00000000..03c5f19e
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_800
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_979 b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_979
new file mode 100644
index 00000000..56897b27
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_979
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD
new file mode 100644
index 00000000..ace04c19
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AE b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AE
new file mode 100644
index 00000000..bc2e8d8e
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AE
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO
new file mode 100644
index 00000000..c306e037
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR
new file mode 100644
index 00000000..7d7fb24d
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU
new file mode 100644
index 00000000..44da9cfd
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BB b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BB
new file mode 100644
index 00000000..672f42b1
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BB
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR
new file mode 100644
index 00000000..c0f70683
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS
new file mode 100644
index 00000000..b9c6f228
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BY b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BY
new file mode 100644
index 00000000..706d64ed
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BY
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CA b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CA
new file mode 100644
index 00000000..a169c934
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CA
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CC b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CC
new file mode 100644
index 00000000..97fa27e9
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CC
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CN b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CN
new file mode 100644
index 00000000..9741b32e
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CN
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CX b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CX
new file mode 100644
index 00000000..334390d4
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_CX
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE
new file mode 100644
index 00000000..c6835b76
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_FR b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_FR
new file mode 100644
index 00000000..db0a6b39
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_FR
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB
new file mode 100644
index 00000000..cc39b9e2
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GG b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GG
new file mode 100644
index 00000000..32a4d0d0
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GG
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_HU b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_HU
new file mode 100644
index 00000000..d10ef035
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_HU
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT
new file mode 100644
index 00000000..fb81fe0c
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP
new file mode 100644
index 00000000..698c404b
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR
new file mode 100644
index 00000000..5c388435
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX
new file mode 100644
index 00000000..ff509e76
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ
new file mode 100644
index 00000000..fee7982c
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL
new file mode 100644
index 00000000..52b0c5a0
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE
new file mode 100644
index 00000000..7bb4228d
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG
new file mode 100644
index 00000000..b97c6812
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US
new file mode 100644
index 00000000..6058300b
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US
Binary files differ
diff --git a/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT
new file mode 100644
index 00000000..fa8356d7
--- /dev/null
+++ b/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT
Binary files differ