diff options
Diffstat (limited to 'java/libphonenumber')
740 files changed, 13204 insertions, 0 deletions
diff --git a/java/libphonenumber/build.xml b/java/libphonenumber/build.xml new file mode 100644 index 0000000..172c265 --- /dev/null +++ b/java/libphonenumber/build.xml @@ -0,0 +1,175 @@ +<?xml version="1.0" ?> + +<project name="libphonenumber" default="compile"> + <property name="src.dir" value="src"/> + <property name="test.dir" value="test"/> + <property name="build.dir" value="build"/> + <property name="classes.dir" value="${build.dir}/classes"/> + <property name="jar.dir" value="${build.dir}/jar"/> + <property name="lib.dir" value="../lib"/> + <property name="report.dir" value="${build.dir}/junitreport"/> + <property name="resources.dir" value="../../resources/"/> + <property name="javascript.dir" value="../../javascript/"/> + <property name="build.tools.jar" + value="../../tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar"/> + + <path id="classpath"> + <fileset dir="${lib.dir}" includes="**/*.jar"/> + </path> + <path id="test.classpath"> + <pathelement location="${classes.dir}"/> + <pathelement location="${lib.dir}/junit-4.8.1.jar"/> + <pathelement location="${jar.dir}/${ant.project.name}-test.jar"/> + <fileset dir="${lib.dir}"> + <include name="**/*.jar"/> + </fileset> + </path> + + <target name="build-metadata"> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="BuildMetadataProtoFromXml"/> + <arg value="${resources.dir}/PhoneNumberMetaData.xml"/> + <arg value="src"/> + <arg value="false"/> <!-- Not for testing. --> + <arg value="false"/> <!-- No lite metadata. --> + </exec> + </target> + + <target name="build-test-metadata"> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="BuildMetadataProtoFromXml"/> + <arg value="${resources.dir}/PhoneNumberMetaDataForTesting.xml"/> + <arg value="test"/> + <arg value="true"/> <!-- For testing. --> + <arg value="false"/> <!-- No lite metadata. --> + </exec> + </target> + + <target name="build-geo-data"> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="GenerateAreaCodeData"/> + <arg value="${resources.dir}/geocoding/"/> + <arg value="src/com/google/i18n/phonenumbers/geocoding/data"/> + </exec> + </target> + + <target name="build-geo-test-data"> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="GenerateAreaCodeData"/> + <arg value="${resources.dir}/test/geocoding/"/> + <arg value="test/com/google/i18n/phonenumbers/geocoding/testing_data"/> + </exec> + </target> + + <target name="build-js-metadata"> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="BuildMetadataJsonFromXml"/> + <arg value="${resources.dir}/PhoneNumberMetaData.xml"/> + <arg value="${javascript.dir}/i18n/phonenumbers/metadata.js"/> + </exec> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="BuildMetadataJsonFromXml"/> + <arg value="${resources.dir}/PhoneNumberMetaData.xml"/> + <arg value="${javascript.dir}/i18n/phonenumbers/metadatalite.js"/> + <arg value="true"/> <!-- Lite metadata. --> + </exec> + <exec executable="java"> + <arg value="-jar" /> + <arg value="${build.tools.jar}"/> + <arg value="BuildMetadataJsonFromXml"/> + <arg value="${resources.dir}/PhoneNumberMetaDataForTesting.xml"/> + <arg value="${javascript.dir}/i18n/phonenumbers/metadatafortesting.js"/> + </exec> + </target> + + <target name="compile" description="Compile Java source." + depends="build-metadata,build-geo-data"> + <mkdir dir="${classes.dir}"/> + <javac srcdir="${src.dir}" destdir="${classes.dir}" + classpathref="classpath" includeAntRuntime="false"/> + <javac srcdir="${test.dir}" destdir="${classes.dir}" + classpathref="classpath" debug="on" includeAntRuntime="false"/> + </target> + + <target name="jar" depends="compile"> + <mkdir dir="${jar.dir}"/> + <jar destfile="${jar.dir}/${ant.project.name}.jar"> + <fileset dir="${classes.dir}"> + <include name="**/*.class"/> + <exclude name="**/*Test*"/> + <exclude name="**/BuildMetadata*"/> + <exclude name="**/geocoding/*"/> + </fileset> + <fileset dir="${src.dir}"> + <include name="**/PhoneNumberMetadataProto*"/> + </fileset> + </jar> + <jar destfile="${jar.dir}/offline-geocoder.jar"> + <fileset dir="${classes.dir}"> + <include name="**/geocoding/*.class"/> + <exclude name="**/*Test*"/> + <exclude name="**/geocoding/GenerateAreaCodeData*"/> + </fileset> + <fileset dir="${src.dir}"> + <include name="**/geocoding/data/*"/> + </fileset> + </jar> + </target> + + <target name="test-jar" + depends="compile,build-test-metadata,build-geo-test-data"> + <mkdir dir="${jar.dir}"/> + <jar destfile="${jar.dir}/${ant.project.name}-test.jar"> + <fileset dir="${classes.dir}"> + <include name="**/*.class"/> + <exclude name="**/*Test*"/> + </fileset> + <fileset dir="${src.dir}"> + <include name="**/PhoneNumberMetadataProto*"/> + </fileset> + <fileset dir="${test.dir}"> + <include name="**/PhoneNumberMetadataProtoForTesting*"/> + </fileset> + <fileset dir="${test.dir}"> + <include name="**/geocoding/testing_data/*"/> + </fileset> + </jar> + </target> + + <target name="junit" depends="test-jar"> + <mkdir dir="${report.dir}"/> + <junit printsummary="yes"> + <classpath refid="test.classpath"/> + <formatter type="xml"/> + <batchtest fork="no" todir="${report.dir}"> + <fileset dir="${test.dir}" includes="**/*Test.java"/> + </batchtest> + </junit> + </target> + + <target name="junitreport"> + <junitreport todir="${report.dir}"> + <fileset dir="${report.dir}" includes="TEST-*.xml"/> + <report todir="${report.dir}"/> + </junitreport> + </target> + + <target name="clean" description="Remove generated files."> + <delete dir="${build.dir}"/> + </target> + + <target name="clean-build" depends="clean,jar"/> +</project> + diff --git a/java/libphonenumber/pom.xml b/java/libphonenumber/pom.xml new file mode 100644 index 0000000..2a4a9ae --- /dev/null +++ b/java/libphonenumber/pom.xml @@ -0,0 +1,205 @@ +<?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>4.3-SNAPSHOT</version> + <packaging>jar</packaging> + <name>libphonenumber</name> + <url>http://code.google.com/p/libphonenumber/</url> + + <parent> + <groupId>org.sonatype.oss</groupId> + <artifactId>oss-parent</artifactId> + <version>7</version> + </parent> + + <description> + Google's common Java library for parsing, formatting, storing and validating international phone numbers. + Optimized for running on smartphones. + </description> + + <organization> + <name>Google</name> + <url>http://www.google.com/</url> + </organization> + + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + </license> + </licenses> + + <scm> + <connection>scm:svn:http://libphonenumber.googlecode.com/svn/trunk/java/</connection> + <developerConnection>scm:svn:https://libphonenumber.googlecode.com/svn/trunk/java/</developerConnection> + <url>scm:svn:http://libphonenumber.googlecode.com/svn/trunk/java/</url> + </scm> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <developers> + <developer> + <id>jia.shao.peng</id> + <name>Shaopeng Jia</name> + <email>jia.shao.peng@gmail.com</email> + <organization>Google</organization> + <roles> + <role>owner</role> + <role>developer</role> + </roles> + </developer> + <developer> + <id>lararennie</id> + <name>Lara Rennie</name> + <email>lararennie@google.com</email> + <organization>Google</organization> + <roles> + <role>developer</role> + </roles> + </developer> + </developers> + + <contributors> + <contributor> + <name>tronikos</name> + <email>tronikos@gmail.com</email> + </contributor> + <contributor> + <name>g1smd.email</name> + <email>g1smd.email@gmail.com</email> + </contributor> + <contributor> + <name>Philippe Liard</name> + <email>philip.liard@gmail.com</email> + </contributor> + </contributors> + + <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> + <testResource> + <directory>test/com/google/i18n/phonenumbers/geocoding/testing_data</directory> + <targetPath>com/google/i18n/phonenumbers/geocoding/testing_data</targetPath> + </testResource> + </testResources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.3.1</version> + <configuration> + <excludes> + <exclude>**/geocoding/</exclude> + </excludes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.10</version> + <configuration> + <forkMode>never</forkMode> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>2.1.2</version> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.7</version> + <executions> + <execution> + <id>attach-javadocs</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-release-plugin</artifactId> + <version>2.0-beta-7</version> + <configuration> + <tagBase> + https://libphonenumber.googlecode.com/svn/tags/ + </tagBase> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.3.2</version> + <configuration> + <source>1.5</source> + <target>1.5</target> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>release-sign-artifacts</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-gpg-plugin</artifactId> + <version>1.1</version> + <executions> + <execution> + <id>sign-artifacts</id> + <phase>verify</phase> + <goals> + <goal>sign</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.8.1</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/java/libphonenumber/release_notes.txt b/java/libphonenumber/release_notes.txt new file mode 100644 index 0000000..0fb5dc6 --- /dev/null +++ b/java/libphonenumber/release_notes.txt @@ -0,0 +1,361 @@ +November 10th, 2011: libphonenumber-4.2 +* Code changes + - Providing an "exact match" isEmergencyNumber method + - Improvement to PhoneNumberMatcher: requires national prefix to be present + when matching national-format numbers, unless matching for a region where it + is explicitly marked in the metadata that they may be omitted. Applies to + leniency level VALID and higher. + - Change formatNumberForMobileDialing not to modify the phoneNumber passed in. + +* Metadata changes + - Emergency numbers added for all remaining countries + - Collected data on which numbers we format with a national prefix are + commonly written without one and added this + - Updates for AR, AT, BH, CZ, GR, IR, KM, LT, MX, PT, SE, SO, UG + - Addition of SX (Sint Maarten) + +October 19th, 2011: libphonenumber-4.1 +* Code changes + - Update code and metadata for countries with IDD "8~10" to accept phone + numbers where the "~" is omitted. + - Modify formatInOriginalFormat to use raw_input (when present) when the number + is considered as invalid by the library. + - Add ShortNumberUtil to deal with international short phone numbers, such as + short codes and emergency numbers. + - Increase the maximum phone-number length accepted when parsing (now set to + 16). + +* Metadata changes + - Updates: BF, BN, CN, DE, DK, DO, FR, IN, KI, KW, MC, MD, ML, PA, QA, SB, UK, + WS + - Emergency number information also added to: AE, AF, AL, AM, AR, AT, AU, BA, + BB, BD, BE, BG, BH, BO, BR, BY, CA, CH, CL, CN, CO, CR, CY, CZ, DE, DJ, DK, + DO, DZ, EC, EE, EG, ES, FI, FJ, FO, FR, GB, GE, GF, GH, GI, GL, GR, GT, GY, + HK, HN, HR, HU, ID, IE, IL, IN, IR, IS, IT, JM, JO, JP, KR, KW, KY, KZ, LB, + LK, LT, LU, LV, MA, MC, MD, ME, MK, ML, MM, MN, MO, MT, MU, MV, MX, MY, NG, + NI, NL, NO, NP, OM, PA, PE, PH, PK, PL, PM, PT, PY, QA, RO, RS, RU, RW, SA, + SB, SD, SE, SG, SI, SK, SL, SM, SR, SV, SY, TD, TH, TJ, TM, TN, TR, TT, TW, + UA, UG, US, UY, UZ, VA, VE, VN, VU, ZA, ZM, ZW + +October 6th, 2011: libphonenumber-4.0 +* Code changes + - New function formatNumberForMobileDialing, which attempts to format a number in + such a way that the call can be connected from a mobile phone. If this is + impossible, for example for numbers that cannot be internationally dialled, + then an empty string is returned. + - Fallback functionality to English for non-CJK languages for geocoding + +* Metadata changes + - Collecting data for emergency numbers + - Updates: AR, AU, BR, CN, CZ, EG, GD, IE, IL, JM, KW, KH, SD, SO, TR, UG, UZ + - Geocoding data changes: AO, AR, AT, BJ, BR, CD, CG, CI, CL, CN, CV, DE, ES, + FR, GR, GW, HU, KM, MR, MZ, NL, PL, PT, SE, ST, SZ + +September 13th, 2011: libphonenumber-3.9 +* Code changes + - Enable AsYouTypeFormatter to handle long IDD and NDD. + - Allow the presence of an IDD following a +. + - Fix formatting of phone numbers which contain only 0s in the national number. + - Refactored some code in geocoding including AreaCodeMap and the storage + strategies. + +* Metadata changes + - Updates: AM, BE, BH, BJ, BR, BT, BZ, CI, CL, CN, DE, DK, DM, DZ, EC, EG, FJ, + GR, HR, HT, IN, IQ, IS, JM, KE, KG, KH, KR, LA, LB, LR, MA, MD, ML, MO, MX, + MY, NE, NG, PG, PH, PK, PY, QA, SA, SD, SG, SN, TD, TG, TH, TN, TT, UG, YE, + ZA, ZM + - New geocoding data for: AC, CG, CU, CV, EG, ET, FI, FI, FI, GL, JP, KM, MA, + MA, MU, MU, MU, MZ, RS, SH, SH, SL, SO, ST, TG, TG, TG, UG, ZM + - Updated geocoding data for: AR, DE + +August 11th, 2011: libphonenumber-3.8 +* Code changes + - Fix to demo to not throw null-ptr exceptions for invalid NANPA numbers + - Fixed AYTF to not accept plus signs in the middle of input + - PhoneNumberMatcher improvements - added STRICT_GROUPING and EXACT_GROUPING + levels, numbers followed/preceded by a currency symbol will not match, + multiple numbers separated by phone-number punctuation will now match. ", " + is no longer accepted as an extension symbol when matching, only when + parsing. "x" is only accepted as a carrier code or extension marker, not + otherwise. + - Changes to handling of leading zeroes - these will not be silently ignored + anymore, but will be stored as part of the number. + - PhoneNumberOfflineGeocoder - new method to get the description of a number that assumes + the validity of the number has already been checked and will not re-verify it. + - Split geocoding US binary data into multiple files. + +* Metadata changes + - Updates: AR, AT, AU, AZ, BE, BF, BH, BY, CA, CN, CO, CR, HT, HU, IT, KG, KH, + LB, LI, ME, NC, RS, SE, TT, US, VG, ZA + - New geocoding data for: AL, AM, AO, BF, BJ, BW, CD, CI, CZ, DZ, EE, GH, GM, + GN, GR, GW, HU, IS, KE, LK, LS, LT, LU, LV, MD, MG, MR, NA, PE, QN, SD, SK, + SN, SZ, TN, VE, VN, ZA, ZW + - Updated geocoding data for: GB, PT, US + - Revised sorting of geocoding data + +July 5th, 2011 +* Code changes + - Refactored AreaCodeMap to minimize binary and memory footprint by using 2 different strategies. + - Refactored BuildMetadataFromXml.java and added unittests. + +* Metadata changes + - Regenerate binaries for all existing area code mapping data with smaller sizes. + - Added city-level area code data mapping for US and Canada. + +June 29th, 2011 +* Code changes + - Fixed issue 38, issue 39, issue 41 and issue 43 + +* Metadata changes + - Added phone number area mapping files for + - JP in Japanese + - FR in French + - TW in English, Simplified and Traditional Chinese + - RU in English + - IT in English and Italian + - PT in Portuguese + - TR in English and Turkish + - CH in English, German, French and Italian + - Updates: CR, GE, IT, JP, KW, MH, MP, MU, PE, PM, RW, TG, TJ, TK + +June 14th, 2011 +* Code changes + - Added PhoneNumberOfflineGeocoder, supporting classes and their unittests. + - Added GenerateAreaCodeData to transform phone number area mapping files from text files to binary + files. + - Modified PhoneNumberParserServlet.java and phonenumberparser.jsp to incorporate + PhoneNumberOfflineGeocoding in the appengine demo. + +* Metadata changes + - Added phone number area mapping files for NANPA countries and GB in English, NL in Dutch, AR, CL + and ES in Spanish, AT and DE in German, SE in Swedish, BR in Portuguese, KR in English, Korean, + Simplified and Traditional Chinese, and CN in Simplified Chinese. + +June 10th, 2011 +* Code changes: + - Fixes for PhoneNumberMatcher to be more restrictive in valid mode and not match numbers + surrounded by Latin characters. This ensures, for example, the string abc123456789acg will not be + marked as a phone numbers. + - Enable PhoneNumberUtil to handle all digits, rather than a subset + - Fix for AYTF issue36 and improvement for US AYTF behaviour. +* Metadata changes: + - Updates: BG, EG, ES, GH, PF, SC, SY, VA + +May 24th, 2011 +* Code changes: + - Phonenumber now implements Serializable. + - findNumbers doesn't accept numbers with mis-matched brackets as phone-numbers + - An offline phone number geocoder has been added. The current implementation just returns the + region name for the phone number; more detailed geocoding will be added later. +* Metadata changes: + - New countries: GF, KP, NC, PA, PF, PW, PY, SB, SR, TO, UY, VU + - Updates: CY, CZ, ES, GB, GQ, JM, MQ, TN, VI + +May 9th, 2011 +* Code changes: + - Fixed potential for a null-ptr exception in getExampleNumber + - Potential speed improvement with replacement of StringBuffer with StringBuilder +* Metadata changes + - Changed way that international formats are specified to make it easier to do so + - New countries: AX, CC, CX, WF + - Updates: AM, AR, AU, AW, CN, CO, CR, DM, EC, ET, FI, FJ, GH, IN, JP, KE, KM, + KN, LR, MD, MQ, MX, NP, PH, SC, SE, SM, SN, SY, UG, US, VC, VI, ZM + +Apr 26th, 2011 +* Code changes: + - Improved PhoneNumberMatcher for cases with other numbers before or after the phone number. + - Improved AsYouTypeFormatter not to use formatting rules containing non-formatting characters + (e.g. '*' in Israeli star numbers). +* Metadata changes: + - New countries: FJ, FM, GY, NF, NI, NR, TV. + - Updates: AM, AZ, BF, BW, BZ, CI, CR, GB, GP, HK, JM, KH, LB, LY, MV, PE, PK, SZ, TJ, US. +* Minor documentation updates + +Apr 11th, 2011 +* Bug fixes: + - Adding date exclusion pattern in PhoneNumberMatcher. + - Fixing bug with selecting a suitable region for numbers with leading zeros where mutiple regions + for that country code are possible. +* Metadata changes: + - Updates: AG, AI, AS, BB, BM, BS, CA, DM, DO, ET, FO, GD, GE, GU, IN, JM, KN, KY, LC, MN, MP, MR, + MS, NO, PR, TC, TR, TT, US, VC, VG, VI + - New countries: CK, FK, GT, IO, KI, SJ, SV +* Documentation updates and some small refactoring to AsYouTypeFormatter + +Mar 31st, 2011 +* New functionality: + - Can parse and format numbers in RFC-3966 format. + - Added isAlphaNumber to check to see if a number is a "vanity" or "alpha" number + - Can format a number made up of alpha-characters in an "out-of-country" format (e.g. 0011 1 + 800-SIX-FLAG to dial an American alpha-number from Australia). +* Code changes: + - Renamed private vars, private methods and fixed comments to try and differentiate between country + (calling) codes and region codes. + == Non-backwards-compatible API changes: == + - Renamed getSupportedCountries to getSupportedRegions, as this more accurately reflects that the + library is based around region codes. + - getNationalSignificantNumber is no longer a static method, but is instead an instance method. +* Metadata changes: + - Bug-fixes and updates for AU, AZ, EE, FI, IN, JO, KW, KZ, MV, RU, RR, VA + - New country: ME + +Mar 22nd, 2011 +* Metadata changes: + - New mobile-number pattern for AU + +Mar 10th, 2011 +* New functionality: + - New function to format a number with the preferred domestic carrier code used when parsing, + falling back to a default calling code otherwise (formatNationalNumberWithPreferredCarrierCode). + - We now store the preferred domestic carrier code used when the user calls parseAndKeepRawInput + - New functionality to extract phone-numbers from text (findNumbers). This is just the first + version - it does not extract ALPHA numbers such as 0800 CALL ME, or numbers where alternate + endings are specified (such as 03-331 6005/6006). +* Code changes: + - Tidying up the test file to use several pre-defined phone number constants + - Fixing several lint errors + - Added javadoc to formatNationalNumberWithCarrierCode + - Fixed bug where a null pointer exception was thrown when getAsYouTypeFormatter was called with an + invalid region code + - Improved AsYouTypeFormatter to deal with countries with variable-length patterns such as LU +* Metadata changes: + - Bug-fixes and updates for the following countries: BF, BO, BR, CL, CO, CR, DK, FO, GE, KR, KW, + LA, LU, MU, SC, SH, TR, VE + - New country: SH + +Mar 10th, 2011 +* Code changes: + - releasing the code to run the demo on localhost or appengine. + +Mar 7th, 2011 +* Metadata changes: + - Adding support for AC + +Feb 11th, 2011 +* Metadata changes: + - Update UAN number ranges for IM and JE. + +Feb 9th, 2011 +* Code changes: + - Better isNumberMatch method. This will now recognise numbers starting with a national prefix as + an NSN_MATCH, instead of SHORT_NSN_MATCH. + == Note Non-backwards-compatible API change here! == + This will no longer throw a NumberParseException - instead we will return NOT_A_NUMBER if one + or other of the numbers provided do not match. + - New number-type UAN now supported in the code. This represents Company Numbers or Universally + Accessible Numbers. +* Metadata changes: + - Bug-fixes and updates for the following countries: AG, AZ, BA, BE, CA, CU, ES, FI, GB, GD, GG, + IE, IL, IM, IN, IR, IT, JE, JP, KR, KW, NG, NZ, PK, PS, PT, RU, SE, SG, SY, US + - New countries: CO, LU, LY, MC, SM + - Addition of "Personal Number" ranges to all NANPA countries + +Jan 31st, 2011 +* Code changes: + - Introducing equals() and hashCode() methods for the Phonenumber.PhoneNumber class + +Jan 28th, 2011 +* Code changes: + - Fixing critical bug with non-Android-compatible code. isEmpty() was being used and CANON_EQ in + reg-ex matches. + +Jan 20th, 2011 +* Code improvements: + - Handle null phone-numbers when parsing by throwing a NumberParseException. + - Handle extension written with an accented "o", as per Spanish, when parsing. + - Handle U+30FC dashes as phone-number punctuation. + - Allow "ZZ" or null regions to be specified for numbers starting with a full-width "+" symbol, or + with other characters (such as whitespace) before the leading +. + - new getLengthOfNationalDestinationCode function +* Metadata changes: + - New types of numbers introduced: UAN (universal or "company" numbers) and short codes. Note that + "generalDesc" patterns do not encompass short-codes. No code-support for these has been + introduced as of yet. We are also now enabling the collection of data for information such as + area-code-optional, and no-international-dialling ranges. + - Data updates as per ITU notifications/bug fixes for the following countries: AM, BH, CD, CG, CR, + DE, DJ, EE, GB, GN, HU, IE, JO, JP, LB, LR, MA, MK, MN, MR, NA, PG, SC, SG, SO, SZ, VN, ZA, ZW + - Data added for the following countries: BZ, CU, EC, FO, GI, HN, HT, LK, MT, MV, NU, PS, SD + - Indentation fixes in reg-exes for the following countries: BG, GB + - Allow nationalPrefixForParsing to be specified for countries with no national prefix, to handle + possible carrier prefixes + +Jan 3rd, 2011 +* Metadata changes: + - Updates to JE + - Updated comments for GB/GG/IM/JE + +November 25th, 2010 +* Metadata changes: + - Updates to existing countries: AD, AG, AI, AN, AS, BB, BG, BM, BS, BW, CA, DM, DO, GD, GH, GM, + GU, IN, JM, KN, KY, KZ, LB, LC, MP, MS, PR, SY, TC, TT, TZ, US, VC, VG, VI. + - Reorganize reg-exes for better readability. + - Updated comments. + +October 22nd, 2010 +* Metadata changes: + - Updates to existing countries: AE, GB, GG, IM, JE + +October 15th, 2010 +* Code improvements: + - Allowed parsing of numbers that start with "++" or a full-width "+" symbol + - Allowed reg-exes for national and possible number patterns to have white space in them in the + source XML file + - Added a more useful toString method for the phone number proto class +* Metadata changes: + - Updates to existing countries: AF, BF, BO, ES, GB, GG, IM, IS, JE, JE, JP, KR, PE, PT, RU, SE, + TT, ZW +* Bug fixes: + - Parsing empty strings with invalid region codes no longer throws a null pointer exception + +September 4th, 2010 +* Code improvement: + - Added new phone number type: pager +* Metadata change: + - update to existing country: GG, IM, JE, RS, RU +* Bug fixes: + - ArrayOutOfBoundException in AsYouTypeFormatter.getRememberedPosition() + - AsYouTypeFormatter for UK childline number + +September 1st, 2010 +* Bug fix on KZ metadata. + +August 17th, 2010 +* Code improvement: + - Refactored BuildMetadataProtoFromXml.java into BuildMetadataFromXml.java and + BuildMetadataProtoFromXml.java + - Added BuildMetadataProtoFromXml.java and JSArrayBuilder.java + - Refactored CountryCodeToRegionCodeMap and CountryCodeToRegionCodeMapForTesting into separate + files. + +August 16th, 2010 +* Bug fixes + - AsYouTypeFormatter for formatting Chinese geographical numbers entered in national format. + - AsYouTypeFormatter for formatting Chinese 400/800 numbers entered in national format. +* Metadata change: + - new countries: AM, AN, BH, GL, IS + - adding national prefix 1 to all NANPA countries. + - update to existing countries: BF, FR, UK, PK, RE + +August 4th, 2010 +* Further improve startup performance + - Preload no country specific metadata at startup. + - Stop creating the file containing mapping from country calling code to region code + and loading it at startup; instead, do the initialization in PhoneNumberUtil. + +July 31th, 2010 + +* Improve startup performance + - Separate generated metadata binary file to one file per region + - Preload US at start up, and load other region at the time when needed + - Create a file containing mapping from country calling code to region code, + and load it at startup + - Same change also applied to unittests + +July 30th, 2010 +* Metadata change: + - new country: TL + - update to existing country: AZ, CN, FR, GH, JO, LA, PG, PK, QA, SZ, UA, VN + +* Code improvement + - China local number formatting for AsYouTypeFormatter + - improve extension parsing to handle number in the form of +1 (645) 123 1234 ext. 910# diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java new file mode 100644 index 0000000..80eae06 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java @@ -0,0 +1,574 @@ +/* + * 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; + private boolean isInternationalFormatting = false; + private boolean isExpectingCountryCallingCode = false; + private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + private String defaultCountry; + + 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 + "]*)+"); + + // 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 String digitPlaceholder = "\u2008"; + private Pattern digitPattern = Pattern.compile(digitPlaceholder); + 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(); + // This contains the national prefix that has been extracted. It contains only digits without + // formatting. + private String nationalPrefixExtracted = ""; + 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; + // 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 leadingThreeDigits) { + List<NumberFormat> formatList = + (isInternationalFormatting && currentMetaData.intlNumberFormatSize() > 0) + ? currentMetaData.intlNumberFormats() + : currentMetaData.numberFormats(); + for (NumberFormat format : formatList) { + if (isFormatEligible(format.getFormat())) { + possibleFormats.add(format); + } + } + narrowDownPossibleFormats(leadingThreeDigits); + } + + 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() > indexOfLeadingDigitsPattern) { + Pattern leadingDigitsPattern = + regexCache.getPatternForRegex( + format.getLeadingDigitsPattern(indexOfLeadingDigitsPattern)); + Matcher m = leadingDigitsPattern.matcher(leadingDigits); + if (!m.lookingAt()) { + it.remove(); + } + } // else the particular format has no more specific leadingDigitsPattern, and it should be + // retained. + } + } + + 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 digitPlaceholder + template = template.replaceAll("9", digitPlaceholder); + 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); + nationalPrefixExtracted = ""; + nationalNumber.setLength(0); + ableToFormat = true; + inputHasFormatting = false; + positionToRemember = 0; + originalPosition = 0; + isInternationalFormatting = false; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + 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. + prefixBeforeNationalNumber.append(" "); + 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. + nationalPrefixExtracted = removeNationalPrefixFromNationalNumber(); + return attemptToChooseFormattingPattern(); + } + default: + if (isExpectingCountryCallingCode) { + if (attemptToExtractCountryCallingCode()) { + isExpectingCountryCallingCode = false; + } + return prefixBeforeNationalNumber + nationalNumber.toString(); + } + if (possibleFormats.size() > 0) { // The formatting pattern is 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 + ? prefixBeforeNationalNumber + tempNationalNumber + : tempNationalNumber; + } else { + return attemptToChooseFormattingPattern(); + } + } + } + + private String attemptToChoosePatternWithPrefixExtracted() { + ableToFormat = true; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + return attemptToChooseFormattingPattern(); + } + + // 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 (nationalPrefixExtracted.length() > 0) { + // Put the extracted NDD back to the national number before attempting to extract a new NDD. + nationalNumber.insert(0, nationalPrefixExtracted); + // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set + // it to empty string because people sometimes enter national prefix after country code, e.g + // +44 (0)20-1234-5678. + int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(nationalPrefixExtracted); + prefixBeforeNationalNumber.setLength(indexOfPreviousNdd); + } + return !nationalPrefixExtracted.equals(removeNationalPrefixFromNationalNumber()); + } + + private boolean isDigitOrLeadingPlusSign(char nextChar) { + return Character.isDigit(nextChar) || + (accruedInput.length() == 1 && + PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches()); + } + + String attemptToFormatAccruedDigits() { + for (NumberFormat numFormat : possibleFormats) { + Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber); + if (m.matches()) { + String formattedNumber = m.replaceAll(numFormat.getFormat()); + return prefixBeforeNationalNumber + 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; + } + + // 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 as least MIN_LEADING_DIGITS_LENGTH digits of national + // number (excluding national prefix) have been entered. + if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) { + getAvailableFormats(nationalNumber.substring(0, MIN_LEADING_DIGITS_LENGTH)); + maybeCreateNewTemplate(); + return inputAccruedNationalNumber(); + } else { + return prefixBeforeNationalNumber + 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 + ? prefixBeforeNationalNumber + tempNationalNumber + : tempNationalNumber; + } else { + return prefixBeforeNationalNumber.toString(); + } + } + + // Returns the national prefix extracted, or an empty string if it is not present. + private String removeNationalPrefixFromNationalNumber() { + int startOfNationalNumber = 0; + if (currentMetaData.getCountryCode() == 1 && nationalNumber.charAt(0) == '1') { + startOfNationalNumber = 1; + prefixBeforeNationalNumber.append("1 "); + isInternationalFormatting = true; + } else if (currentMetaData.hasNationalPrefixForParsing()) { + Pattern nationalPrefixForParsing = + regexCache.getPatternForRegex(currentMetaData.getNationalPrefixForParsing()); + Matcher m = nationalPrefixForParsing.matcher(nationalNumber); + if (m.lookingAt()) { + // 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. + isInternationalFormatting = 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()) { + isInternationalFormatting = 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(" "); + } + 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 (!newRegionCode.equals(defaultCountry)) { + currentMetaData = getMetadataForRegion(newRegionCode); + } + String countryCodeString = Integer.toString(countryCode); + prefixBeforeNationalNumber.append(countryCodeString).append(" "); + 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 = digitPattern.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/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java new file mode 100644 index 0000000..b69c3ca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java @@ -0,0 +1,898 @@ +/* + * 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 273 as there are 205 different country codes, + // and this offers a load factor of roughly 0.75. + Map<Integer, List<String>> countryCodeToRegionCodeMap = + new HashMap<Integer, List<String>>(273); + + 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("MA"); + 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>(1); + listWithRegionCode.add("SH"); + 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>(1); + listWithRegionCode.add("AN"); + 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("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("BD"); + countryCodeToRegionCodeMap.put(880, listWithRegionCode); + + listWithRegionCode = new ArrayList<String>(1); + listWithRegionCode.add("TW"); + countryCodeToRegionCodeMap.put(886, 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("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/java/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java new file mode 100644 index 0000000..7d2bb30 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/NumberParseException.java @@ -0,0 +1,63 @@ +/* + * 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. + * @author Lara Rennie + */ +@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/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java new file mode 100644 index 0000000..5e19b48 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatch.java @@ -0,0 +1,125 @@ +/* + * 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> + * + * @author Tom Hofmann + */ +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/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java new file mode 100644 index 0000000..62586f1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java @@ -0,0 +1,446 @@ +/* + * 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 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. + * + * @author Tom Hofmann + */ +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}"); + + /** + * 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; + + /** + * Matches white-space, which may indicate the end of a phone number and the start of something + * else (such as a neighbouring zip-code). If white-space is found, continues to match all + * characters that are not typically used to start a phone number. + */ + private static final Pattern GROUP_SEPARATOR; + + /** + * 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); + GROUP_SEPARATOR = Pattern.compile("\\p{Z}" + "[^" + leadClassChars + "\\p{Nd}]*"); + + /* 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; + } + + 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; + } + + /** + * 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 isCurrencySymbol(char character) { + return 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 a publication page reference or a date. + if (PUB_PAGES.matcher(candidate).find() || SLASH_SEPARATED_DATES.matcher(candidate).find()) { + 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) { + // Try removing either the first or last "group" in the number and see if this gives a result. + // We consider white space to be a possible indication of the start or end of the phone number. + Matcher groupMatcher = GROUP_SEPARATOR.matcher(candidate); + + if (groupMatcher.find()) { + // Try the first group by itself. + CharSequence firstGroupOnly = candidate.substring(0, groupMatcher.start()); + firstGroupOnly = trimAfterFirstMatch(PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, + firstGroupOnly); + PhoneNumberMatch match = parseAndVerify(firstGroupOnly.toString(), offset); + if (match != null) { + return match; + } + maxTries--; + + int withoutFirstGroupStart = groupMatcher.end(); + // Try the rest of the candidate without the first group. + CharSequence withoutFirstGroup = candidate.substring(withoutFirstGroupStart); + withoutFirstGroup = trimAfterFirstMatch(PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, + withoutFirstGroup); + match = parseAndVerify(withoutFirstGroup.toString(), offset + withoutFirstGroupStart); + if (match != null) { + return match; + } + maxTries--; + + if (maxTries > 0) { + int lastGroupStart = withoutFirstGroupStart; + while (groupMatcher.find()) { + // Find the last group. + lastGroupStart = groupMatcher.start(); + } + CharSequence withoutLastGroup = candidate.substring(0, lastGroupStart); + withoutLastGroup = trimAfterFirstMatch(PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, + withoutLastGroup); + if (withoutLastGroup.equals(firstGroupOnly)) { + // If there are only two groups, then the group "without the last group" is the same as + // the first group. In these cases, we don't want to re-check the number group, so we exit + // already. + return null; + } + match = parseAndVerify(withoutLastGroup.toString(), offset); + 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()) { + 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 a currency symbol. + if (isCurrencySymbol(previousChar) || isLatinLetter(previousChar)) { + return null; + } + } + int lastCharIndex = offset + candidate.length(); + if (lastCharIndex < text.length()) { + char nextChar = text.charAt(lastCharIndex); + if (isCurrencySymbol(nextChar) || isLatinLetter(nextChar)) { + return null; + } + } + } + + PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion); + if (leniency.verify(number, candidate, phoneUtil)) { + // We used parseAndKeepRawInput to create this number, but for now we don't return the extra + // values parsed. TODO: stop clearing all values here and switch all users over + // to using rawInput() rather than the rawString() of PhoneNumberMatch. + number.clearCountryCodeSource(); + number.clearRawInput(); + number.clearPreferredDomesticCarrierCode(); + return new PhoneNumberMatch(offset, candidate, number); + } + } catch (NumberParseException e) { + // ignore and continue + } + return null; + } + + /** + * Always throws {@link UnsupportedOperationException} as removal is not supported. + */ + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java new file mode 100644 index 0000000..a600334 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -0,0 +1,2790 @@ +/* + * 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.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/english_country_names_and_code_elements + * + * @author Shaopeng Jia + * @author Lara Rennie + */ +public class PhoneNumberUtil { + /** 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 = 3; + // The ITU says the maximum length should be 15, but we have found longer numbers in Germany. + static final int MAX_LENGTH_FOR_NSN = 16; + // The maximum length of the country calling code. + static final int MAX_LENGTH_COUNTRY_CODE = 3; + static final String META_DATA_FILE_PREFIX = + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto"; + private String currentFilePrefix = META_DATA_FILE_PREFIX; + private static final Logger LOGGER = Logger.getLogger(PhoneNumberUtil.class.getName()); + + // 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 Map<Integer, List<String>> countryCallingCodeToRegionCodeMap = null; + + // The set of regions the library supports. + // There are roughly 220 of them and we set the initial capacity of the HashSet to 300 to offer a + // load factor of roughly 0.75. + private final Set<String> supportedRegions = new HashSet<String>(300); + + // Region-code for the unknown region. + private static final String UNKNOWN_REGION = "ZZ"; + + // The set of regions that share country calling code 1. + // There are roughly 26 regions and 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); + 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"; + + // The PLUS_SIGN signifies the international prefix. + static final char PLUS_SIGN = '+'; + + private static final String RFC3966_EXTN_PREFIX = ";ext="; + + // 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 { + // 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> 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\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: + // plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])* + // Note VALID_PUNCTUATION starts with a -, so must be the first in the range. + private static final String VALID_PHONE_NUMBER = + "[" + PLUS_CHARS + "]*(?:[" + VALID_PUNCTUATION + "]*" + DIGITS + "){3,}[" + + VALID_PUNCTUATION + 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,]*" + + "(?:ext(?: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); + + private 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"); + + private static PhoneNumberUtil instance = null; + + // A mapping from a region code to the PhoneMetadata for that region. + private final Map<String, PhoneMetadata> regionToMetadataMap = + Collections.synchronizedMap(new HashMap<String, PhoneMetadata>()); + + // A cache for frequently used region-specific regular expressions. + // As most people use phone numbers primarily from one to two countries, and there are roughly 60 + // regular expressions needed, the initial capacity of 100 offers a rough load factor of 0.75. + private RegexCache regexCache = new RegexCache(100); + + /** + * 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=". + * + * 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, + // 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.PhoneNumber) possible}, but not + * necessarily {@linkplain PhoneNumberUtil#isValidNumber(Phonenumber.PhoneNumber) valid}. + */ + POSSIBLE { + @Override + boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util) { + return util.isPossibleNumber(number); + } + }, + /** + * Phone numbers accepted are + * {@linkplain PhoneNumberUtil#isPossibleNumber(Phonenumber.PhoneNumber) possible} and + * {@linkplain PhoneNumberUtil#isValidNumber(Phonenumber.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) || + !containsOnlyValidXChars(number, candidate, util)) { + return false; + } + return 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 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) || + !containsOnlyValidXChars(number, candidate, util) || + containsMoreThanOneSlash(candidate) || + !isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + // TODO: Evaluate how this works for other locales (testing has been + // limited to NANPA regions) and optimise if necessary. + String[] formattedNumberGroups = getNationalNumberGroups(util, number); + StringBuilder normalizedCandidate = normalizeDigits(candidate, + true /* keep strip non-digits */); + int fromIndex = 0; + // Check each group of consecutive digits are not broken into separate groups in the + // {@code candidate} string. + for (int i = 0; i < formattedNumberGroups.length; i++) { + // Fails if the substring of {@code candidate} 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. + if (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. + 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()); + } + }, + /** + * 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) || + !containsOnlyValidXChars(number, candidate, util) || + containsMoreThanOneSlash(candidate) || + !isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + // TODO: Evaluate how this works for other locales (testing has been + // limited to NANPA regions) and optimise if necessary. + StringBuilder normalizedCandidate = normalizeDigits(candidate, + true /* keep strip non-digits */); + String[] candidateGroups = + 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; + } + String[] formattedNumberGroups = getNationalNumberGroups(util, number); + // 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) { + // 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("-"); + } + + private static boolean containsMoreThanOneSlash(String candidate) { + int firstSlashIndex = candidate.indexOf('/'); + return (firstSlashIndex > 0 && candidate.substring(firstSlashIndex + 1).contains("/")); + } + + private 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; + } + + private 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; + } + // Remove the first-group symbol. + String candidateNationalPrefixRule = formatRule.getNationalPrefixFormattingRule(); + // We assume that the first-group symbol will never be _before_ the national prefix. + candidateNationalPrefixRule = + candidateNationalPrefixRule.substring(0, candidateNationalPrefixRule.indexOf("$1")); + candidateNationalPrefixRule = util.normalizeDigitsOnly(candidateNationalPrefixRule); + if (candidateNationalPrefixRule.length() == 0) { + // National Prefix not needed for this number. + return true; + } + // Normalize the remainder. + String rawInputCopy = util.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; + } + + /** Returns true if {@code number} is a verified number according to this leniency. */ + abstract boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util); + } + + /** + * This class implements a singleton, so the only constructor is private. + */ + private PhoneNumberUtil() { + } + + private void init(String filePrefix) { + currentFilePrefix = filePrefix; + for (List<String> regionCodes : countryCallingCodeToRegionCodeMap.values()) { + supportedRegions.addAll(regionCodes); + } + nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE)); + } + + private void loadMetadataForRegionFromFile(String filePrefix, String regionCode) { + InputStream source = + PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + regionCode); + ObjectInputStream in = null; + try { + in = new ObjectInputStream(source); + PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection(); + metadataCollection.readExternal(in); + for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { + regionToMetadataMap.put(regionCode, metadata); + } + } catch (IOException e) { + LOGGER.log(Level.WARNING, e.toString()); + } finally { + close(in); + } + } + + private static void close(InputStream in) { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + LOGGER.log(Level.WARNING, e.toString()); + } + } + } + + /** + * 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 3 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(); + } + + private 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; + } + + /** + * 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 in the {@code nationalNumber_} field of 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. + * <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) { + String regionCode = getRegionCodeForNumber(number); + if (!isValidRegionCode(regionCode)) { + return 0; + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (!metadata.hasNationalPrefix()) { + return 0; + } + + PhoneNumberType type = getNumberTypeHelper(getNationalSignificantNumber(number), + metadata); + // Most numbers other than the two types below have to be dialled in full. + if (type != PhoneNumberType.FIXED_LINE && type != PhoneNumberType.FIXED_LINE_OR_MOBILE) { + 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 (getRegionCodeForCountryCode(number.getCountryCode()).equals("AR") && + getNumberType(number) == PhoneNumberType.MOBILE) { + // 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 1 for + // the digit 9, which also forms part of the national significant number. + // + // TODO: Investigate the possibility of better modeling the metadata to make it + // easier to obtain the NDC. + return numberGroups[3].length() + 1; + } + return numberGroups[2].length(); + } + + /** + * 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()); + char[] numberAsCharArray = number.toCharArray(); + for (char character : numberAsCharArray) { + 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(); + } + + static synchronized PhoneNumberUtil getInstance( + String baseFileLocation, + Map<Integer, List<String>> countryCallingCodeToRegionCodeMap) { + if (instance == null) { + instance = new PhoneNumberUtil(); + instance.countryCallingCodeToRegionCodeMap = countryCallingCodeToRegionCodeMap; + instance.init(baseFileLocation); + } + return instance; + } + + /** + * Used for testing purposes only to reset the PhoneNumberUtil singleton to null. + */ + static synchronized void resetInstance() { + instance = null; + } + + /** + * Convenience method to get a list of what regions the library has metadata for. + */ + public Set<String> getSupportedRegions() { + return supportedRegions; + } + + /** + * 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) { + return getInstance(META_DATA_FILE_PREFIX, + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap()); + } + return instance; + } + + /** + * 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 region code is not unknown or null and log an error message. The + * {@code countryCallingCode} and {@code number} supplied is used only for the resultant log + * message. + */ + private boolean hasValidRegionCode(String regionCode, + int countryCallingCode, String number) { + if (!isValidRegionCode(regionCode)) { + LOGGER.log(Level.WARNING, + "Number " + number + " has invalid or missing country calling code (" + + countryCallingCode + ")"); + return false; + } + return true; + } + + /** + * 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()) { + 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.PhoneNumber, PhoneNumberUtil.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 since no formatting of the national number needs to be applied. + // Extensions are not formatted. + formattedNumber.append(nationalSignificantNumber); + formatNumberByFormat(countryCallingCode, PhoneNumberFormat.E164, formattedNumber); + return; + } + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + if (!isValidRegionCode(regionCode)) { + formattedNumber.append(nationalSignificantNumber); + return; + } + + formattedNumber.append(formatNationalNumber(nationalSignificantNumber, + regionCode, numberFormat)); + maybeGetFormattedExtension(number, regionCode, numberFormat, formattedNumber); + formatNumberByFormat(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); + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + return nationalSignificantNumber; + } + List<NumberFormat> userDefinedFormatsCopy = + new ArrayList<NumberFormat>(userDefinedFormats.size()); + for (NumberFormat numFormat : userDefinedFormats) { + String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule(); + if (nationalPrefixFormattingRule.length() > 0) { + // 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. + NumberFormat numFormatCopy = new NumberFormat(); + numFormatCopy.mergeFrom(numFormat); + String nationalPrefix = getMetadataForRegion(regionCode).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(); + } + userDefinedFormatsCopy.add(numFormatCopy); + } else { + // Otherwise, we just add the original rule to the modified list of formats. + userDefinedFormatsCopy.add(numFormat); + } + } + + StringBuilder formattedNumber = + new StringBuilder(formatAccordingToFormats(nationalSignificantNumber, + userDefinedFormatsCopy, + numberFormat)); + maybeGetFormattedExtension(number, regionCode, numberFormat, formattedNumber); + formatNumberByFormat(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); + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + return nationalSignificantNumber; + } + + StringBuilder formattedNumber = new StringBuilder(20); + formattedNumber.append(formatNationalNumber(nationalSignificantNumber, + regionCode, + PhoneNumberFormat.NATIONAL, + carrierCode)); + maybeGetFormattedExtension(number, regionCode, PhoneNumberFormat.NATIONAL, formattedNumber); + formatNumberByFormat(countryCallingCode, PhoneNumberFormat.NATIONAL, formattedNumber); + return formattedNumber.toString(); + } + + /** + * 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) { + String regionCode = getRegionCodeForNumber(number); + if (!isValidRegionCode(regionCode)) { + 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(); + PhoneNumberType numberType = getNumberType(numberNoExt); + if ((regionCode.equals("CO")) && (regionCallingFrom.equals("CO")) && + (numberType == PhoneNumberType.FIXED_LINE)) { + formattedNumber = + formatNationalNumberWithCarrierCode(numberNoExt, COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX); + } else if ((regionCode.equals("BR")) && (regionCallingFrom.equals("BR")) && + ((numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) || + (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE))) { + formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() + ? 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 (canBeInternationallyDialled(numberNoExt)) { + return withFormatting ? format(numberNoExt, PhoneNumberFormat.INTERNATIONAL) + : format(numberNoExt, PhoneNumberFormat.E164); + } else { + formattedNumber = (regionCallingFrom.equals(regionCode)) + ? format(numberNoExt, PhoneNumberFormat.NATIONAL) : ""; + } + return withFormatting ? formattedNumber : normalizeDigitsOnly(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)) { + return format(number, PhoneNumberFormat.INTERNATIONAL); + } + int countryCallingCode = number.getCountryCode(); + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidRegionCode(regionCode, countryCallingCode, nationalSignificantNumber)) { + 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 == getCountryCodeForRegion(regionCallingFrom)) { + // For regions that 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); + } + String formattedNationalNumber = + formatNationalNumber(nationalSignificantNumber, + regionCode, PhoneNumberFormat.INTERNATIONAL); + PhoneMetadata metadata = getMetadataForRegion(regionCallingFrom); + String internationalPrefix = metadata.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 (metadata.hasPreferredInternationalPrefix()) { + internationalPrefixForFormatting = metadata.getPreferredInternationalPrefix(); + } + + StringBuilder formattedNumber = new StringBuilder(formattedNationalNumber); + maybeGetFormattedExtension(number, regionCode, PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + formatNumberByFormat(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 is an invalid number, the method returns the raw input when + * it is available. + * + * @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() && !isValidNumber(number)) { + return number.getRawInput(); + } + if (!number.hasCountryCodeSource()) { + return format(number, PhoneNumberFormat.NATIONAL); + } + switch (number.getCountryCodeSource()) { + case FROM_NUMBER_WITH_PLUS_SIGN: + return format(number, PhoneNumberFormat.INTERNATIONAL); + case FROM_NUMBER_WITH_IDD: + return formatOutOfCountryCallingNumber(number, regionCallingFrom); + case FROM_NUMBER_WITHOUT_PLUS_SIGN: + return format(number, PhoneNumberFormat.INTERNATIONAL).substring(1); + case FROM_DEFAULT_COUNTRY: + default: + return format(number, PhoneNumberFormat.NATIONAL); + } + } + + /** + * 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(); + String regionCode = getRegionCodeForCountryCode(countryCode); + if (!hasValidRegionCode(regionCode, countryCode, rawInput)) { + 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 metadata = getMetadataForRegion(regionCallingFrom); + if (countryCode == NANPA_COUNTRY_CODE) { + if (isNANPACountry(regionCallingFrom)) { + return countryCode + " " + rawInput; + } + } else if (countryCode == getCountryCodeForRegion(regionCallingFrom)) { + // Here we copy the formatting rules so we can modify the pattern we expect to match against. + List<NumberFormat> availableFormats = + new ArrayList<NumberFormat>(metadata.numberFormatSize()); + for (NumberFormat format : metadata.numberFormats()) { + NumberFormat newFormat = new NumberFormat(); + newFormat.mergeFrom(format); + // The first group is the first group of digits that the user determined. + newFormat.setPattern("(\\d+)(.*)"); + // Here we just concatenate them back together after the national prefix has been fixed. + newFormat.setFormat("$1$2"); + availableFormats.add(newFormat); + } + // Now we format using these patterns instead of the default pattern, but with the national + // prefix prefixed if necessary, by choosing the format rule based on the leading digits + // present in the unformatted national number. + // 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 formatAccordingToFormats(rawInput, availableFormats, PhoneNumberFormat.NATIONAL); + } + String internationalPrefix = metadata.getInternationalPrefix(); + // For countries that have multiple international prefixes, the international format of the + // number is returned, unless there is a preferred international prefix. + String internationalPrefixForFormatting = + UNIQUE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches() + ? internationalPrefix + : metadata.getPreferredInternationalPrefix(); + StringBuilder formattedNumber = new StringBuilder(rawInput); + maybeGetFormattedExtension(number, regionCode, PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + formatNumberByFormat(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 a leading zero has been set, we prefix this now. Note this is not a national prefix. + StringBuilder nationalNumber = new StringBuilder(number.isItalianLeadingZero() ? "0" : ""); + nationalNumber.append(number.getNationalNumber()); + return nationalNumber.toString(); + } + + /** + * A helper function that is used by format and formatByPattern. + */ + private void formatNumberByFormat(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); + return; + case NATIONAL: + default: + return; + } + } + + // Simple wrapper of formatNationalNumber for the common case of no carrier code. + private String formatNationalNumber(String number, + String regionCode, + PhoneNumberFormat numberFormat) { + return formatNationalNumber(number, regionCode, 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 formatNationalNumber(String number, + String regionCode, + PhoneNumberFormat numberFormat, + String carrierCode) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + 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(); + String formattedNationalNumber = + formatAccordingToFormats(number, availableFormats, numberFormat, carrierCode); + if (numberFormat == PhoneNumberFormat.RFC3966) { + formattedNationalNumber = + SEPARATOR_PATTERN.matcher(formattedNationalNumber).replaceAll("-"); + } + return formattedNationalNumber; + } + + private 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 formatAccordingToFormats for the common case of no carrier code. + private String formatAccordingToFormats(String nationalNumber, + List<NumberFormat> availableFormats, + PhoneNumberFormat numberFormat) { + return formatAccordingToFormats(nationalNumber, availableFormats, numberFormat, null); + } + + // Note that carrierCode is optional - if NULL or an empty string, no carrier code replacement + // will take place. + private String formatAccordingToFormats(String nationalNumber, + List<NumberFormat> availableFormats, + PhoneNumberFormat numberFormat, + String carrierCode) { + NumberFormat numFormat = chooseFormattingPatternForNumber(availableFormats, nationalNumber); + if (numFormat == null) { + // If no pattern above is matched, we format the number as a whole. + return nationalNumber; + } + String numberFormatRule = numFormat.getFormat(); + Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber); + if (numberFormat == PhoneNumberFormat.NATIONAL && + carrierCode != null && carrierCode.length() > 0 && + numFormat.getDomesticCarrierCodeFormattingRule().length() > 0) { + // Replace the $CC in the formatting rule with the desired carrier code. + String carrierCodeFormattingRule = numFormat.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); + return m.replaceAll(numberFormatRule); + } else { + // Use the national prefix formatting rule instead. + String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule(); + if (numberFormat == PhoneNumberFormat.NATIONAL && + nationalPrefixFormattingRule != null && + nationalPrefixFormattingRule.length() > 0) { + Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule); + return m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule)); + } else { + return m.replaceAll(numberFormatRule); + } + } + } + + /** + * 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. + */ + 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 was entered. + */ + public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) { + // Check the region code is valid. + if (!isValidRegionCode(regionCode)) { + LOGGER.log(Level.SEVERE, "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; + } + + /** + * Appends the formatted extension of a phone number to formattedNumber, if the phone number had + * an extension specified. + */ + private void maybeGetFormattedExtension(PhoneNumber number, String regionCode, + PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + if (number.hasExtension() && number.getExtension().length() > 0) { + if (numberFormat == PhoneNumberFormat.RFC3966) { + formattedNumber.append(RFC3966_EXTN_PREFIX).append(number.getExtension()); + } else { + formatExtension(number.getExtension(), regionCode, formattedNumber); + } + } + } + + /** + * Formats the extension part of the phone number by prefixing it with the appropriate extension + * prefix. This will be the default extension prefix, unless overridden by a preferred + * extension prefix for this region. + */ + private void formatExtension(String extensionDigits, String regionCode, + StringBuilder extension) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata.hasPreferredExtnPrefix()) { + extension.append(metadata.getPreferredExtnPrefix()).append(extensionDigits); + } else { + extension.append(DEFAULT_EXTN_PREFIX).append(extensionDigits); + } + } + + 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(); + 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); + if (!isValidRegionCode(regionCode)) { + return PhoneNumberType.UNKNOWN; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return getNumberTypeHelper(nationalSignificantNumber, getMetadataForRegion(regionCode)); + } + + private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) { + PhoneNumberDesc generalNumberDesc = metadata.getGeneralDesc(); + if (!generalNumberDesc.hasNationalNumberPattern() || + !isNumberMatchingDesc(nationalNumber, generalNumberDesc)) { + 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; + } + + 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; + } + + PhoneMetadata getMetadataForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + return null; + } + synchronized (regionToMetadataMap) { + if (!regionToMetadataMap.containsKey(regionCode)) { + loadMetadataForRegionFromFile(currentFilePrefix, regionCode); + } + } + return regionToMetadataMap.get(regionCode); + } + + private boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) { + Matcher possibleNumberPatternMatcher = + regexCache.getPatternForRegex(numberDesc.getPossibleNumberPattern()) + .matcher(nationalNumber); + Matcher nationalNumberPatternMatcher = + regexCache.getPatternForRegex(numberDesc.getNationalNumberPattern()) + .matcher(nationalNumber); + return possibleNumberPatternMatcher.matches() && 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 (isValidRegionCode(regionCode) && 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. + * + * @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) { + if (number.getCountryCode() != getCountryCodeForRegion(regionCode)) { + return false; + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + PhoneNumberDesc generalNumDesc = metadata.getGeneralDesc(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + + // For regions where we don't have metadata for PhoneNumberDesc, we treat any number passed in + // as a valid number if its national significant number is between the minimum and maximum + // lengths defined by ITU for a national significant number. + if (!generalNumDesc.hasNationalNumberPattern()) { + int numberLength = nationalSignificantNumber.length(); + return numberLength > MIN_LENGTH_FOR_NSN && numberLength <= MAX_LENGTH_FOR_NSN; + } + 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) { + 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. + 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. + */ + public String getRegionCodeForCountryCode(int countryCallingCode) { + List<String> regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return regionCodes == null ? UNKNOWN_REGION : regionCodes.get(0); + } + + /** + * 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)) { + return 0; + } + PhoneMetadata metadata = getMetadataForRegion(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) { + if (!isValidRegionCode(regionCode)) { + LOGGER.log(Level.SEVERE, "Invalid or missing region code provided."); + return null; + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + 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 = getMetadataForRegion( + 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; + } + } + + /** + * 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. + String regionCode = getRegionCodeForCountryCode(countryCode); + if (!isValidRegionCode(regionCode)) { + return ValidationResult.INVALID_COUNTRY_CODE; + } + PhoneNumberDesc generalNumDesc = getMetadataForRegion(regionCode).getGeneralDesc(); + // Handling case of numbers with no metadata. + if (!generalNumDesc.hasNationalNumberPattern()) { + LOGGER.log(Level.FINER, "Checking if number is possible with incomplete metadata."); + int numberLength = nationalNumber.length(); + if (numberLength < MIN_LENGTH_FOR_NSN) { + return ValidationResult.TOO_SHORT; + } else if (numberLength > MAX_LENGTH_FOR_NSN) { + return ValidationResult.TOO_LONG; + } else { + return ValidationResult.IS_POSSIBLE; + } + } + Pattern possibleNumberPattern = + regexCache.getPatternForRegex(generalNumDesc.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.PhoneNumber)} for details. + * + * <p>This method first parses the number, then invokes + * {@link #isPossibleNumber(Phonenumber.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. + * @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); + } + }; + } + + /** + * 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."); + } + // Extract a possible number from the string passed in (this strips leading characters that + // could not be the start of a phone number.) + String number = extractPossibleNumber(numberToParse); + if (!isViablePhoneNumber(number)) { + 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(number, defaultRegion)) { + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Missing or invalid default region."); + } + + if (keepRawInput) { + phoneNumber.setRawInput(numberToParse); + } + StringBuilder nationalNumber = new StringBuilder(number); + // 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)) { + regionMetadata = getMetadataForRegion(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(); + maybeStripNationalPrefixAndCarrierCode(normalizedNationalNumber, regionMetadata, carrierCode); + 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."); + } + if (normalizedNationalNumber.charAt(0) == '0') { + phoneNumber.setItalianLeadingZero(true); + } + phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString())); + } + + /** + * 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, 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, 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, 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, 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 only be dialled from within the region. If unknown, or the + * number can be dialled from outside the region as well, returns false. Does not check the + * number is a valid number. + * TODO: Make this method public when we have enough metadata to make it worthwhile. Currently + * visible for testing purposes only. + * + * @param number the phone-number for which we want to know whether it is only diallable from + * within the region + */ + boolean canBeInternationallyDialled(PhoneNumber number) { + String regionCode = getRegionCodeForNumber(number); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidRegionCode(regionCode, number.getCountryCode(), nationalSignificantNumber)) { + return true; + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + return !isNumberMatchingDesc(nationalSignificantNumber, metadata.getNoInternationalDialling()); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.java new file mode 100644 index 0000000..cb3f8b5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonemetadata.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. + */ + +/** + * 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(); + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + // required 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; + } + + 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(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_); + } + + 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); + 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()); + } + } + + 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/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java new file mode 100644 index 0000000..4ed1563 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/Phonenumber.java @@ -0,0 +1,260 @@ +/* + * 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 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(); + 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.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_ && + 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) + 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: true"); + } + 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/java/libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/RegexCache.java new file mode 100644 index 0000000..a9ff7e0 --- /dev/null +++ b/java/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/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java new file mode 100644 index 0000000..2a23d7c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberUtil.java @@ -0,0 +1,94 @@ +/* + * 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.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; + +import java.util.regex.Pattern; + +/* + * 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. + * + * @author Shaopeng Jia + */ +public class ShortNumberUtil { + + private final PhoneNumberUtil phoneUtil; + + public ShortNumberUtil() { + phoneUtil = PhoneNumberUtil.getInstance(); + } + + // @VisibleForTesting + ShortNumberUtil(PhoneNumberUtil util) { + phoneUtil = util; + } + + /** + * 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 matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */); + } + + /** + * 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 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 = phoneUtil.getMetadataForRegion(regionCode); + if (metadata == null || !metadata.hasEmergency()) { + return false; + } + Pattern emergencyNumberPattern = + Pattern.compile(metadata.getEmergency().getNationalNumberPattern()); + String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number); + // In Brazil, it is impossible to append additional digits to an emergency number to dial the + // number. + return (!allowPrefixMatch || regionCode.equals("BR")) + ? emergencyNumberPattern.matcher(normalizedNumber).matches() + : emergencyNumberPattern.matcher(normalizedNumber).lookingAt(); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC Binary files differnew file mode 100644 index 0000000..63a0784 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD Binary files differnew file mode 100644 index 0000000..5651404 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE Binary files differnew file mode 100644 index 0000000..5ce6bd9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF Binary files differnew file mode 100644 index 0000000..ce0b677 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG Binary files differnew file mode 100644 index 0000000..0fb852a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI Binary files differnew file mode 100644 index 0000000..5ec108b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL Binary files differnew file mode 100644 index 0000000..e7f2d42 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM Binary files differnew file mode 100644 index 0000000..5af20f5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN Binary files differnew file mode 100644 index 0000000..27c2ae3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO Binary files differnew file mode 100644 index 0000000..77b08cb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR Binary files differnew file mode 100644 index 0000000..a39c601 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS Binary files differnew file mode 100644 index 0000000..3b38675 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT Binary files differnew file mode 100644 index 0000000..c38a56c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU Binary files differnew file mode 100644 index 0000000..2fa06cf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW Binary files differnew file mode 100644 index 0000000..fb3aad4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX Binary files differnew file mode 100644 index 0000000..c0dbabf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ Binary files differnew file mode 100644 index 0000000..e4b14a6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA Binary files differnew file mode 100644 index 0000000..ad4662f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB Binary files differnew file mode 100644 index 0000000..982cff9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD Binary files differnew file mode 100644 index 0000000..b6c204a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE Binary files differnew file mode 100644 index 0000000..b37f61f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF Binary files differnew file mode 100644 index 0000000..48d20e7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG Binary files differnew file mode 100644 index 0000000..2b3c0ae --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH Binary files differnew file mode 100644 index 0000000..841ea9a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI Binary files differnew file mode 100644 index 0000000..293ebbc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ Binary files differnew file mode 100644 index 0000000..e3c5863 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL Binary files differnew file mode 100644 index 0000000..4987820 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM Binary files differnew file mode 100644 index 0000000..d014b2a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN Binary files differnew file mode 100644 index 0000000..c257c58 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO Binary files differnew file mode 100644 index 0000000..f5919ff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR Binary files differnew file mode 100644 index 0000000..ec29af2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS Binary files differnew file mode 100644 index 0000000..f52796e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT Binary files differnew file mode 100644 index 0000000..e549cd7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW Binary files differnew file mode 100644 index 0000000..21fd265 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY Binary files differnew file mode 100644 index 0000000..a679105 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ Binary files differnew file mode 100644 index 0000000..5a4d052 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA Binary files differnew file mode 100644 index 0000000..5bf386d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC Binary files differnew file mode 100644 index 0000000..2f2f8aa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD Binary files differnew file mode 100644 index 0000000..cf7bba2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF Binary files differnew file mode 100644 index 0000000..e3ce491 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG Binary files differnew file mode 100644 index 0000000..2b4128d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH Binary files differnew file mode 100644 index 0000000..409254a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI Binary files differnew file mode 100644 index 0000000..98198b8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK Binary files differnew file mode 100644 index 0000000..2f6fe63 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL Binary files differnew file mode 100644 index 0000000..0e90d89 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM Binary files differnew file mode 100644 index 0000000..4018df4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN Binary files differnew file mode 100644 index 0000000..67a7f5e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO Binary files differnew file mode 100644 index 0000000..b1dbb84 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR Binary files differnew file mode 100644 index 0000000..cbc064b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU Binary files differnew file mode 100644 index 0000000..97e9838 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV Binary files differnew file mode 100644 index 0000000..4517244 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX Binary files differnew file mode 100644 index 0000000..cb8dfd9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY Binary files differnew file mode 100644 index 0000000..de1e004 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ Binary files differnew file mode 100644 index 0000000..5c41a79 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE Binary files differnew file mode 100644 index 0000000..cfc5b19 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ Binary files differnew file mode 100644 index 0000000..5511381 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK Binary files differnew file mode 100644 index 0000000..0082966 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM Binary files differnew file mode 100644 index 0000000..723ea80 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO Binary files differnew file mode 100644 index 0000000..0305f76 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ Binary files differnew file mode 100644 index 0000000..4107335 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC Binary files differnew file mode 100644 index 0000000..343743d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE Binary files differnew file mode 100644 index 0000000..28bd9fb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG Binary files differnew file mode 100644 index 0000000..38e39b3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER Binary files differnew file mode 100644 index 0000000..ae89200 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES Binary files differnew file mode 100644 index 0000000..9b855f1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET Binary files differnew file mode 100644 index 0000000..8843e54 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI Binary files differnew file mode 100644 index 0000000..604d7ff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ Binary files differnew file mode 100644 index 0000000..cdd713c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK Binary files differnew file mode 100644 index 0000000..6c19901 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM Binary files differnew file mode 100644 index 0000000..b4031f0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO Binary files differnew file mode 100644 index 0000000..46dac92 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR Binary files differnew file mode 100644 index 0000000..66d244e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA Binary files differnew file mode 100644 index 0000000..dddd714 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB Binary files differnew file mode 100644 index 0000000..bd6e72a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD Binary files differnew file mode 100644 index 0000000..e120fa5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE Binary files differnew file mode 100644 index 0000000..ac5bb57 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF Binary files differnew file mode 100644 index 0000000..da17df2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG Binary files differnew file mode 100644 index 0000000..0e6809f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH Binary files differnew file mode 100644 index 0000000..dea89c7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI Binary files differnew file mode 100644 index 0000000..7dcc9ff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL Binary files differnew file mode 100644 index 0000000..d327b75 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM Binary files differnew file mode 100644 index 0000000..3bf3e41 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN Binary files differnew file mode 100644 index 0000000..b0b7406 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP Binary files differnew file mode 100644 index 0000000..e03584b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ Binary files differnew file mode 100644 index 0000000..424b068 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR Binary files differnew file mode 100644 index 0000000..655b5b4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT Binary files differnew file mode 100644 index 0000000..a2a20cf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU Binary files differnew file mode 100644 index 0000000..9a006f1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW Binary files differnew file mode 100644 index 0000000..77b6398 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY Binary files differnew file mode 100644 index 0000000..eb36761 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK Binary files differnew file mode 100644 index 0000000..dfd2d09 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN Binary files differnew file mode 100644 index 0000000..6dd47c0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR Binary files differnew file mode 100644 index 0000000..27a0c8a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT Binary files differnew file mode 100644 index 0000000..245ee93 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU Binary files differnew file mode 100644 index 0000000..6ef1306 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID Binary files differnew file mode 100644 index 0000000..3d0f8cc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE Binary files differnew file mode 100644 index 0000000..12bc792 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL Binary files differnew file mode 100644 index 0000000..a0f1071 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM Binary files differnew file mode 100644 index 0000000..8d8c881 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN Binary files differnew file mode 100644 index 0000000..05b4b50 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO Binary files differnew file mode 100644 index 0000000..a9aa569 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ Binary files differnew file mode 100644 index 0000000..4009946 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR Binary files differnew file mode 100644 index 0000000..9edbc87 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS Binary files differnew file mode 100644 index 0000000..d281347 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT Binary files differnew file mode 100644 index 0000000..d5c2c71 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE Binary files differnew file mode 100644 index 0000000..1908b64 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM Binary files differnew file mode 100644 index 0000000..81be1e1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO Binary files differnew file mode 100644 index 0000000..47058ad --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP Binary files differnew file mode 100644 index 0000000..9db7e6e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE Binary files differnew file mode 100644 index 0000000..68de57a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG Binary files differnew file mode 100644 index 0000000..617ce07 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH Binary files differnew file mode 100644 index 0000000..9f757d4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI Binary files differnew file mode 100644 index 0000000..82bdb90 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM Binary files differnew file mode 100644 index 0000000..21570ae --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN Binary files differnew file mode 100644 index 0000000..5a5f4e8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP Binary files differnew file mode 100644 index 0000000..42a4b26 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR Binary files differnew file mode 100644 index 0000000..47f4390 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW Binary files differnew file mode 100644 index 0000000..77f805a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY Binary files differnew file mode 100644 index 0000000..cfd2678 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ Binary files differnew file mode 100644 index 0000000..b129ff6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA Binary files differnew file mode 100644 index 0000000..62db7dc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB Binary files differnew file mode 100644 index 0000000..65b3c94 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC Binary files differnew file mode 100644 index 0000000..c8a6ad5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI Binary files differnew file mode 100644 index 0000000..c29d890 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK Binary files differnew file mode 100644 index 0000000..a9a9d2e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR Binary files differnew file mode 100644 index 0000000..f1ce4be --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS Binary files differnew file mode 100644 index 0000000..e04c603 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT Binary files differnew file mode 100644 index 0000000..0c11315 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU Binary files differnew file mode 100644 index 0000000..4ffc791 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV Binary files differnew file mode 100644 index 0000000..a76eab9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY Binary files differnew file mode 100644 index 0000000..8fc1ee7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA Binary files differnew file mode 100644 index 0000000..ef1522a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC Binary files differnew file mode 100644 index 0000000..79fac1a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD Binary files differnew file mode 100644 index 0000000..b17e4af --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME Binary files differnew file mode 100644 index 0000000..24937fd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF Binary files differnew file mode 100644 index 0000000..3813149 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG Binary files differnew file mode 100644 index 0000000..072379f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH Binary files differnew file mode 100644 index 0000000..fc64213 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK Binary files differnew file mode 100644 index 0000000..3bbd43e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML Binary files differnew file mode 100644 index 0000000..5cce562 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM Binary files differnew file mode 100644 index 0000000..4f3ea91 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN Binary files differnew file mode 100644 index 0000000..0a7e31a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO Binary files differnew file mode 100644 index 0000000..4cf9625 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP Binary files differnew file mode 100644 index 0000000..0f9476d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ Binary files differnew file mode 100644 index 0000000..c48db34 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR Binary files differnew file mode 100644 index 0000000..36db9e4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS Binary files differnew file mode 100644 index 0000000..969cafc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT Binary files differnew file mode 100644 index 0000000..c2aaa53 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU Binary files differnew file mode 100644 index 0000000..d69bd68 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV Binary files differnew file mode 100644 index 0000000..8841a29 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW Binary files differnew file mode 100644 index 0000000..7bf7d43 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX Binary files differnew file mode 100644 index 0000000..fa3cb40 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY Binary files differnew file mode 100644 index 0000000..07b6b85 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ Binary files differnew file mode 100644 index 0000000..3d0967a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA Binary files differnew file mode 100644 index 0000000..86d10bc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC Binary files differnew file mode 100644 index 0000000..6e5d3f7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE Binary files differnew file mode 100644 index 0000000..b9cd0ac --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF Binary files differnew file mode 100644 index 0000000..622d39f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG Binary files differnew file mode 100644 index 0000000..0f478ca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI Binary files differnew file mode 100644 index 0000000..64d3eb0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL Binary files differnew file mode 100644 index 0000000..aaefdd9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO Binary files differnew file mode 100644 index 0000000..6838854 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP Binary files differnew file mode 100644 index 0000000..2868f9c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR Binary files differnew file mode 100644 index 0000000..c8ec23e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU Binary files differnew file mode 100644 index 0000000..50dbafd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ Binary files differnew file mode 100644 index 0000000..6c3535b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM Binary files differnew file mode 100644 index 0000000..84cded4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA Binary files differnew file mode 100644 index 0000000..2c032e6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE Binary files differnew file mode 100644 index 0000000..6b89b38 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF Binary files differnew file mode 100644 index 0000000..60c6d30 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG Binary files differnew file mode 100644 index 0000000..9fbb7bc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH Binary files differnew file mode 100644 index 0000000..56a53cb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK Binary files differnew file mode 100644 index 0000000..e1114b6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL Binary files differnew file mode 100644 index 0000000..69d172c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM Binary files differnew file mode 100644 index 0000000..f8da61b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR Binary files differnew file mode 100644 index 0000000..3b8c4a2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS Binary files differnew file mode 100644 index 0000000..da7d297 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT Binary files differnew file mode 100644 index 0000000..6baccc7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW Binary files differnew file mode 100644 index 0000000..45398fa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY Binary files differnew file mode 100644 index 0000000..6bc931e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA Binary files differnew file mode 100644 index 0000000..8ec44a0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE Binary files differnew file mode 100644 index 0000000..e2af509 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO Binary files differnew file mode 100644 index 0000000..a55d60f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS Binary files differnew file mode 100644 index 0000000..5a803f9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU Binary files differnew file mode 100644 index 0000000..28bb82d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW Binary files differnew file mode 100644 index 0000000..cb6329e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA Binary files differnew file mode 100644 index 0000000..aefd945 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB Binary files differnew file mode 100644 index 0000000..e35361f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC Binary files differnew file mode 100644 index 0000000..f012a55 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD Binary files differnew file mode 100644 index 0000000..060bd91 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE Binary files differnew file mode 100644 index 0000000..e5850c7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG Binary files differnew file mode 100644 index 0000000..e8dfd31 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH Binary files differnew file mode 100644 index 0000000..dcf690a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI Binary files differnew file mode 100644 index 0000000..ca7c517 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ Binary files differnew file mode 100644 index 0000000..17122cc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK Binary files differnew file mode 100644 index 0000000..48323b5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL Binary files differnew file mode 100644 index 0000000..e942566 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM Binary files differnew file mode 100644 index 0000000..9432784 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN Binary files differnew file mode 100644 index 0000000..549ff61 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO Binary files differnew file mode 100644 index 0000000..0b4edc7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR Binary files differnew file mode 100644 index 0000000..a7260aa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST Binary files differnew file mode 100644 index 0000000..265f3af --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV Binary files differnew file mode 100644 index 0000000..436b979 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX Binary files differnew file mode 100644 index 0000000..50b2362 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY Binary files differnew file mode 100644 index 0000000..4a6a7b8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ Binary files differnew file mode 100644 index 0000000..c1ed388 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC Binary files differnew file mode 100644 index 0000000..dc62e4c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD Binary files differnew file mode 100644 index 0000000..b92127f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG Binary files differnew file mode 100644 index 0000000..176b9bf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH Binary files differnew file mode 100644 index 0000000..8b56a1f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ Binary files differnew file mode 100644 index 0000000..efce54e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK Binary files differnew file mode 100644 index 0000000..849f1c7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL Binary files differnew file mode 100644 index 0000000..46a855f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM Binary files differnew file mode 100644 index 0000000..cf1c21d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN Binary files differnew file mode 100644 index 0000000..50a7217 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO Binary files differnew file mode 100644 index 0000000..e2cd8de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR Binary files differnew file mode 100644 index 0000000..060cc34 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT Binary files differnew file mode 100644 index 0000000..945011b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV Binary files differnew file mode 100644 index 0000000..3b53210 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW Binary files differnew file mode 100644 index 0000000..acda89f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ Binary files differnew file mode 100644 index 0000000..5450858 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA Binary files differnew file mode 100644 index 0000000..5019f02 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG Binary files differnew file mode 100644 index 0000000..d154f24 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US Binary files differnew file mode 100644 index 0000000..1046ec6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY Binary files differnew file mode 100644 index 0000000..f9e4805 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ Binary files differnew file mode 100644 index 0000000..f894a1f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA Binary files differnew file mode 100644 index 0000000..42367de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC Binary files differnew file mode 100644 index 0000000..294335d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE Binary files differnew file mode 100644 index 0000000..645c9a5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG Binary files differnew file mode 100644 index 0000000..bda87e4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI Binary files differnew file mode 100644 index 0000000..987acec --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN Binary files differnew file mode 100644 index 0000000..ad1e62b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU Binary files differnew file mode 100644 index 0000000..26ecb82 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF Binary files differnew file mode 100644 index 0000000..2337ed6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS Binary files differnew file mode 100644 index 0000000..03fa87f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE Binary files differnew file mode 100644 index 0000000..be646a1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT Binary files differnew file mode 100644 index 0000000..e5eb105 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA Binary files differnew file mode 100644 index 0000000..c742d5c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM Binary files differnew file mode 100644 index 0000000..dd3dea3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW Binary files differnew file mode 100644 index 0000000..2766b3c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMap.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMap.java new file mode 100644 index 0000000..10f9535 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMap.java @@ -0,0 +1,203 @@ +/* + * 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.geocoding; + +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.logging.Logger; + +/** + * A utility that maps phone number prefixes to a string describing the geographical area the prefix + * covers. + * + * @author Shaopeng Jia + */ +public class AreaCodeMap implements Externalizable { + private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + private static final Logger LOGGER = Logger.getLogger(AreaCodeMap.class.getName()); + + private AreaCodeMapStorageStrategy areaCodeMapStorage; + + // @VisibleForTesting + AreaCodeMapStorageStrategy getAreaCodeMapStorage() { + return areaCodeMapStorage; + } + + /** + * Creates an empty {@link AreaCodeMap}. The default constructor is necessary for implementing + * {@link Externalizable}. The empty map could later be populated by + * {@link #readAreaCodeMap(java.util.SortedMap)} or {@link #readExternal(java.io.ObjectInput)}. + */ + public AreaCodeMap() {} + + /** + * Gets the size of the provided area code map storage. The map storage passed-in will be filled + * as a result. + */ + private static int getSizeOfAreaCodeMapStorage(AreaCodeMapStorageStrategy mapStorage, + SortedMap<Integer, String> areaCodeMap) throws IOException { + mapStorage.readFromSortedMap(areaCodeMap); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + mapStorage.writeExternal(objectOutputStream); + objectOutputStream.flush(); + int sizeOfStorage = byteArrayOutputStream.size(); + objectOutputStream.close(); + return sizeOfStorage; + } + + private AreaCodeMapStorageStrategy createDefaultMapStorage() { + return new DefaultMapStorage(); + } + + private AreaCodeMapStorageStrategy createFlyweightMapStorage() { + return new FlyweightMapStorage(); + } + + /** + * Gets the smaller area code map storage strategy according to the provided area code map. It + * actually uses (outputs the data to a stream) both strategies and retains the best one which + * make this method quite expensive. + */ + // @VisibleForTesting + AreaCodeMapStorageStrategy getSmallerMapStorage(SortedMap<Integer, String> areaCodeMap) { + try { + AreaCodeMapStorageStrategy flyweightMapStorage = createFlyweightMapStorage(); + int sizeOfFlyweightMapStorage = getSizeOfAreaCodeMapStorage(flyweightMapStorage, areaCodeMap); + + AreaCodeMapStorageStrategy defaultMapStorage = createDefaultMapStorage(); + int sizeOfDefaultMapStorage = getSizeOfAreaCodeMapStorage(defaultMapStorage, areaCodeMap); + + return sizeOfFlyweightMapStorage < sizeOfDefaultMapStorage + ? flyweightMapStorage : defaultMapStorage; + } catch (IOException e) { + LOGGER.severe(e.getMessage()); + return createFlyweightMapStorage(); + } + } + + /** + * Creates an {@link AreaCodeMap} initialized with {@code sortedAreaCodeMap}. Note that the + * underlying implementation of this method is expensive thus should not be called by + * time-critical applications. + * + * @param sortedAreaCodeMap a map from phone number prefixes to descriptions of corresponding + * geographical areas, sorted in ascending order of the phone number prefixes as integers. + */ + public void readAreaCodeMap(SortedMap<Integer, String> sortedAreaCodeMap) { + areaCodeMapStorage = getSmallerMapStorage(sortedAreaCodeMap); + } + + /** + * Supports Java Serialization. + */ + public void readExternal(ObjectInput objectInput) throws IOException { + // Read the area code map storage strategy flag. + boolean useFlyweightMapStorage = objectInput.readBoolean(); + if (useFlyweightMapStorage) { + areaCodeMapStorage = new FlyweightMapStorage(); + } else { + areaCodeMapStorage = new DefaultMapStorage(); + } + areaCodeMapStorage.readExternal(objectInput); + } + + /** + * Supports Java Serialization. + */ + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeBoolean(areaCodeMapStorage instanceof FlyweightMapStorage); + areaCodeMapStorage.writeExternal(objectOutput); + } + + /** + * Returns the description of the geographical area the {@code number} corresponds to. This method + * distinguishes the case of an invalid prefix and a prefix for which the name is not available in + * the current language. If the description is not available in the current language an empty + * string is returned. If no description was found for the provided number, null is returned. + * + * @param number the phone number to look up + * @return the description of the geographical area + */ + String lookup(PhoneNumber number) { + int numOfEntries = areaCodeMapStorage.getNumOfEntries(); + if (numOfEntries == 0) { + return null; + } + long phonePrefix = + Long.parseLong(number.getCountryCode() + phoneUtil.getNationalSignificantNumber(number)); + int currentIndex = numOfEntries - 1; + SortedSet<Integer> currentSetOfLengths = areaCodeMapStorage.getPossibleLengths(); + while (currentSetOfLengths.size() > 0) { + Integer possibleLength = currentSetOfLengths.last(); + String phonePrefixStr = String.valueOf(phonePrefix); + if (phonePrefixStr.length() > possibleLength) { + phonePrefix = Long.parseLong(phonePrefixStr.substring(0, possibleLength)); + } + currentIndex = binarySearch(0, currentIndex, phonePrefix); + if (currentIndex < 0) { + return null; + } + int currentPrefix = areaCodeMapStorage.getPrefix(currentIndex); + if (phonePrefix == currentPrefix) { + return areaCodeMapStorage.getDescription(currentIndex); + } + currentSetOfLengths = currentSetOfLengths.headSet(possibleLength); + } + return null; + } + + /** + * Does a binary search for {@code value} in the provided array from {@code start} to {@code end} + * (inclusive). Returns the position if {@code value} is found; otherwise, returns the + * position which has the largest value that is less than {@code value}. This means if + * {@code value} is the smallest, -1 will be returned. + */ + private int binarySearch(int start, int end, long value) { + int current = 0; + while (start <= end) { + current = (start + end) >>> 1; + int currentValue = areaCodeMapStorage.getPrefix(current); + if (currentValue == value) { + return current; + } else if (currentValue > value) { + current--; + end = current; + } else { + start = current + 1; + } + } + return current; + } + + /** + * Dumps the mappings contained in the area code map. + */ + @Override + public String toString() { + return areaCodeMapStorage.toString(); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMapStorageStrategy.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMapStorageStrategy.java new file mode 100644 index 0000000..0ef9b91 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/AreaCodeMapStorageStrategy.java @@ -0,0 +1,108 @@ +/* + * 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.geocoding; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.SortedMap; +import java.util.TreeSet; + +/** + * Abstracts the way area code data is stored into memory and serialized to a stream. It is used by + * {@link AreaCodeMap} to support the most space-efficient storage strategy according to the + * provided data. + * + * @author Philippe Liard + */ +abstract class AreaCodeMapStorageStrategy { + protected int numOfEntries = 0; + protected final TreeSet<Integer> possibleLengths = new TreeSet<Integer>(); + + /** + * Gets the phone number prefix located at the provided {@code index}. + * + * @param index the index of the prefix that needs to be returned + * @return the phone number prefix at the provided index + */ + public abstract int getPrefix(int index); + + /** + * Gets the description corresponding to the phone number prefix located at the provided {@code + * index}. If the description is not available in the current language an empty string is + * returned. + * + * @param index the index of the phone number prefix that needs to be returned + * @return the description corresponding to the phone number prefix at the provided index + */ + public abstract String getDescription(int index); + + /** + * Sets the internal state of the underlying storage implementation from the provided {@code + * sortedAreaCodeMap} that maps phone number prefixes to description strings. + * + * @param sortedAreaCodeMap a sorted map that maps phone number prefixes including country + * calling code to description strings + */ + public abstract void readFromSortedMap(SortedMap<Integer, String> sortedAreaCodeMap); + + /** + * Sets the internal state of the underlying storage implementation reading the provided {@code + * objectInput}. + * + * @param objectInput the object input stream from which the area code map is read + * @throws IOException if an error occurred reading the provided input stream + */ + public abstract void readExternal(ObjectInput objectInput) throws IOException; + + /** + * Writes the internal state of the underlying storage implementation to the provided {@code + * objectOutput}. + * + * @param objectOutput the object output stream to which the area code map is written + * @throws IOException if an error occurred writing to the provided output stream + */ + public abstract void writeExternal(ObjectOutput objectOutput) throws IOException; + + /** + * @return the number of entries contained in the area code map + */ + public int getNumOfEntries() { + return numOfEntries; + } + + /** + * @return the set containing the possible lengths of prefixes + */ + public TreeSet<Integer> getPossibleLengths() { + return possibleLengths; + } + + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + int numOfEntries = getNumOfEntries(); + + for (int i = 0; i < numOfEntries; i++) { + output.append(getPrefix(i)) + .append("|") + .append(getDescription(i)) + .append("\n"); + } + return output.toString(); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/DefaultMapStorage.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/DefaultMapStorage.java new file mode 100644 index 0000000..4242118 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/DefaultMapStorage.java @@ -0,0 +1,94 @@ +/* + * 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.geocoding; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.SortedMap; + +/** + * Default area code map storage strategy that is used for data not containing description + * duplications. It is mainly intended to avoid the overhead of the string table management when it + * is actually unnecessary (i.e no string duplication). + * + * @author Shaopeng Jia + */ +class DefaultMapStorage extends AreaCodeMapStorageStrategy { + + public DefaultMapStorage() {} + + private int[] phoneNumberPrefixes; + private String[] descriptions; + + @Override + public int getPrefix(int index) { + return phoneNumberPrefixes[index]; + } + + @Override + public String getDescription(int index) { + return descriptions[index]; + } + + @Override + public void readFromSortedMap(SortedMap<Integer, String> sortedAreaCodeMap) { + numOfEntries = sortedAreaCodeMap.size(); + phoneNumberPrefixes = new int[numOfEntries]; + descriptions = new String[numOfEntries]; + int index = 0; + for (int prefix : sortedAreaCodeMap.keySet()) { + phoneNumberPrefixes[index++] = prefix; + possibleLengths.add((int) Math.log10(prefix) + 1); + } + sortedAreaCodeMap.values().toArray(descriptions); + } + + @Override + public void readExternal(ObjectInput objectInput) throws IOException { + numOfEntries = objectInput.readInt(); + if (phoneNumberPrefixes == null || phoneNumberPrefixes.length < numOfEntries) { + phoneNumberPrefixes = new int[numOfEntries]; + } + if (descriptions == null || descriptions.length < numOfEntries) { + descriptions = new String[numOfEntries]; + } + for (int i = 0; i < numOfEntries; i++) { + phoneNumberPrefixes[i] = objectInput.readInt(); + descriptions[i] = objectInput.readUTF(); + } + int sizeOfLengths = objectInput.readInt(); + possibleLengths.clear(); + for (int i = 0; i < sizeOfLengths; i++) { + possibleLengths.add(objectInput.readInt()); + } + } + + @Override + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeInt(numOfEntries); + for (int i = 0; i < numOfEntries; i++) { + objectOutput.writeInt(phoneNumberPrefixes[i]); + objectOutput.writeUTF(descriptions[i]); + } + int sizeOfLengths = possibleLengths.size(); + objectOutput.writeInt(sizeOfLengths); + for (Integer length : possibleLengths) { + objectOutput.writeInt(length); + } + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorage.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorage.java new file mode 100644 index 0000000..54e9647 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorage.java @@ -0,0 +1,263 @@ +/* + * 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.geocoding; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Flyweight area code map storage strategy that uses a table to store unique strings and shorts to + * store the prefix and description indexes when possible. It is particularly space-efficient when + * the provided area code map contains a lot of redundant descriptions. + * + * @author Philippe Liard + */ +final class FlyweightMapStorage extends AreaCodeMapStorageStrategy { + // Size of short and integer types in bytes. + private static final int SHORT_NUM_BYTES = Short.SIZE / 8; + private static final int INT_NUM_BYTES = Integer.SIZE / 8; + + // The number of bytes used to store a phone number prefix. + private int prefixSizeInBytes; + // The number of bytes used to store a description index. It is computed from the size of the + // description pool containing all the strings. + private int descIndexSizeInBytes; + + private ByteBuffer phoneNumberPrefixes; + private ByteBuffer descriptionIndexes; + + // Sorted string array of unique description strings. + private String[] descriptionPool; + + @Override + public int getPrefix(int index) { + return readWordFromBuffer(phoneNumberPrefixes, prefixSizeInBytes, index); + } + + /** + * This implementation returns the same string (same identity) when called for multiple indexes + * corresponding to prefixes that have the same description. + */ + @Override + public String getDescription(int index) { + int indexInDescriptionPool = + readWordFromBuffer(descriptionIndexes, descIndexSizeInBytes, index); + return descriptionPool[indexInDescriptionPool]; + } + + @Override + public void readFromSortedMap(SortedMap<Integer, String> areaCodeMap) { + SortedSet<String> descriptionsSet = new TreeSet<String>(); + numOfEntries = areaCodeMap.size(); + prefixSizeInBytes = getOptimalNumberOfBytesForValue(areaCodeMap.lastKey()); + phoneNumberPrefixes = ByteBuffer.allocate(numOfEntries * prefixSizeInBytes); + + // Fill the phone number prefixes byte buffer, the set of possible lengths of prefixes and the + // description set. + int index = 0; + for (Entry<Integer, String> entry : areaCodeMap.entrySet()) { + int prefix = entry.getKey(); + storeWordInBuffer(phoneNumberPrefixes, prefixSizeInBytes, index, prefix); + possibleLengths.add((int) Math.log10(prefix) + 1); + descriptionsSet.add(entry.getValue()); + ++index; + } + createDescriptionPool(descriptionsSet, areaCodeMap); + } + + /** + * Creates the description pool from the provided set of string descriptions and area code map. + */ + private void createDescriptionPool(SortedSet<String> descriptionsSet, + SortedMap<Integer, String> areaCodeMap) { + descIndexSizeInBytes = getOptimalNumberOfBytesForValue(descriptionsSet.size() - 1); + descriptionIndexes = ByteBuffer.allocate(numOfEntries * descIndexSizeInBytes); + descriptionPool = new String[descriptionsSet.size()]; + descriptionsSet.toArray(descriptionPool); + + // Map the phone number prefixes to the descriptions. + int index = 0; + for (int i = 0; i < numOfEntries; i++) { + int prefix = readWordFromBuffer(phoneNumberPrefixes, prefixSizeInBytes, i); + String description = areaCodeMap.get(prefix); + int positionInDescriptionPool = Arrays.binarySearch(descriptionPool, description); + storeWordInBuffer(descriptionIndexes, descIndexSizeInBytes, index, positionInDescriptionPool); + ++index; + } + } + + @Override + public void readExternal(ObjectInput objectInput) throws IOException { + // Read binary words sizes. + prefixSizeInBytes = objectInput.readInt(); + descIndexSizeInBytes = objectInput.readInt(); + + // Read possible lengths. + int sizeOfLengths = objectInput.readInt(); + possibleLengths.clear(); + for (int i = 0; i < sizeOfLengths; i++) { + possibleLengths.add(objectInput.readInt()); + } + + // Read description pool size. + int descriptionPoolSize = objectInput.readInt(); + // Read description pool. + if (descriptionPool == null || descriptionPool.length < descriptionPoolSize) { + descriptionPool = new String[descriptionPoolSize]; + } + for (int i = 0; i < descriptionPoolSize; i++) { + String description = objectInput.readUTF(); + descriptionPool[i] = description; + } + readEntries(objectInput); + } + + /** + * Reads the area code entries from the provided input stream and stores them to the internal byte + * buffers. + */ + private void readEntries(ObjectInput objectInput) throws IOException { + numOfEntries = objectInput.readInt(); + if (phoneNumberPrefixes == null || phoneNumberPrefixes.capacity() < numOfEntries) { + phoneNumberPrefixes = ByteBuffer.allocate(numOfEntries * prefixSizeInBytes); + } + if (descriptionIndexes == null || descriptionIndexes.capacity() < numOfEntries) { + descriptionIndexes = ByteBuffer.allocate(numOfEntries * descIndexSizeInBytes); + } + for (int i = 0; i < numOfEntries; i++) { + readExternalWord(objectInput, prefixSizeInBytes, phoneNumberPrefixes, i); + readExternalWord(objectInput, descIndexSizeInBytes, descriptionIndexes, i); + } + } + + @Override + public void writeExternal(ObjectOutput objectOutput) throws IOException { + // Write binary words sizes. + objectOutput.writeInt(prefixSizeInBytes); + objectOutput.writeInt(descIndexSizeInBytes); + + // Write possible lengths. + int sizeOfLengths = possibleLengths.size(); + objectOutput.writeInt(sizeOfLengths); + for (Integer length : possibleLengths) { + objectOutput.writeInt(length); + } + + // Write description pool size. + objectOutput.writeInt(descriptionPool.length); + // Write description pool. + for (String description : descriptionPool) { + objectOutput.writeUTF(description); + } + + // Write entries. + objectOutput.writeInt(numOfEntries); + for (int i = 0; i < numOfEntries; i++) { + writeExternalWord(objectOutput, prefixSizeInBytes, phoneNumberPrefixes, i); + writeExternalWord(objectOutput, descIndexSizeInBytes, descriptionIndexes, i); + } + } + + /** + * Gets the minimum number of bytes that can be used to store the provided {@code value}. + */ + private static int getOptimalNumberOfBytesForValue(int value) { + return value <= Short.MAX_VALUE ? SHORT_NUM_BYTES : INT_NUM_BYTES; + } + + /** + * Stores a value which is read from the provided {@code objectInput} to the provided byte {@code + * buffer} at the specified {@code index}. + * + * @param objectInput the object input stream from which the value is read + * @param wordSize the number of bytes used to store the value read from the stream + * @param outputBuffer the byte buffer to which the value is stored + * @param index the index where the value is stored in the buffer + * @throws IOException if an error occurred reading from the object input stream + */ + private static void readExternalWord(ObjectInput objectInput, int wordSize, + ByteBuffer outputBuffer, int index) throws IOException { + int wordIndex = index * wordSize; + if (wordSize == SHORT_NUM_BYTES) { + outputBuffer.putShort(wordIndex, objectInput.readShort()); + } else { + outputBuffer.putInt(wordIndex, objectInput.readInt()); + } + } + + /** + * Writes the value read from the provided byte {@code buffer} at the specified {@code index} to + * the provided {@code objectOutput}. + * + * @param objectOutput the object output stream to which the value is written + * @param wordSize the number of bytes used to store the value + * @param inputBuffer the byte buffer from which the value is read + * @param index the index of the value in the the byte buffer + * @throws IOException if an error occurred writing to the provided object output stream + */ + private static void writeExternalWord(ObjectOutput objectOutput, int wordSize, + ByteBuffer inputBuffer, int index) throws IOException { + int wordIndex = index * wordSize; + if (wordSize == SHORT_NUM_BYTES) { + objectOutput.writeShort(inputBuffer.getShort(wordIndex)); + } else { + objectOutput.writeInt(inputBuffer.getInt(wordIndex)); + } + } + + /** + * Reads the {@code value} at the specified {@code index} from the provided byte {@code buffer}. + * Note that only integer and short sizes are supported. + * + * @param buffer the byte buffer from which the value is read + * @param wordSize the number of bytes used to store the value + * @param index the index where the value is read from + * + * @return the value read from the buffer + */ + private static int readWordFromBuffer(ByteBuffer buffer, int wordSize, int index) { + int wordIndex = index * wordSize; + return wordSize == SHORT_NUM_BYTES ? buffer.getShort(wordIndex) : buffer.getInt(wordIndex); + } + + /** + * Stores the provided {@code value} to the provided byte {@code buffer} at the specified {@code + * index} using the provided {@code wordSize} in bytes. Note that only integer and short sizes are + * supported. + * + * @param buffer the byte buffer to which the value is stored + * @param wordSize the number of bytes used to store the provided value + * @param index the index to which the value is stored + * @param value the value that is stored assuming it does not require more than the specified + * number of bytes. + */ + private static void storeWordInBuffer(ByteBuffer buffer, int wordSize, int index, int value) { + int wordIndex = index * wordSize; + if (wordSize == SHORT_NUM_BYTES) { + buffer.putShort(wordIndex, (short) value); + } else { + buffer.putInt(wordIndex, value); + } + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/MappingFileProvider.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/MappingFileProvider.java new file mode 100644 index 0000000..d3aa3b0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/MappingFileProvider.java @@ -0,0 +1,229 @@ +/* + * 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.geocoding; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * A utility which knows the data files that are available for the geocoder to use. The data files + * contain mappings from phone number prefixes to text descriptions, and are organized by country + * calling code and language that the text descriptions are in. + * + * @author Shaopeng Jia + */ +public class MappingFileProvider implements Externalizable { + private int numOfEntries = 0; + private int[] countryCallingCodes; + private List<Set<String>> availableLanguages; + private static final Map<String, String> LOCALE_NORMALIZATION_MAP; + + static { + Map<String, String> normalizationMap = new HashMap<String, String>(); + normalizationMap.put("zh_TW", "zh_Hant"); + normalizationMap.put("zh_HK", "zh_Hant"); + normalizationMap.put("zh_MO", "zh_Hant"); + + LOCALE_NORMALIZATION_MAP = Collections.unmodifiableMap(normalizationMap); + } + + /** + * Creates an empty {@link MappingFileProvider}. The default constructor is necessary for + * implementing {@link Externalizable}. The empty provider could later be populated by + * {@link #readFileConfigs(java.util.SortedMap)} or {@link #readExternal(java.io.ObjectInput)}. + */ + public MappingFileProvider() { + } + + /** + * Initializes an {@link MappingFileProvider} with {@code availableDataFiles}. + * + * @param availableDataFiles a map from country calling codes to sets of languages in which data + * files are available for the specific country calling code. The map is sorted in ascending + * order of the country calling codes as integers. + */ + public void readFileConfigs(SortedMap<Integer, Set<String>> availableDataFiles) { + numOfEntries = availableDataFiles.size(); + countryCallingCodes = new int[numOfEntries]; + availableLanguages = new ArrayList<Set<String>>(numOfEntries); + int index = 0; + for (int countryCallingCode : availableDataFiles.keySet()) { + countryCallingCodes[index++] = countryCallingCode; + availableLanguages.add(new HashSet<String>(availableDataFiles.get(countryCallingCode))); + } + } + + /** + * Supports Java Serialization. + */ + public void readExternal(ObjectInput objectInput) throws IOException { + numOfEntries = objectInput.readInt(); + if (countryCallingCodes == null || countryCallingCodes.length < numOfEntries) { + countryCallingCodes = new int[numOfEntries]; + } + if (availableLanguages == null) { + availableLanguages = new ArrayList<Set<String>>(); + } + for (int i = 0; i < numOfEntries; i++) { + countryCallingCodes[i] = objectInput.readInt(); + int numOfLangs = objectInput.readInt(); + Set<String> setOfLangs = new HashSet<String>(); + for (int j = 0; j < numOfLangs; j++) { + setOfLangs.add(objectInput.readUTF()); + } + availableLanguages.add(setOfLangs); + } + } + + /** + * Supports Java Serialization. + */ + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeInt(numOfEntries); + for (int i = 0; i < numOfEntries; i++) { + objectOutput.writeInt(countryCallingCodes[i]); + Set<String> setOfLangs = availableLanguages.get(i); + int numOfLangs = setOfLangs.size(); + objectOutput.writeInt(numOfLangs); + for (String lang : setOfLangs) { + objectOutput.writeUTF(lang); + } + } + } + + /** + * Returns a string representing the data in this class. The string contains one line for each + * country calling code. The country calling code is followed by a '|' and then a list of + * comma-separated languages sorted in ascending order. + */ + @Override + public String toString() { + StringBuilder output = new StringBuilder(); + for (int i = 0; i < numOfEntries; i++) { + output.append(countryCallingCodes[i]); + output.append('|'); + SortedSet<String> sortedSetOfLangs = new TreeSet<String>(availableLanguages.get(i)); + for (String lang : sortedSetOfLangs) { + output.append(lang); + output.append(','); + } + output.append('\n'); + } + return output.toString(); + } + + /** + * Gets the name of the file that contains the mapping data for the {@code countryCallingCode} in + * the language specified. + * + * @param countryCallingCode the country calling code of phone numbers which the data file + * contains + * @param language two-letter lowercase ISO language codes as defined by ISO 639-1 + * @param script four-letter titlecase (the first letter is uppercase and the rest of the letters + * are lowercase) ISO script codes as defined in ISO 15924 + * @param region two-letter uppercase ISO country codes as defined by ISO 3166-1 + * @return the name of the file, or empty string if no such file can be found + */ + String getFileName(int countryCallingCode, String language, String script, String region) { + if (language.length() == 0) { + return ""; + } + int index = Arrays.binarySearch(countryCallingCodes, countryCallingCode); + if (index < 0) { + return ""; + } + Set<String> setOfLangs = availableLanguages.get(index); + if (setOfLangs.size() > 0) { + String languageCode = findBestMatchingLanguageCode(setOfLangs, language, script, region); + if (languageCode.length() > 0) { + StringBuilder fileName = new StringBuilder(); + fileName.append(countryCallingCode).append('_').append(languageCode); + return fileName.toString(); + } + } + return ""; + } + + private String findBestMatchingLanguageCode( + Set<String> setOfLangs, String language, String script, String region) { + StringBuilder fullLocale = constructFullLocale(language, script, region); + String fullLocaleStr = fullLocale.toString(); + String normalizedLocale = LOCALE_NORMALIZATION_MAP.get(fullLocaleStr); + if (normalizedLocale != null) { + if (setOfLangs.contains(normalizedLocale)) { + return normalizedLocale; + } + } + if (setOfLangs.contains(fullLocaleStr)) { + return fullLocaleStr; + } + + if (onlyOneOfScriptOrRegionIsEmpty(script, region)) { + if (setOfLangs.contains(language)) { + return language; + } + } else if (script.length() > 0 && region.length() > 0) { + StringBuilder langWithScript = new StringBuilder(language).append('_').append(script); + String langWithScriptStr = langWithScript.toString(); + if (setOfLangs.contains(langWithScriptStr)) { + return langWithScriptStr; + } + + StringBuilder langWithRegion = new StringBuilder(language).append('_').append(region); + String langWithRegionStr = langWithRegion.toString(); + if (setOfLangs.contains(langWithRegionStr)) { + return langWithRegionStr; + } + + if (setOfLangs.contains(language)) { + return language; + } + } + return ""; + } + + private boolean onlyOneOfScriptOrRegionIsEmpty(String script, String region) { + return (script.length() == 0 && region.length() > 0) || + (region.length() == 0 && script.length() > 0); + } + + private StringBuilder constructFullLocale(String language, String script, String region) { + StringBuilder fullLocale = new StringBuilder(language); + appendSubsequentLocalePart(script, fullLocale); + appendSubsequentLocalePart(region, fullLocale); + return fullLocale; + } + + private void appendSubsequentLocalePart(String subsequentLocalePart, StringBuilder fullLocale) { + if (subsequentLocalePart.length() > 0) { + fullLocale.append('_').append(subsequentLocalePart); + } + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java new file mode 100644 index 0000000..1d074b7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java @@ -0,0 +1,217 @@ +/* + * 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.geocoding; + +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An offline geocoder which provides geographical information related to a phone number. + * + * @author Shaopeng Jia + */ +public class PhoneNumberOfflineGeocoder { + private static PhoneNumberOfflineGeocoder instance = null; + private static final String MAPPING_DATA_DIRECTORY = + "/com/google/i18n/phonenumbers/geocoding/data/"; + private static final Logger LOGGER = Logger.getLogger(PhoneNumberOfflineGeocoder.class.getName()); + + private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + private final String phonePrefixDataDirectory; + + // The mappingFileProvider knows for which combination of countryCallingCode and language a phone + // prefix mapping file is available in the file system, so that a file can be loaded when needed. + private MappingFileProvider mappingFileProvider = new MappingFileProvider(); + + // A mapping from countryCallingCode_lang to the corresponding phone prefix map that has been + // loaded. + private Map<String, AreaCodeMap> availablePhonePrefixMaps = new HashMap<String, AreaCodeMap>(); + + // @VisibleForTesting + PhoneNumberOfflineGeocoder(String phonePrefixDataDirectory) { + this.phonePrefixDataDirectory = phonePrefixDataDirectory; + loadMappingFileProvider(); + } + + private void loadMappingFileProvider() { + InputStream source = + PhoneNumberOfflineGeocoder.class.getResourceAsStream(phonePrefixDataDirectory + "config"); + ObjectInputStream in = null; + try { + in = new ObjectInputStream(source); + mappingFileProvider.readExternal(in); + } catch (IOException e) { + LOGGER.log(Level.WARNING, e.toString()); + } finally { + close(in); + } + } + + private AreaCodeMap getPhonePrefixDescriptions( + int prefixMapKey, String language, String script, String region) { + String fileName = mappingFileProvider.getFileName(prefixMapKey, language, script, region); + if (fileName.length() == 0) { + return null; + } + if (!availablePhonePrefixMaps.containsKey(fileName)) { + loadAreaCodeMapFromFile(fileName); + } + return availablePhonePrefixMaps.get(fileName); + } + + private void loadAreaCodeMapFromFile(String fileName) { + InputStream source = + PhoneNumberOfflineGeocoder.class.getResourceAsStream(phonePrefixDataDirectory + fileName); + ObjectInputStream in = null; + try { + in = new ObjectInputStream(source); + AreaCodeMap map = new AreaCodeMap(); + map.readExternal(in); + availablePhonePrefixMaps.put(fileName, map); + } catch (IOException e) { + LOGGER.log(Level.WARNING, e.toString()); + } finally { + close(in); + } + } + + private static void close(InputStream in) { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + LOGGER.log(Level.WARNING, e.toString()); + } + } + } + + /** + * Gets a {@link PhoneNumberOfflineGeocoder} instance to carry out international phone number + * geocoding. + * + * <p> The {@link PhoneNumberOfflineGeocoder} is implemented as a singleton. Therefore, calling + * this method multiple times will only result in one instance being created. + * + * @return a {@link PhoneNumberOfflineGeocoder} instance + */ + public static synchronized PhoneNumberOfflineGeocoder getInstance() { + if (instance == null) { + instance = new PhoneNumberOfflineGeocoder(MAPPING_DATA_DIRECTORY); + } + return instance; + } + + /** + * Returns the customary display name in the given language for the given territory the phone + * number is from. + */ + private String getCountryNameForNumber(PhoneNumber number, Locale language) { + String regionCode = phoneUtil.getRegionCodeForNumber(number); + return (regionCode == null || regionCode.equals("ZZ")) + ? "" : new Locale("", regionCode).getDisplayCountry(language); + } + + /** + * Returns a text description for the given language code for the given phone number. The + * description might consist of the name of the country where the phone number is from and/or the + * name of the geographical area the phone number is from. This method assumes the validity of the + * number passed in has already been checked. + * + * @param number a valid phone number for which we want to get a text description + * @param languageCode the language code for which the description should be written + * @return a text description for the given language code for the given phone number + */ + public String getDescriptionForValidNumber(PhoneNumber number, Locale languageCode) { + String langStr = languageCode.getLanguage(); + String scriptStr = ""; // No script is specified + String regionStr = languageCode.getCountry(); + + String areaDescription = + getAreaDescriptionForNumber(number, langStr, scriptStr, regionStr); + return (areaDescription.length() > 0) + ? areaDescription : getCountryNameForNumber(number, languageCode); + } + + /** + * Returns a text description for the given language code for the given phone number. The + * description might consist of the name of the country where the phone number is from and/or the + * name of the geographical area the phone number is from. This method explictly checkes the + * validity of the number passed in. + * + * @param number the phone number for which we want to get a text description + * @param languageCode the language code for which the description should be written + * @return a text description for the given language code for the given phone number, or empty + * string if the number passed in is invalid + */ + public String getDescriptionForNumber(PhoneNumber number, Locale languageCode) { + if (!phoneUtil.isValidNumber(number)) { + return ""; + } + return getDescriptionForValidNumber(number, languageCode); + } + + /** + * Returns an area-level text description in the given language for the given phone number. + * + * @param number the phone number for which we want to get a text description + * @param lang two-letter lowercase ISO language codes as defined by ISO 639-1 + * @param script four-letter titlecase (the first letter is uppercase and the rest of the letters + * are lowercase) ISO script codes as defined in ISO 15924 + * @param region two-letter uppercase ISO country codes as defined by ISO 3166-1 + * @return an area-level text description in the given language for the given phone number, or an + * empty string if such a description is not available + */ + private String getAreaDescriptionForNumber( + PhoneNumber number, String lang, String script, String region) { + int countryCallingCode = number.getCountryCode(); + // As the NANPA data is split into multiple files covering 3-digit areas, use a phone number + // prefix of 4 digits for NANPA instead, e.g. 1650. + int phonePrefix = (countryCallingCode != 1) ? + countryCallingCode : (1000 + (int) (number.getNationalNumber() / 10000000)); + AreaCodeMap phonePrefixDescriptions = + getPhonePrefixDescriptions(phonePrefix, lang, script, region); + String description = (phonePrefixDescriptions != null) + ? phonePrefixDescriptions.lookup(number) + : null; + // When a location is not available in the requested language, fall back to English. + if ((description == null || description.length() == 0) && mayFallBackToEnglish(lang)) { + AreaCodeMap defaultMap = getPhonePrefixDescriptions(phonePrefix, "en", "", ""); + if (defaultMap == null) { + return ""; + } + description = defaultMap.lookup(number); + } + return description != null ? description : ""; + } + + private boolean mayFallBackToEnglish(String lang) { + // Don't fall back to English if the requested language is among the following: + // - Chinese + // - Japanese + // - Korean + return !lang.equals("zh") && !lang.equals("ja") && !lang.equals("ko"); + } +} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1201_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1201_en Binary files differnew file mode 100644 index 0000000..bb98273 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1201_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1202_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1202_en Binary files differnew file mode 100644 index 0000000..306ce02 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1202_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1203_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1203_en Binary files differnew file mode 100644 index 0000000..93786eb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1203_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1204_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1204_en Binary files differnew file mode 100644 index 0000000..eaad437 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1204_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1205_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1205_en Binary files differnew file mode 100644 index 0000000..8fb3949 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1205_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1206_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1206_en Binary files differnew file mode 100644 index 0000000..e5ee177 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1206_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1207_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1207_en Binary files differnew file mode 100644 index 0000000..4d720c3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1207_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1208_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1208_en Binary files differnew file mode 100644 index 0000000..0c503bf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1208_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1209_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1209_en Binary files differnew file mode 100644 index 0000000..f55fa82 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1209_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1210_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1210_en Binary files differnew file mode 100644 index 0000000..519470d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1210_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1212_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1212_en Binary files differnew file mode 100644 index 0000000..d4179c0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1212_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1213_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1213_en Binary files differnew file mode 100644 index 0000000..e7315eb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1213_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1214_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1214_en Binary files differnew file mode 100644 index 0000000..1a736df --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1214_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1215_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1215_en Binary files differnew file mode 100644 index 0000000..9caefe3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1215_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1216_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1216_en Binary files differnew file mode 100644 index 0000000..5305522 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1216_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1217_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1217_en Binary files differnew file mode 100644 index 0000000..b6e2606 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1217_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1218_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1218_en Binary files differnew file mode 100644 index 0000000..52851ba --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1218_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1219_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1219_en Binary files differnew file mode 100644 index 0000000..5731a17 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1219_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1224_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1224_en Binary files differnew file mode 100644 index 0000000..5af1238 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1224_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1225_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1225_en Binary files differnew file mode 100644 index 0000000..32ee0d0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1225_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1226_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1226_en Binary files differnew file mode 100644 index 0000000..7f2d4fa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1226_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1228_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1228_en Binary files differnew file mode 100644 index 0000000..5440111 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1228_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1229_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1229_en Binary files differnew file mode 100644 index 0000000..bd6c00f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1229_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1231_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1231_en Binary files differnew file mode 100644 index 0000000..3a137ed --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1231_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1234_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1234_en Binary files differnew file mode 100644 index 0000000..14906de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1234_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1239_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1239_en Binary files differnew file mode 100644 index 0000000..ed594ca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1239_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1240_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1240_en Binary files differnew file mode 100644 index 0000000..8b054e1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1240_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1248_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1248_en Binary files differnew file mode 100644 index 0000000..cc14c9e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1248_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1250_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1250_en Binary files differnew file mode 100644 index 0000000..4f1f495 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1250_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1251_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1251_en Binary files differnew file mode 100644 index 0000000..dd34251 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1251_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1252_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1252_en Binary files differnew file mode 100644 index 0000000..d4243ab --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1252_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1253_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1253_en Binary files differnew file mode 100644 index 0000000..ca292d9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1253_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1254_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1254_en Binary files differnew file mode 100644 index 0000000..8c090c8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1254_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1256_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1256_en Binary files differnew file mode 100644 index 0000000..b954f65 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1256_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1260_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1260_en Binary files differnew file mode 100644 index 0000000..1d112d9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1260_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1262_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1262_en Binary files differnew file mode 100644 index 0000000..a0ba4c0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1262_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1267_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1267_en Binary files differnew file mode 100644 index 0000000..3c8fba6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1267_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1269_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1269_en Binary files differnew file mode 100644 index 0000000..7111bf4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1269_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1270_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1270_en Binary files differnew file mode 100644 index 0000000..81775d7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1270_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1276_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1276_en Binary files differnew file mode 100644 index 0000000..95d98ab --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1276_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1281_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1281_en Binary files differnew file mode 100644 index 0000000..67a497f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1281_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1289_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1289_en Binary files differnew file mode 100644 index 0000000..a44c5b3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1289_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1301_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1301_en Binary files differnew file mode 100644 index 0000000..fdec02f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1301_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1302_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1302_en Binary files differnew file mode 100644 index 0000000..d9578c8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1302_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1303_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1303_en Binary files differnew file mode 100644 index 0000000..2df62e6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1303_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1304_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1304_en Binary files differnew file mode 100644 index 0000000..812f34b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1304_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1305_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1305_en Binary files differnew file mode 100644 index 0000000..ddc522f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1305_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1306_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1306_en Binary files differnew file mode 100644 index 0000000..35094f0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1306_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1307_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1307_en Binary files differnew file mode 100644 index 0000000..9a851de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1307_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1308_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1308_en Binary files differnew file mode 100644 index 0000000..b0545ca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1308_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1309_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1309_en Binary files differnew file mode 100644 index 0000000..d5029f8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1309_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1310_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1310_en Binary files differnew file mode 100644 index 0000000..8340bba --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1310_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1312_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1312_en Binary files differnew file mode 100644 index 0000000..9a2fdc6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1312_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1313_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1313_en Binary files differnew file mode 100644 index 0000000..e09f6cd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1313_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1314_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1314_en Binary files differnew file mode 100644 index 0000000..576ac1c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1314_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1315_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1315_en Binary files differnew file mode 100644 index 0000000..c097de2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1315_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1316_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1316_en Binary files differnew file mode 100644 index 0000000..eae6b38 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1316_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1317_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1317_en Binary files differnew file mode 100644 index 0000000..e577222 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1317_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1318_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1318_en Binary files differnew file mode 100644 index 0000000..3e48ecc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1318_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1319_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1319_en Binary files differnew file mode 100644 index 0000000..f690c73 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1319_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1320_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1320_en Binary files differnew file mode 100644 index 0000000..6441a1d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1320_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1321_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1321_en Binary files differnew file mode 100644 index 0000000..a3e406e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1321_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1323_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1323_en Binary files differnew file mode 100644 index 0000000..8571ced --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1323_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1325_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1325_en Binary files differnew file mode 100644 index 0000000..e3f8595 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1325_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1330_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1330_en Binary files differnew file mode 100644 index 0000000..a3f3b7e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1330_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1331_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1331_en Binary files differnew file mode 100644 index 0000000..d5f7c6c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1331_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1334_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1334_en Binary files differnew file mode 100644 index 0000000..2aab6a1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1334_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1336_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1336_en Binary files differnew file mode 100644 index 0000000..a873afc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1336_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1337_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1337_en Binary files differnew file mode 100644 index 0000000..6de57a4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1337_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1339_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1339_en Binary files differnew file mode 100644 index 0000000..0c2e42b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1339_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1347_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1347_en Binary files differnew file mode 100644 index 0000000..4b4c5dc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1347_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1351_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1351_en Binary files differnew file mode 100644 index 0000000..eee213d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1351_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1352_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1352_en Binary files differnew file mode 100644 index 0000000..ec62795 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1352_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1360_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1360_en Binary files differnew file mode 100644 index 0000000..f9a5a8a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1360_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1361_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1361_en Binary files differnew file mode 100644 index 0000000..5c221a9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1361_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1385_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1385_en Binary files differnew file mode 100644 index 0000000..4a4c1bb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1385_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1386_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1386_en Binary files differnew file mode 100644 index 0000000..45049ba --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1386_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1401_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1401_en Binary files differnew file mode 100644 index 0000000..7293621 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1401_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1402_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1402_en Binary files differnew file mode 100644 index 0000000..d93b8c9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1402_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1403_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1403_en Binary files differnew file mode 100644 index 0000000..b606c26 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1403_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1404_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1404_en Binary files differnew file mode 100644 index 0000000..bf273a3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1404_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1405_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1405_en Binary files differnew file mode 100644 index 0000000..9722abc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1405_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1406_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1406_en Binary files differnew file mode 100644 index 0000000..4874675 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1406_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1407_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1407_en Binary files differnew file mode 100644 index 0000000..6acfc6a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1407_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1408_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1408_en Binary files differnew file mode 100644 index 0000000..62ac82a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1408_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1409_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1409_en Binary files differnew file mode 100644 index 0000000..15d8a3a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1409_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1410_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1410_en Binary files differnew file mode 100644 index 0000000..2e3c4ac --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1410_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1412_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1412_en Binary files differnew file mode 100644 index 0000000..ed26616 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1412_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1413_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1413_en Binary files differnew file mode 100644 index 0000000..7cf4cee --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1413_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1414_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1414_en Binary files differnew file mode 100644 index 0000000..717dbd7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1414_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1415_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1415_en Binary files differnew file mode 100644 index 0000000..9079586 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1415_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1416_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1416_en Binary files differnew file mode 100644 index 0000000..d6e6f96 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1416_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1417_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1417_en Binary files differnew file mode 100644 index 0000000..ac551fd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1417_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1418_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1418_en Binary files differnew file mode 100644 index 0000000..8667894 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1418_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1419_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1419_en Binary files differnew file mode 100644 index 0000000..fb7548b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1419_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1423_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1423_en Binary files differnew file mode 100644 index 0000000..9023400 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1423_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1424_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1424_en Binary files differnew file mode 100644 index 0000000..bc3b1a5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1424_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1425_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1425_en Binary files differnew file mode 100644 index 0000000..7d7084e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1425_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1430_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1430_en Binary files differnew file mode 100644 index 0000000..eb8782d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1430_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1432_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1432_en Binary files differnew file mode 100644 index 0000000..9c8a2ca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1432_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1434_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1434_en Binary files differnew file mode 100644 index 0000000..82fb900 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1434_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1435_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1435_en Binary files differnew file mode 100644 index 0000000..db6c64f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1435_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1438_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1438_en Binary files differnew file mode 100644 index 0000000..be39869 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1438_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1440_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1440_en Binary files differnew file mode 100644 index 0000000..fd860de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1440_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1443_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1443_en Binary files differnew file mode 100644 index 0000000..bf278f6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1443_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1450_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1450_en Binary files differnew file mode 100644 index 0000000..4950cd8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1450_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1469_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1469_en Binary files differnew file mode 100644 index 0000000..d1caf62 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1469_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1478_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1478_en Binary files differnew file mode 100644 index 0000000..e5b09f9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1478_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1479_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1479_en Binary files differnew file mode 100644 index 0000000..51ab912 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1479_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1480_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1480_en Binary files differnew file mode 100644 index 0000000..8c259c0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1480_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1484_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1484_en Binary files differnew file mode 100644 index 0000000..4bc0dfa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1484_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1501_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1501_en Binary files differnew file mode 100644 index 0000000..7e118f6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1501_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1502_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1502_en Binary files differnew file mode 100644 index 0000000..a7a5b99 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1502_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1503_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1503_en Binary files differnew file mode 100644 index 0000000..48d05d4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1503_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1504_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1504_en Binary files differnew file mode 100644 index 0000000..49c0b85 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1504_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1505_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1505_en Binary files differnew file mode 100644 index 0000000..c4eb180 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1505_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1506_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1506_en Binary files differnew file mode 100644 index 0000000..6a7b473 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1506_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1507_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1507_en Binary files differnew file mode 100644 index 0000000..dc76325 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1507_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1508_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1508_en Binary files differnew file mode 100644 index 0000000..3e9ce41 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1508_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1509_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1509_en Binary files differnew file mode 100644 index 0000000..12fbdc6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1509_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1510_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1510_en Binary files differnew file mode 100644 index 0000000..b342c22 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1510_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1512_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1512_en Binary files differnew file mode 100644 index 0000000..63b9995 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1512_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1513_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1513_en Binary files differnew file mode 100644 index 0000000..338c8f1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1513_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1514_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1514_en Binary files differnew file mode 100644 index 0000000..8f5d124 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1514_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1515_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1515_en Binary files differnew file mode 100644 index 0000000..fada095 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1515_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1516_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1516_en Binary files differnew file mode 100644 index 0000000..39e0138 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1516_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1517_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1517_en Binary files differnew file mode 100644 index 0000000..f017efc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1517_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1518_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1518_en Binary files differnew file mode 100644 index 0000000..d57a9e0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1518_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1519_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1519_en Binary files differnew file mode 100644 index 0000000..184ffbf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1519_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1520_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1520_en Binary files differnew file mode 100644 index 0000000..1930d45 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1520_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1530_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1530_en Binary files differnew file mode 100644 index 0000000..0ba769f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1530_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1540_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1540_en Binary files differnew file mode 100644 index 0000000..2056d8f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1540_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1541_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1541_en Binary files differnew file mode 100644 index 0000000..def6616 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1541_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1551_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1551_en Binary files differnew file mode 100644 index 0000000..e36fbbc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1551_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1559_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1559_en Binary files differnew file mode 100644 index 0000000..a798388 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1559_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1561_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1561_en Binary files differnew file mode 100644 index 0000000..a5c4d8e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1561_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1562_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1562_en Binary files differnew file mode 100644 index 0000000..ae32a56 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1562_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1563_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1563_en Binary files differnew file mode 100644 index 0000000..1a6094f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1563_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1567_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1567_en Binary files differnew file mode 100644 index 0000000..4c005b5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1567_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1570_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1570_en Binary files differnew file mode 100644 index 0000000..c8491c1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1570_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1571_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1571_en Binary files differnew file mode 100644 index 0000000..bd6dc00 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1571_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1573_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1573_en Binary files differnew file mode 100644 index 0000000..e952524 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1573_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1574_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1574_en Binary files differnew file mode 100644 index 0000000..2eb7589 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1574_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1575_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1575_en Binary files differnew file mode 100644 index 0000000..5a8f792 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1575_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1580_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1580_en Binary files differnew file mode 100644 index 0000000..fe11647 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1580_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1585_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1585_en Binary files differnew file mode 100644 index 0000000..f55ba0f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1585_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1586_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1586_en Binary files differnew file mode 100644 index 0000000..721c4d0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1586_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1587_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1587_en Binary files differnew file mode 100644 index 0000000..71f8a24 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1587_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1601_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1601_en Binary files differnew file mode 100644 index 0000000..45e0d3c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1601_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1602_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1602_en Binary files differnew file mode 100644 index 0000000..b1d2266 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1602_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1603_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1603_en Binary files differnew file mode 100644 index 0000000..dc28c76 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1603_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1604_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1604_en Binary files differnew file mode 100644 index 0000000..6175abd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1604_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1605_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1605_en Binary files differnew file mode 100644 index 0000000..6f80f31 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1605_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1606_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1606_en Binary files differnew file mode 100644 index 0000000..30810b4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1606_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1607_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1607_en Binary files differnew file mode 100644 index 0000000..70c77da --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1607_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1608_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1608_en Binary files differnew file mode 100644 index 0000000..e29fcc2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1608_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1609_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1609_en Binary files differnew file mode 100644 index 0000000..8819bb4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1609_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1610_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1610_en Binary files differnew file mode 100644 index 0000000..ad86252 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1610_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1612_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1612_en Binary files differnew file mode 100644 index 0000000..2fb4156 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1612_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1613_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1613_en Binary files differnew file mode 100644 index 0000000..e1df260 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1613_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1614_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1614_en Binary files differnew file mode 100644 index 0000000..f9d0201 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1614_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1615_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1615_en Binary files differnew file mode 100644 index 0000000..5347dff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1615_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1616_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1616_en Binary files differnew file mode 100644 index 0000000..b6bef4d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1616_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1617_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1617_en Binary files differnew file mode 100644 index 0000000..6d47691 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1617_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1618_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1618_en Binary files differnew file mode 100644 index 0000000..074da52 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1618_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1619_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1619_en Binary files differnew file mode 100644 index 0000000..5781415 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1619_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1620_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1620_en Binary files differnew file mode 100644 index 0000000..1428f52 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1620_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1623_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1623_en Binary files differnew file mode 100644 index 0000000..fa04f3a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1623_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1626_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1626_en Binary files differnew file mode 100644 index 0000000..8243d25 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1626_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1630_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1630_en Binary files differnew file mode 100644 index 0000000..a545ba1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1630_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1631_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1631_en Binary files differnew file mode 100644 index 0000000..a3e4b30 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1631_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1636_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1636_en Binary files differnew file mode 100644 index 0000000..c6e31ce --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1636_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1641_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1641_en Binary files differnew file mode 100644 index 0000000..09d37ff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1641_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1646_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1646_en Binary files differnew file mode 100644 index 0000000..7029025 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1646_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1647_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1647_en Binary files differnew file mode 100644 index 0000000..c000f64 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1647_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1650_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1650_en Binary files differnew file mode 100644 index 0000000..349fdcf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1650_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1651_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1651_en Binary files differnew file mode 100644 index 0000000..edd6f90 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1651_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1657_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1657_en Binary files differnew file mode 100644 index 0000000..dd7858f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1657_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1660_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1660_en Binary files differnew file mode 100644 index 0000000..84167e8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1660_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1661_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1661_en Binary files differnew file mode 100644 index 0000000..163197a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1661_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1662_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1662_en Binary files differnew file mode 100644 index 0000000..89104de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1662_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1678_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1678_en Binary files differnew file mode 100644 index 0000000..287de14 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1678_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1682_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1682_en Binary files differnew file mode 100644 index 0000000..f70ae44 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1682_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1701_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1701_en Binary files differnew file mode 100644 index 0000000..402f3c2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1701_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1702_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1702_en Binary files differnew file mode 100644 index 0000000..b5cb753 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1702_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1703_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1703_en Binary files differnew file mode 100644 index 0000000..3196a8e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1703_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1704_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1704_en Binary files differnew file mode 100644 index 0000000..65928c3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1704_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1705_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1705_en Binary files differnew file mode 100644 index 0000000..441b558 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1705_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1706_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1706_en Binary files differnew file mode 100644 index 0000000..988df79 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1706_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1707_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1707_en Binary files differnew file mode 100644 index 0000000..37194ec --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1707_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1708_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1708_en Binary files differnew file mode 100644 index 0000000..b68c3aa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1708_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1709_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1709_en Binary files differnew file mode 100644 index 0000000..1047732 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1709_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1712_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1712_en Binary files differnew file mode 100644 index 0000000..92a81f1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1712_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1713_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1713_en Binary files differnew file mode 100644 index 0000000..5ca9b5e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1713_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1714_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1714_en Binary files differnew file mode 100644 index 0000000..ffc4f85 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1714_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1715_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1715_en Binary files differnew file mode 100644 index 0000000..0079c6b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1715_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1716_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1716_en Binary files differnew file mode 100644 index 0000000..b393523 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1716_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1717_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1717_en Binary files differnew file mode 100644 index 0000000..876a808 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1717_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1718_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1718_en Binary files differnew file mode 100644 index 0000000..4a16abb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1718_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1719_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1719_en Binary files differnew file mode 100644 index 0000000..dc6d6a7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1719_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1720_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1720_en Binary files differnew file mode 100644 index 0000000..aa2deb2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1720_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1724_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1724_en Binary files differnew file mode 100644 index 0000000..b95249e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1724_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1726_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1726_en Binary files differnew file mode 100644 index 0000000..cb81e2d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1726_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1727_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1727_en Binary files differnew file mode 100644 index 0000000..f59ce52 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1727_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1730_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1730_en Binary files differnew file mode 100644 index 0000000..a2db58d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1730_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1731_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1731_en Binary files differnew file mode 100644 index 0000000..e041cac --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1731_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1732_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1732_en Binary files differnew file mode 100644 index 0000000..244a2c9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1732_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1734_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1734_en Binary files differnew file mode 100644 index 0000000..06f2135 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1734_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1740_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1740_en Binary files differnew file mode 100644 index 0000000..7ed9506 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1740_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1754_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1754_en Binary files differnew file mode 100644 index 0000000..701f6a8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1754_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1757_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1757_en Binary files differnew file mode 100644 index 0000000..97714b5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1757_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1760_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1760_en Binary files differnew file mode 100644 index 0000000..40854a6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1760_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1763_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1763_en Binary files differnew file mode 100644 index 0000000..971e1ac --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1763_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1765_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1765_en Binary files differnew file mode 100644 index 0000000..1e87dcc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1765_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1769_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1769_en Binary files differnew file mode 100644 index 0000000..7f5616a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1769_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1770_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1770_en Binary files differnew file mode 100644 index 0000000..01bc96d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1770_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1772_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1772_en Binary files differnew file mode 100644 index 0000000..3e6641b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1772_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1773_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1773_en Binary files differnew file mode 100644 index 0000000..3b5cb28 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1773_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1774_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1774_en Binary files differnew file mode 100644 index 0000000..47fe94a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1774_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1775_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1775_en Binary files differnew file mode 100644 index 0000000..879e514 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1775_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1778_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1778_en Binary files differnew file mode 100644 index 0000000..c6b9c96 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1778_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1779_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1779_en Binary files differnew file mode 100644 index 0000000..fac0886 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1779_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1780_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1780_en Binary files differnew file mode 100644 index 0000000..fdeddcc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1780_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1781_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1781_en Binary files differnew file mode 100644 index 0000000..ea2f926 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1781_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1785_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1785_en Binary files differnew file mode 100644 index 0000000..0ca48dd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1785_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1786_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1786_en Binary files differnew file mode 100644 index 0000000..612dd69 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1786_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1801_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1801_en Binary files differnew file mode 100644 index 0000000..c93ac1a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1801_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1802_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1802_en Binary files differnew file mode 100644 index 0000000..8fd7eb6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1802_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1803_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1803_en Binary files differnew file mode 100644 index 0000000..0732fbb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1803_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1804_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1804_en Binary files differnew file mode 100644 index 0000000..6f70d2c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1804_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1805_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1805_en Binary files differnew file mode 100644 index 0000000..47c5bf3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1805_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1806_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1806_en Binary files differnew file mode 100644 index 0000000..4674327 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1806_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1807_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1807_en Binary files differnew file mode 100644 index 0000000..86fde6d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1807_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1808_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1808_en Binary files differnew file mode 100644 index 0000000..b810cfb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1808_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1810_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1810_en Binary files differnew file mode 100644 index 0000000..c1e3af7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1810_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1812_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1812_en Binary files differnew file mode 100644 index 0000000..0ba83df --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1812_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1813_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1813_en Binary files differnew file mode 100644 index 0000000..7fb187f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1813_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1814_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1814_en Binary files differnew file mode 100644 index 0000000..2c05f2f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1814_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1815_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1815_en Binary files differnew file mode 100644 index 0000000..a80e7e8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1815_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1816_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1816_en Binary files differnew file mode 100644 index 0000000..fbfc566 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1816_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1817_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1817_en Binary files differnew file mode 100644 index 0000000..22f36cc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1817_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1818_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1818_en Binary files differnew file mode 100644 index 0000000..78cef0c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1818_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1819_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1819_en Binary files differnew file mode 100644 index 0000000..42ab96a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1819_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1828_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1828_en Binary files differnew file mode 100644 index 0000000..a83f8fc --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1828_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1830_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1830_en Binary files differnew file mode 100644 index 0000000..b9dd2bb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1830_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1831_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1831_en Binary files differnew file mode 100644 index 0000000..2706c69 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1831_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1832_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1832_en Binary files differnew file mode 100644 index 0000000..77a8d42 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1832_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1838_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1838_en Binary files differnew file mode 100644 index 0000000..ff902ce --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1838_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1843_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1843_en Binary files differnew file mode 100644 index 0000000..ec90963 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1843_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1845_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1845_en Binary files differnew file mode 100644 index 0000000..7ad004c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1845_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1847_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1847_en Binary files differnew file mode 100644 index 0000000..0531619 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1847_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1848_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1848_en Binary files differnew file mode 100644 index 0000000..ca5aca7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1848_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1850_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1850_en Binary files differnew file mode 100644 index 0000000..4157758 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1850_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1851_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1851_en Binary files differnew file mode 100644 index 0000000..8523ef3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1851_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1856_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1856_en Binary files differnew file mode 100644 index 0000000..d5ce6b3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1856_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1857_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1857_en Binary files differnew file mode 100644 index 0000000..853bf5f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1857_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1858_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1858_en Binary files differnew file mode 100644 index 0000000..d036af8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1858_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1859_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1859_en Binary files differnew file mode 100644 index 0000000..82eae89 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1859_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1860_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1860_en Binary files differnew file mode 100644 index 0000000..24f9897 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1860_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1862_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1862_en Binary files differnew file mode 100644 index 0000000..8442816 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1862_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1863_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1863_en Binary files differnew file mode 100644 index 0000000..37b26a9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1863_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1864_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1864_en Binary files differnew file mode 100644 index 0000000..99aa6db --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1864_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1865_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1865_en Binary files differnew file mode 100644 index 0000000..2fa95f3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1865_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1867_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1867_en Binary files differnew file mode 100644 index 0000000..e390fa5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1867_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1870_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1870_en Binary files differnew file mode 100644 index 0000000..626fe8e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1870_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1872_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1872_en Binary files differnew file mode 100644 index 0000000..e851d4b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1872_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1878_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1878_en Binary files differnew file mode 100644 index 0000000..676f678 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1878_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1888_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1888_en Binary files differnew file mode 100644 index 0000000..47068cb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1888_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1901_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1901_en Binary files differnew file mode 100644 index 0000000..d54c8b4 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1901_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1902_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1902_en Binary files differnew file mode 100644 index 0000000..89897a9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1902_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1903_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1903_en Binary files differnew file mode 100644 index 0000000..86d1f70 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1903_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1904_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1904_en Binary files differnew file mode 100644 index 0000000..ad534ce --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1904_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1905_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1905_en Binary files differnew file mode 100644 index 0000000..a445998 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1905_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1906_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1906_en Binary files differnew file mode 100644 index 0000000..2919ad0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1906_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1907_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1907_en Binary files differnew file mode 100644 index 0000000..04c63e2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1907_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1908_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1908_en Binary files differnew file mode 100644 index 0000000..99c0e32 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1908_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1909_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1909_en Binary files differnew file mode 100644 index 0000000..457e115 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1909_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1910_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1910_en Binary files differnew file mode 100644 index 0000000..11e93fe --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1910_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1912_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1912_en Binary files differnew file mode 100644 index 0000000..30ec7de --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1912_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1913_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1913_en Binary files differnew file mode 100644 index 0000000..0272f76 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1913_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1914_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1914_en Binary files differnew file mode 100644 index 0000000..e19a7bf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1914_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1915_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1915_en Binary files differnew file mode 100644 index 0000000..6adc9ae --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1915_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1916_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1916_en Binary files differnew file mode 100644 index 0000000..766cf63 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1916_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1917_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1917_en Binary files differnew file mode 100644 index 0000000..72c9476 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1917_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1918_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1918_en Binary files differnew file mode 100644 index 0000000..034ceea --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1918_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1919_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1919_en Binary files differnew file mode 100644 index 0000000..66b5a93 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1919_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1920_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1920_en Binary files differnew file mode 100644 index 0000000..5e75d99 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1920_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1925_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1925_en Binary files differnew file mode 100644 index 0000000..defa317 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1925_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1928_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1928_en Binary files differnew file mode 100644 index 0000000..cc06485 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1928_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1931_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1931_en Binary files differnew file mode 100644 index 0000000..2cbd816 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1931_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1936_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1936_en Binary files differnew file mode 100644 index 0000000..c8bdcff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1936_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1937_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1937_en Binary files differnew file mode 100644 index 0000000..2698438 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1937_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1940_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1940_en Binary files differnew file mode 100644 index 0000000..a100c66 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1940_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1941_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1941_en Binary files differnew file mode 100644 index 0000000..30f5f87 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1941_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1947_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1947_en Binary files differnew file mode 100644 index 0000000..314dd69 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1947_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1949_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1949_en Binary files differnew file mode 100644 index 0000000..8dd0dd5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1949_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1951_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1951_en Binary files differnew file mode 100644 index 0000000..9812455 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1951_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1952_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1952_en Binary files differnew file mode 100644 index 0000000..86ddc13 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1952_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1954_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1954_en Binary files differnew file mode 100644 index 0000000..1f79669 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1954_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1956_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1956_en Binary files differnew file mode 100644 index 0000000..cfe7888 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1956_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1970_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1970_en Binary files differnew file mode 100644 index 0000000..4a9fd6c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1970_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1971_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1971_en Binary files differnew file mode 100644 index 0000000..053acd0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1971_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1972_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1972_en Binary files differnew file mode 100644 index 0000000..3335253 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1972_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1973_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1973_en Binary files differnew file mode 100644 index 0000000..d682cc7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1973_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1978_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1978_en Binary files differnew file mode 100644 index 0000000..8f02daf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1978_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1979_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1979_en Binary files differnew file mode 100644 index 0000000..9d9d449 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1979_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1980_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1980_en Binary files differnew file mode 100644 index 0000000..f1d82a3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1980_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1985_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1985_en Binary files differnew file mode 100644 index 0000000..73336d9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1985_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1989_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1989_en Binary files differnew file mode 100644 index 0000000..42db96d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/1989_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/20_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/20_en Binary files differnew file mode 100644 index 0000000..76b227e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/20_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_en Binary files differnew file mode 100644 index 0000000..ad7f944 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_fr Binary files differnew file mode 100644 index 0000000..9016b0d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/212_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/213_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/213_en Binary files differnew file mode 100644 index 0000000..7a1379c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/213_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/216_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/216_en Binary files differnew file mode 100644 index 0000000..9af2d13 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/216_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/220_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/220_en Binary files differnew file mode 100644 index 0000000..29941e6 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/220_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/221_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/221_en Binary files differnew file mode 100644 index 0000000..b876d30 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/221_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_en Binary files differnew file mode 100644 index 0000000..7b4ec36 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_fr Binary files differnew file mode 100644 index 0000000..ceb0870 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/222_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/224_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/224_en Binary files differnew file mode 100644 index 0000000..e63507d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/224_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_en Binary files differnew file mode 100644 index 0000000..e290e50 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_fr Binary files differnew file mode 100644 index 0000000..e290e50 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/225_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/226_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/226_en Binary files differnew file mode 100644 index 0000000..ed31886 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/226_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_en Binary files differnew file mode 100644 index 0000000..192a5d7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_es Binary files differnew file mode 100644 index 0000000..7c124ef --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_fr Binary files differnew file mode 100644 index 0000000..884ca42 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/228_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_en Binary files differnew file mode 100644 index 0000000..21b5b82 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_fr Binary files differnew file mode 100644 index 0000000..6002a86 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/229_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_en Binary files differnew file mode 100644 index 0000000..3cf3259 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_es Binary files differnew file mode 100644 index 0000000..49f2050 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_fr Binary files differnew file mode 100644 index 0000000..bf51072 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/230_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/232_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/232_en Binary files differnew file mode 100644 index 0000000..9cb3996 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/232_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/233_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/233_en Binary files differnew file mode 100644 index 0000000..aca1927 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/233_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_en Binary files differnew file mode 100644 index 0000000..092d85a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_pt Binary files differnew file mode 100644 index 0000000..092d85a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/238_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_en Binary files differnew file mode 100644 index 0000000..37a5e89 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_pt Binary files differnew file mode 100644 index 0000000..8610e0a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/239_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_en Binary files differnew file mode 100644 index 0000000..86c316f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_fr Binary files differnew file mode 100644 index 0000000..2ad2a1a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/242_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_en Binary files differnew file mode 100644 index 0000000..14b51a0 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_fr Binary files differnew file mode 100644 index 0000000..ac48d42 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/243_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_en Binary files differnew file mode 100644 index 0000000..59c00b9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_pt Binary files differnew file mode 100644 index 0000000..34cf12b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/244_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_en Binary files differnew file mode 100644 index 0000000..2738fe8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_pt Binary files differnew file mode 100644 index 0000000..2738fe8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/245_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/247_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/247_en Binary files differnew file mode 100644 index 0000000..259944a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/247_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/249_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/249_en Binary files differnew file mode 100644 index 0000000..d605df8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/249_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/251_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/251_en Binary files differnew file mode 100644 index 0000000..e389d1c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/251_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/252_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/252_en Binary files differnew file mode 100644 index 0000000..241ed68 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/252_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/254_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/254_en Binary files differnew file mode 100644 index 0000000..b21858b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/254_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/256_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/256_en Binary files differnew file mode 100644 index 0000000..6043317 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/256_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_en Binary files differnew file mode 100644 index 0000000..6f11df7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_pt Binary files differnew file mode 100644 index 0000000..18ddf2e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/258_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/260_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/260_en Binary files differnew file mode 100644 index 0000000..b469b16 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/260_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/261_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/261_en Binary files differnew file mode 100644 index 0000000..af8affb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/261_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/263_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/263_en Binary files differnew file mode 100644 index 0000000..7ec8339 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/263_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/264_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/264_en Binary files differnew file mode 100644 index 0000000..ef92fe5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/264_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/266_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/266_en Binary files differnew file mode 100644 index 0000000..3fc9c6f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/266_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/267_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/267_en Binary files differnew file mode 100644 index 0000000..4c52bd2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/267_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/268_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/268_en Binary files differnew file mode 100644 index 0000000..16067ff --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/268_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_en Binary files differnew file mode 100644 index 0000000..bbc053b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_fr Binary files differnew file mode 100644 index 0000000..bbc053b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/269_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/27_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/27_en Binary files differnew file mode 100644 index 0000000..c86a27c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/27_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_en Binary files differnew file mode 100644 index 0000000..b65865d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_fr Binary files differnew file mode 100644 index 0000000..a9df787 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/290_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/299_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/299_en Binary files differnew file mode 100644 index 0000000..2e0fee5 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/299_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_el b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_el Binary files differnew file mode 100644 index 0000000..3ae0b10 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_el diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_en Binary files differnew file mode 100644 index 0000000..8211506 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/30_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_en Binary files differnew file mode 100644 index 0000000..7565cac --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_nl b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_nl Binary files differnew file mode 100644 index 0000000..78768ba --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/31_nl diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_en Binary files differnew file mode 100644 index 0000000..7e9655f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_fr Binary files differnew file mode 100644 index 0000000..85f2c6b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/33_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_en Binary files differnew file mode 100644 index 0000000..3ec6b10 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_es Binary files differnew file mode 100644 index 0000000..749b162 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/34_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_en Binary files differnew file mode 100644 index 0000000..61f0da1 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_pt Binary files differnew file mode 100644 index 0000000..eb08045 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/351_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_de b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_de Binary files differnew file mode 100644 index 0000000..d20ebca --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_de diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_en Binary files differnew file mode 100644 index 0000000..e510e7b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/352_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/354_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/354_en Binary files differnew file mode 100644 index 0000000..2e85aa2 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/354_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/355_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/355_en Binary files differnew file mode 100644 index 0000000..b903bcd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/355_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_en Binary files differnew file mode 100644 index 0000000..3e9c6c3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_fi b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_fi Binary files differnew file mode 100644 index 0000000..3824cfb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_fi diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_se b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_se Binary files differnew file mode 100644 index 0000000..3c49760 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/358_se diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_en Binary files differnew file mode 100644 index 0000000..d9f2a71 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_hu b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_hu Binary files differnew file mode 100644 index 0000000..6eaf151 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/36_hu diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/370_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/370_en Binary files differnew file mode 100644 index 0000000..52b47bd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/370_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/371_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/371_en Binary files differnew file mode 100644 index 0000000..5273f0e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/371_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/372_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/372_en Binary files differnew file mode 100644 index 0000000..aaaa338 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/372_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_en Binary files differnew file mode 100644 index 0000000..9ef1b6e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ro b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ro Binary files differnew file mode 100644 index 0000000..3ef4931 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ro diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ru b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ru Binary files differnew file mode 100644 index 0000000..b643821 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/373_ru diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/374_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/374_en Binary files differnew file mode 100644 index 0000000..8bdf764 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/374_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_en Binary files differnew file mode 100644 index 0000000..8cde57a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_sr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_sr Binary files differnew file mode 100644 index 0000000..2a5deaa --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/381_sr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_en Binary files differnew file mode 100644 index 0000000..fada2f3 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_it b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_it Binary files differnew file mode 100644 index 0000000..db32682 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/39_it diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_de b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_de Binary files differnew file mode 100644 index 0000000..e62c797 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_de diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_en Binary files differnew file mode 100644 index 0000000..79ab086 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_fr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_fr Binary files differnew file mode 100644 index 0000000..6fb2df8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_fr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_it b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_it Binary files differnew file mode 100644 index 0000000..9cc1e5b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/41_it diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/420_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/420_en Binary files differnew file mode 100644 index 0000000..6e39c43 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/420_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/421_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/421_en Binary files differnew file mode 100644 index 0000000..5a5dc09 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/421_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_de b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_de Binary files differnew file mode 100644 index 0000000..5687e97 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_de diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_en Binary files differnew file mode 100644 index 0000000..050418d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/43_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/44_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/44_en Binary files differnew file mode 100644 index 0000000..3a2d306 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/44_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_en Binary files differnew file mode 100644 index 0000000..934bb3e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_sv b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_sv Binary files differnew file mode 100644 index 0000000..31a27a8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/46_sv diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_en Binary files differnew file mode 100644 index 0000000..969da0c --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_pl b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_pl Binary files differnew file mode 100644 index 0000000..cd5eb5a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/48_pl diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_de b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_de Binary files differnew file mode 100644 index 0000000..428b8bf --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_de diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_en Binary files differnew file mode 100644 index 0000000..40b3748 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/49_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/51_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/51_en Binary files differnew file mode 100644 index 0000000..7f84d3e --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/51_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/53_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/53_en Binary files differnew file mode 100644 index 0000000..5d15867 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/53_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_en Binary files differnew file mode 100644 index 0000000..ae2fbdd --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_es Binary files differnew file mode 100644 index 0000000..afd958b --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/54_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_en Binary files differnew file mode 100644 index 0000000..753576a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_pt b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_pt Binary files differnew file mode 100644 index 0000000..753576a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/55_pt diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_en Binary files differnew file mode 100644 index 0000000..9126f78 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_es Binary files differnew file mode 100644 index 0000000..9126f78 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/56_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_en Binary files differnew file mode 100644 index 0000000..9c7a787 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_es b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_es Binary files differnew file mode 100644 index 0000000..8407816 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/58_es diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/7_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/7_en Binary files differnew file mode 100644 index 0000000..7ac3c1d --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/7_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_en Binary files differnew file mode 100644 index 0000000..f9d096f --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_ja b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_ja Binary files differnew file mode 100644 index 0000000..7cc7384 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/81_ja diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_en Binary files differnew file mode 100644 index 0000000..cd18ecb --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_ko b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_ko Binary files differnew file mode 100644 index 0000000..cbc3017 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_ko diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh Binary files differnew file mode 100644 index 0000000..d452ab7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh_Hant b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh_Hant Binary files differnew file mode 100644 index 0000000..a6a9452 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/82_zh_Hant diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_en Binary files differnew file mode 100644 index 0000000..5221729 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_vi b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_vi Binary files differnew file mode 100644 index 0000000..1b0e2d7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/84_vi diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_en Binary files differnew file mode 100644 index 0000000..b5b21b7 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_zh b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_zh Binary files differnew file mode 100644 index 0000000..bbd7660 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/86_zh diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_en Binary files differnew file mode 100644 index 0000000..497c293 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh Binary files differnew file mode 100644 index 0000000..d04e3ab --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh_Hant b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh_Hant Binary files differnew file mode 100644 index 0000000..eb259e9 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/886_zh_Hant diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_en Binary files differnew file mode 100644 index 0000000..a3dfd81 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_tr b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_tr Binary files differnew file mode 100644 index 0000000..cfcf99a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/90_tr diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/94_en b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/94_en Binary files differnew file mode 100644 index 0000000..0794d2a --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/94_en diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/config b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/config Binary files differnew file mode 100644 index 0000000..c7db9c8 --- /dev/null +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/geocoding/data/config diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java new file mode 100644 index 0000000..64171ac --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java @@ -0,0 +1,867 @@ +/* + * 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 junit.framework.TestCase; + +/** + * Unit tests for AsYouTypeFormatter.java + * + * Note that these tests use the metadata contained in the files with TEST_META_DATA_FILE_PREFIX, + * not the normal metadata files, so should not be used for regression test purposes - these tests + * are illustrative only and test functionality. + * + * @author Shaopeng Jia + */ +public class AsYouTypeFormatterTest extends TestCase { + private PhoneNumberUtil phoneUtil; + + public AsYouTypeFormatterTest() { + phoneUtil = PhoneNumberUtilTest.initializePhoneUtilForTesting(); + } + + 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')); + } + + 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 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')); + + // +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("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("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("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("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')); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java new file mode 100644 index 0000000..6d7417d --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java @@ -0,0 +1,109 @@ +/* + * 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 21 as there are 16 different country codes, + // and this offers a load factor of roughly 0.75. + Map<Integer, List<String>> countryCodeToRegionCodeMap = + new HashMap<Integer, List<String>>(21); + + ArrayList<String> listWithRegionCode; + + listWithRegionCode = new ArrayList<String>(2); + listWithRegionCode.add("US"); + listWithRegionCode.add("BS"); + countryCodeToRegionCodeMap.put(1, listWithRegionCode); + + listWithRegionCode = new ArrayList<String>(1); + listWithRegionCode.add("IT"); + countryCodeToRegionCodeMap.put(39, listWithRegionCode); + + listWithRegionCode = new ArrayList<String>(1); + listWithRegionCode.add("GB"); + 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>(1); + listWithRegionCode.add("AU"); + 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("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("AD"); + countryCodeToRegionCodeMap.put(376, listWithRegionCode); + + return countryCodeToRegionCodeMap; + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java new file mode 100644 index 0000000..7c30588 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java @@ -0,0 +1,176 @@ +/* + * 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; + +/** + * @author Lara Rennie + * + * 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; + private List<PhoneNumber> invalidCases = new ArrayList<PhoneNumber>(); + private List<PhoneNumber> wrongTypeCases = new ArrayList<PhoneNumber>(); + + public ExampleNumbersTest() { + PhoneNumberUtil.resetInstance(); + phoneNumberUtil = PhoneNumberUtil.getInstance(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + invalidCases.clear(); + wrongTypeCases.clear(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + /** + * @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 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); + } + } + assertEquals(0, wrongTypeCases.size()); + } + + public void testEveryRegionHasAnExampleNumber() throws Exception { + for (String regionCode : phoneNumberUtil.getSupportedRegions()) { + PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumber(regionCode); + assertNotNull("None found for region " + regionCode, exampleNumber); + } + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java new file mode 100644 index 0000000..899fc94 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatchTest.java @@ -0,0 +1,72 @@ +/* + * 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}. + * + * @author Tom Hofmann + */ +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/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java new file mode 100644 index 0000000..c23181d --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberMatcherTest.java @@ -0,0 +1,935 @@ +/* + * 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 junit.framework.TestCase; + +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. + * + * @author Tom Hofmann + * @see PhoneNumberUtilTest {@link PhoneNumberUtilTest} for the origin of the test data + */ +public class PhoneNumberMatcherTest extends TestCase { + private PhoneNumberUtil phoneUtil; + + @Override + protected void setUp() throws Exception { + phoneUtil = PhoneNumberUtilTest.initializePhoneUtilForTesting(); + } + + /** 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. + doTestFindInContext("123/45678", RegionCode.DE); + 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 testMatchWithSurroundingZipcodes() throws Exception { + String number = "415-666-7777"; + String zipPreceding = "My address is CA 34215 - " + number + " is my number."; + PhoneNumber expectedResult = phoneUtil.parse(number, RegionCode.US); + + Iterator<PhoneNumberMatch> iterator = + phoneUtil.findNumbers(zipPreceding, RegionCode.US).iterator(); + PhoneNumberMatch match = iterator.hasNext() ? iterator.next() : null; + assertNotNull("Did not find a number in '" + zipPreceding + "'; expected " + number, match); + assertEquals(expectedResult, match.number()); + assertEquals(number, match.rawString()); + + // 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; + assertNotNull("Did not find a number in '" + zipFollowing + "'; expected " + number, + matchWithSpaces); + assertEquals(expectedResult, matchWithSpaces.number()); + assertEquals(number, matchWithSpaces.rawString()); + } + + 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 + } + + 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 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), + }; + + /** + * Strings with number-like things that should only be found under "possible". + */ + private static final NumberTest[] POSSIBLE_ONLY_CASES = { + new NumberTest("abc8002345678", RegionCode.US), + // US numbers cannot start with 7 in the test metadata to be valid. + new NumberTest("7121115678", RegionCode.US), + // 'X' should not be found in numbers at leniencies stricter than POSSIBLE, unless it represents + // a carrier code or extension. + new NumberTest("1650 x 253 - 1234", RegionCode.US), + new NumberTest("650 x 253 - 1234", RegionCode.US), + new NumberTest("650x2531234", RegionCode.US), + new NumberTest("(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("21 7/8 - 14 12/34 - 5", RegionCode.US), + new NumberTest("12.1 - 23.71 - 23.45", RegionCode.US), + new NumberTest("1979-2011 100%", RegionCode.US), + new NumberTest("800 234 1 111x1111", RegionCode.US), + new NumberTest("+494949-4-94", RegionCode.DE), // National number in wrong format + new NumberTest("\uFF14\uFF11\uFF15\uFF16\uFF16\uFF16\uFF16-\uFF17\uFF17\uFF17\uFF17", + RegionCode.US), + }; + + /** + * 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), + }; + + /** + * Strings with number-like things that should 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 + }; + + 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, + PhoneNumberUtil.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, + PhoneNumberUtil.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 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 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 21 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, PhoneNumberUtil.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/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java new file mode 100644 index 0000000..e7038c6 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java @@ -0,0 +1,1968 @@ +/* + * 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 junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Unit tests for PhoneNumberUtil.java + * + * Note that these tests use the metadata contained in the files with TEST_META_DATA_FILE_PREFIX, + * not the normal metadata files, so should not be used for regression test purposes - these tests + * are illustrative only and test functionality. + * + * @author Shaopeng Jia + * @author Lara Rennie + */ +public class PhoneNumberUtilTest extends TestCase { + private PhoneNumberUtil phoneUtil; + // This is used by BuildMetadataProtoFromXml. + static final String TEST_META_DATA_FILE_PREFIX = + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting"; + + // Set up some test numbers to re-use. + private static final PhoneNumber ALPHA_NUMERIC_NUMBER = + new PhoneNumber().setCountryCode(1).setNationalNumber(80074935247L); + 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); + // 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"); + + public PhoneNumberUtilTest() { + phoneUtil = initializePhoneUtilForTesting(); + } + + static PhoneNumberUtil initializePhoneUtilForTesting() { + PhoneNumberUtil.resetInstance(); + return PhoneNumberUtil.getInstance( + TEST_META_DATA_FILE_PREFIX, + CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap()); + } + + public void testGetSupportedRegions() { + assertTrue(phoneUtil.getSupportedRegions().size() > 0); + } + + public void testGetInstanceLoadUSMetadata() { + PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US); + assertEquals(RegionCode.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(RegionCode.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(RegionCode.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 testIsLeadingZeroPossible() { + assertTrue(phoneUtil.isLeadingZeroPossible(39)); // Italy + assertFalse(phoneUtil.isLeadingZeroPossible(1)); // USA + assertFalse(phoneUtil.isLeadingZeroPossible(800)); // 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)); + + // 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)); + } + + 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)); + } + + 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)); + } + + 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)); + } + + 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&+#234"; + 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 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("+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("+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)); + + 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, "AQ")); + } + + 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 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)); + } + + 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")); + } + + 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() { + // US toll free numbers are marked as noInternationalDialling in the test metadata for testing + // purposes. + assertEquals("800 253 0000", + phoneUtil.formatNumberForMobileDialing(US_TOLLFREE, RegionCode.US, true)); + 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)); + 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)); + } + + 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)); + + // $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)); + } + + 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("+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 testFormatUsingOriginalNumberFormat() 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 should be formatted using its raw input when that is available. Note area + // codes starting with 7 are intentionally excluded in the test metadata for testing purposes. + PhoneNumber number6 = phoneUtil.parseAndKeepRawInput("7345678901", RegionCode.US); + assertEquals("7345678901", phoneUtil.formatInOriginalFormat(number6, RegionCode.US)); + + // When the raw input is unavailable, format as usual. + PhoneNumber number7 = phoneUtil.parse("7345678901", RegionCode.US); + assertEquals("734 567 8901", phoneUtil.formatInOriginalFormat(number7, 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)); + } + + 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)); + } + + 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)); + + 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)); + } + + 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)); + } + + public void testGetRegionCodeForCountryCode() { + assertEquals(RegionCode.US, phoneUtil.getRegionCodeForCountryCode(1)); + assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForCountryCode(44)); + assertEquals(RegionCode.DE, phoneUtil.getRegionCodeForCountryCode(49)); + } + + public void testGetRegionCodeForNumber() { + assertEquals(RegionCode.BS, phoneUtil.getRegionCodeForNumber(BS_NUMBER)); + assertEquals(RegionCode.US, phoneUtil.getRegionCodeForNumber(US_NUMBER)); + assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForNumber(GB_MOBILE)); + } + + 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)); + // 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)); + // 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(null)); + } + + public void testIsPossibleNumber() { + assertTrue(phoneUtil.isPossibleNumber(US_NUMBER)); + assertTrue(phoneUtil.isPossibleNumber(US_LOCAL_NUMBER)); + assertTrue(phoneUtil.isPossibleNumber(GB_NUMBER)); + + 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)); + } + + 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)); + + // Try with number that we don't have metadata for. + PhoneNumber adNumber = new PhoneNumber(); + adNumber.setCountryCode(376).setNationalNumber(12345L); + assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE, + phoneUtil.isPossibleNumberWithReason(adNumber)); + adNumber.setCountryCode(376).setNationalNumber(13L); + assertEquals(PhoneNumberUtil.ValidationResult.TOO_SHORT, + phoneUtil.isPossibleNumberWithReason(adNumber)); + adNumber.setCountryCode(376).setNationalNumber(12345678901234567L); + assertEquals(PhoneNumberUtil.ValidationResult.TOO_LONG, + phoneUtil.isPossibleNumberWithReason(adNumber)); + } + + public void testIsNotPossibleNumber() { + assertFalse(phoneUtil.isPossibleNumber(US_LONG_NUMBER)); + + 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)); + } + + public void testTruncateTooLongNumber() { + // US number 650-253-0000, but entered with one additional digit at the end. + assertTrue(phoneUtil.truncateTooLongNumber(US_LONG_NUMBER)); + assertEquals(US_NUMBER, US_LONG_NUMBER); + + // GB number 080 1234 5678, but entered with 4 extra digits at the end. + PhoneNumber tooLongNumber = new PhoneNumber(); + tooLongNumber.setCountryCode(44).setNationalNumber(80123456780123L); + 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); + + // 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() { + // Only one or two digits before strange non-possible punctuation. + assertFalse(PhoneNumberUtil.isViablePhoneNumber("12. March")); + assertFalse(PhoneNumberUtil.isViablePhoneNumber("1+1+1")); + assertFalse(PhoneNumberUtil.isViablePhoneNumber("80+0")); + assertFalse(PhoneNumberUtil.isViablePhoneNumber("00")); + // Three digits is viable. + assertTrue(PhoneNumberUtil.isViablePhoneNumber("111")); + // Alpha numbers. + assertTrue(PhoneNumberUtil.isViablePhoneNumber("0800-4-pizza")); + assertTrue(PhoneNumberUtil.isViablePhoneNumber("0800-4-PIZZA")); + } + + 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 = "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)); + + // 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)); + + 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)); + } + + 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 testParseWithInternationalPrefixes() throws Exception { + assertEquals(US_NUMBER, phoneUtil.parse("+1 (650) 253-0000", RegionCode.NZ)); + 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)); + // 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 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 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."); + } + } + + 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)); + + // 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 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)); + + 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 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)); + assertTrue(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 testUnknownCountryCallingCodeForValidation() { + PhoneNumber invalidNumber = new PhoneNumber(); + invalidNumber.setCountryCode(0).setNationalNumber(1234L); + assertFalse(phoneUtil.isValidNumber(invalidNumber)); + } + + public void testIsNumberMatchMatches() throws Exception { + // Test simple matches where formatting is different, or leading zeroes, 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("+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")); + // 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")); + // 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")); + // 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("43", "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(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")); + // 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", "+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)); + } + + public void testIsAlphaNumber() throws Exception { + assertTrue(phoneUtil.isAlphaNumber("1800 six-flags")); + assertTrue(phoneUtil.isAlphaNumber("1800 six-flags ext. 1234")); + assertFalse(phoneUtil.isAlphaNumber("1800 123-1234")); + assertFalse(phoneUtil.isAlphaNumber("1800 123-1234 extension: 1234")); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhonenumberTest.java new file mode 100644 index 0000000..466a0e3 --- /dev/null +++ b/java/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/java/libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegexCacheTest.java new file mode 100644 index 0000000..a2839d3 --- /dev/null +++ b/java/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/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java new file mode 100644 index 0000000..36e44e5 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java @@ -0,0 +1,47 @@ +/* + * 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 { + static final String AD = "AD"; + static final String AO = "AO"; + static final String AR = "AR"; + static final String AU = "AU"; + static final String BR = "BR"; + static final String BS = "BS"; + static final String CA = "CA"; + static final String CN = "CN"; + static final String CS = "CS"; + static final String DE = "DE"; + static final String GB = "GB"; + 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 PL = "PL"; + static final String RE = "RE"; + 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/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java new file mode 100644 index 0000000..20644d2 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java @@ -0,0 +1,148 @@ +/* + * 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; + +import java.io.InputStream; + +/** + * Unit tests for ShortNumberUtil.java + * + * @author Shaopeng Jia + */ +public class ShortNumberUtilTest extends TestCase { + private ShortNumberUtil shortUtil; + static final String TEST_META_DATA_FILE_PREFIX = + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting"; + + public ShortNumberUtilTest() { + PhoneNumberUtil.resetInstance(); + PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance( + TEST_META_DATA_FILE_PREFIX, + CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap()); + shortUtil = new ShortNumberUtil(phoneUtil); + } + + public void testConnectsToEmergencyNumber_US() { + assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.US)); + assertTrue(shortUtil.connectsToEmergencyNumber("119", RegionCode.US)); + assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.US)); + } + + public void testConnectsToEmergencyNumberLongNumber_US() { + assertTrue(shortUtil.connectsToEmergencyNumber("9116666666", RegionCode.US)); + assertTrue(shortUtil.connectsToEmergencyNumber("1196666666", 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-9", 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("+119", 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("119", RegionCode.US)); + assertFalse(shortUtil.isEmergencyNumber("999", RegionCode.US)); + } + + public void testIsEmergencyNumberLongNumber_US() { + assertFalse(shortUtil.isEmergencyNumber("9116666666", RegionCode.US)); + assertFalse(shortUtil.isEmergencyNumber("1196666666", 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-9", RegionCode.US)); + assertTrue(shortUtil.isEmergencyNumber("*119", 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("+119", 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/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig new file mode 100644 index 0000000..b1ae29b --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberUtilTest.java.orig @@ -0,0 +1,76 @@ +/* + * 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; + +import java.io.InputStream; + +/** + * @author Shaopeng Jia + */ +public class ShortNumberUtilTest extends TestCase { + private ShortNumberUtil shortUtil; + static final String TEST_META_DATA_FILE_PREFIX = + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting"; + + public ShortNumberUtilTest() { + PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance( + TEST_META_DATA_FILE_PREFIX, + CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap()); + shortUtil = new ShortNumberUtil(phoneUtil); + } + + public void testConnectsToEmergencyNumber_US() { + assertTrue(shortUtil.connectsToEmergencyNumber("911", RegionCode.US)); + assertTrue(shortUtil.connectsToEmergencyNumber("119", RegionCode.US)); + assertFalse(shortUtil.connectsToEmergencyNumber("999", RegionCode.US)); + } + + public void testConnectsToEmergencyNumberLongNumber_US() { + assertTrue(shortUtil.connectsToEmergencyNumber("9116666666", RegionCode.US)); + assertTrue(shortUtil.connectsToEmergencyNumber("1196666666", 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-9", 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("+119", 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)); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD Binary files differnew file mode 100644 index 0000000..8dba7fa --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AD diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO Binary files differnew file mode 100644 index 0000000..44b042e --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AO diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR Binary files differnew file mode 100644 index 0000000..549bc8b --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AR diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU Binary files differnew file mode 100644 index 0000000..b3ee483 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_AU diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR Binary files differnew file mode 100644 index 0000000..fc33520 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BR diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS Binary files differnew file mode 100644 index 0000000..7ec5aa3 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_BS diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE Binary files differnew file mode 100644 index 0000000..42d58fe --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_DE diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB Binary files differnew file mode 100644 index 0000000..171bbc0 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_GB diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT Binary files differnew file mode 100644 index 0000000..be4d9c1 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_IT diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP Binary files differnew file mode 100644 index 0000000..1dbb2b1 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_JP diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR Binary files differnew file mode 100644 index 0000000..21c764e --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_KR diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX Binary files differnew file mode 100644 index 0000000..854f020 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_MX diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ Binary files differnew file mode 100644 index 0000000..d3b27a6 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_NZ diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL Binary files differnew file mode 100644 index 0000000..9b082df --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_PL diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE Binary files differnew file mode 100644 index 0000000..02b38fa --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_RE diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG Binary files differnew file mode 100644 index 0000000..c5df8dc --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SG diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US Binary files differnew file mode 100644 index 0000000..cf65f6a --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_US diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT Binary files differnew file mode 100644 index 0000000..ecee4a4 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_YT diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/AreaCodeMapTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/AreaCodeMapTest.java new file mode 100644 index 0000000..84ec90d --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/AreaCodeMapTest.java @@ -0,0 +1,192 @@ +/* + * 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.geocoding; + +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Unittests for AreaCodeMap.java + * + * @author Shaopeng Jia + */ +public class AreaCodeMapTest extends TestCase { + private final AreaCodeMap areaCodeMapForUS = new AreaCodeMap(); + private final AreaCodeMap areaCodeMapForIT = new AreaCodeMap(); + private PhoneNumber number = new PhoneNumber(); + + public AreaCodeMapTest() { + SortedMap<Integer, String> sortedMapForUS = new TreeMap<Integer, String>(); + sortedMapForUS.put(1212, "New York"); + sortedMapForUS.put(1480, "Arizona"); + sortedMapForUS.put(1650, "California"); + sortedMapForUS.put(1907, "Alaska"); + sortedMapForUS.put(1201664, "Westwood, NJ"); + sortedMapForUS.put(1480893, "Phoenix, AZ"); + sortedMapForUS.put(1501372, "Little Rock, AR"); + sortedMapForUS.put(1626308, "Alhambra, CA"); + sortedMapForUS.put(1650345, "San Mateo, CA"); + sortedMapForUS.put(1867993, "Dawson, YT"); + sortedMapForUS.put(1972480, "Richardson, TX"); + + areaCodeMapForUS.readAreaCodeMap(sortedMapForUS); + + SortedMap<Integer, String> sortedMapForIT = new TreeMap<Integer, String>(); + sortedMapForIT.put(3902, "Milan"); + sortedMapForIT.put(3906, "Rome"); + sortedMapForIT.put(39010, "Genoa"); + sortedMapForIT.put(390131, "Alessandria"); + sortedMapForIT.put(390321, "Novara"); + sortedMapForIT.put(390975, "Potenza"); + + areaCodeMapForIT.readAreaCodeMap(sortedMapForIT); + } + + private static SortedMap<Integer, String> createDefaultStorageMapCandidate() { + SortedMap<Integer, String> sortedMap = new TreeMap<Integer, String>(); + // Make the area codes bigger to store them using integer. + sortedMap.put(121212345, "New York"); + sortedMap.put(148034434, "Arizona"); + return sortedMap; + } + + private static SortedMap<Integer, String> createFlyweightStorageMapCandidate() { + SortedMap<Integer, String> sortedMap = new TreeMap<Integer, String>(); + sortedMap.put(1212, "New York"); + sortedMap.put(1213, "New York"); + sortedMap.put(1214, "New York"); + sortedMap.put(1480, "Arizona"); + return sortedMap; + } + + public void testGetSmallerMapStorageChoosesDefaultImpl() { + AreaCodeMapStorageStrategy mapStorage = + new AreaCodeMap().getSmallerMapStorage(createDefaultStorageMapCandidate()); + assertFalse(mapStorage instanceof FlyweightMapStorage); + } + + public void testGetSmallerMapStorageChoosesFlyweightImpl() { + AreaCodeMapStorageStrategy mapStorage = + new AreaCodeMap().getSmallerMapStorage(createFlyweightStorageMapCandidate()); + assertTrue(mapStorage instanceof FlyweightMapStorage); + } + + public void testLookupInvalidNumber_US() { + // central office code cannot start with 1. + number.setCountryCode(1).setNationalNumber(2121234567L); + assertEquals("New York", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_NJ() { + number.setCountryCode(1).setNationalNumber(2016641234L); + assertEquals("Westwood, NJ", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_NY() { + number.setCountryCode(1).setNationalNumber(2126641234L); + assertEquals("New York", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_CA_1() { + number.setCountryCode(1).setNationalNumber(6503451234L); + assertEquals("San Mateo, CA", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_CA_2() { + number.setCountryCode(1).setNationalNumber(6502531234L); + assertEquals("California", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumberFound_TX() { + number.setCountryCode(1).setNationalNumber(9724801234L); + assertEquals("Richardson, TX", areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumberNotFound_TX() { + number.setCountryCode(1).setNationalNumber(9724811234L); + assertNull(areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_CH() { + number.setCountryCode(41).setNationalNumber(446681300L); + assertNull(areaCodeMapForUS.lookup(number)); + } + + public void testLookupNumber_IT() { + number.setCountryCode(39).setNationalNumber(212345678L).setItalianLeadingZero(true); + assertEquals("Milan", areaCodeMapForIT.lookup(number)); + + number.setNationalNumber(612345678L); + assertEquals("Rome", areaCodeMapForIT.lookup(number)); + + number.setNationalNumber(3211234L); + assertEquals("Novara", areaCodeMapForIT.lookup(number)); + + // A mobile number + number.setNationalNumber(321123456L).setItalianLeadingZero(false); + assertNull(areaCodeMapForIT.lookup(number)); + + // An invalid number (too short) + number.setNationalNumber(321123L).setItalianLeadingZero(true); + assertEquals("Novara", areaCodeMapForIT.lookup(number)); + } + + /** + * Creates a new area code map serializing the provided area code map to a stream and then reading + * this stream. The resulting area code map is expected to be strictly equal to the provided one + * from which it was generated. + */ + private static AreaCodeMap createNewAreaCodeMap(AreaCodeMap areaCodeMap) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + areaCodeMap.writeExternal(objectOutputStream); + objectOutputStream.flush(); + + AreaCodeMap newAreaCodeMap = new AreaCodeMap(); + newAreaCodeMap.readExternal( + new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()))); + return newAreaCodeMap; + } + + public void testReadWriteExternalWithDefaultStrategy() throws IOException { + AreaCodeMap localAreaCodeMap = new AreaCodeMap(); + localAreaCodeMap.readAreaCodeMap(createDefaultStorageMapCandidate()); + assertFalse(localAreaCodeMap.getAreaCodeMapStorage() instanceof FlyweightMapStorage); + + AreaCodeMap newAreaCodeMap; + newAreaCodeMap = createNewAreaCodeMap(localAreaCodeMap); + assertEquals(localAreaCodeMap.toString(), newAreaCodeMap.toString()); + } + + public void testReadWriteExternalWithFlyweightStrategy() throws IOException { + AreaCodeMap localAreaCodeMap = new AreaCodeMap(); + localAreaCodeMap.readAreaCodeMap(createFlyweightStorageMapCandidate()); + assertTrue(localAreaCodeMap.getAreaCodeMapStorage() instanceof FlyweightMapStorage); + + AreaCodeMap newAreaCodeMap; + newAreaCodeMap = createNewAreaCodeMap(localAreaCodeMap); + assertEquals(localAreaCodeMap.toString(), newAreaCodeMap.toString()); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorageTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorageTest.java new file mode 100644 index 0000000..3db1264 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/FlyweightMapStorageTest.java @@ -0,0 +1,107 @@ +/* + * 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.geocoding; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collections; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Unittests for FlyweightMapStorage.java + * + * @author Philippe Liard + */ +public class FlyweightMapStorageTest extends TestCase { + private static final SortedMap<Integer, String> areaCodeMap; + static { + SortedMap<Integer, String> tmpMap = new TreeMap<Integer, String>(); + tmpMap.put(331402, "Paris"); + tmpMap.put(331434, "Paris"); + tmpMap.put(334910, "Marseille"); + tmpMap.put(334911, "Marseille"); + tmpMap.put(334912, ""); + tmpMap.put(334913, ""); + areaCodeMap = Collections.unmodifiableSortedMap(tmpMap); + } + + private FlyweightMapStorage mapStorage; + + @Override + protected void setUp() throws Exception { + mapStorage = new FlyweightMapStorage(); + mapStorage.readFromSortedMap(areaCodeMap); + } + + public void testReadFromSortedMap() { + assertEquals(331402, mapStorage.getPrefix(0)); + assertEquals(331434, mapStorage.getPrefix(1)); + assertEquals(334910, mapStorage.getPrefix(2)); + assertEquals(334911, mapStorage.getPrefix(3)); + + assertEquals("Paris", mapStorage.getDescription(0)); + assertSame(mapStorage.getDescription(0), mapStorage.getDescription(1)); + + assertEquals("Marseille", mapStorage.getDescription(2)); + assertSame(mapStorage.getDescription(2), mapStorage.getDescription(3)); + } + + public void testReadFromSortedMapSupportsEmptyDescription() { + assertEquals(334912, mapStorage.getPrefix(4)); + assertEquals(334913, mapStorage.getPrefix(5)); + + assertEquals("", mapStorage.getDescription(4)); + assertSame(mapStorage.getDescription(4), mapStorage.getDescription(5)); + } + + public void testWriteAndReadExternal() throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + mapStorage.writeExternal(objectOutputStream); + objectOutputStream.flush(); + + FlyweightMapStorage newMapStorage = new FlyweightMapStorage(); + ObjectInputStream objectInputStream = + new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); + newMapStorage.readExternal(objectInputStream); + + String expected = mapStorage.toString(); + assertEquals(expected, newMapStorage.toString()); + } + + public void testReadExternalThrowsIOExceptionWithMalformedData() throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + objectOutputStream.writeUTF("hello"); + objectOutputStream.flush(); + ObjectInputStream objectInputStream = + new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); + FlyweightMapStorage newMapStorage = new FlyweightMapStorage(); + try { + newMapStorage.readExternal(objectInputStream); + fail(); + } catch (IOException e) { + // Exception expected. + } + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/MappingFileProviderTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/MappingFileProviderTest.java new file mode 100644 index 0000000..c426189 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/MappingFileProviderTest.java @@ -0,0 +1,93 @@ +/* + * 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.geocoding; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Unittests for MappingFileProvider.java + * + * @author Shaopeng Jia + */ +public class MappingFileProviderTest extends TestCase { + private final MappingFileProvider mappingProvider = new MappingFileProvider(); + private static final Logger LOGGER = Logger.getLogger(MappingFileProviderTest.class.getName()); + + public MappingFileProviderTest() { + SortedMap<Integer, Set<String>> mapping = new TreeMap<Integer, Set<String>>(); + mapping.put(1, newHashSet("en")); + mapping.put(86, newHashSet("zh", "en", "zh_Hant")); + mapping.put(41, newHashSet("de", "fr", "it", "rm")); + mapping.put(65, newHashSet("en", "zh_Hans", "ms", "ta")); + + mappingProvider.readFileConfigs(mapping); + } + + private static HashSet<String> newHashSet(String... strings) { + HashSet<String> set = new HashSet<String>(); + set.addAll(Arrays.asList(strings)); + return set; + } + + public void testReadWriteExternal() { + try { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + mappingProvider.writeExternal(objectOutputStream); + objectOutputStream.flush(); + + MappingFileProvider newMappingProvider = new MappingFileProvider(); + newMappingProvider.readExternal( + new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()))); + assertEquals(mappingProvider.toString(), newMappingProvider.toString()); + } catch (IOException e) { + LOGGER.log(Level.SEVERE, e.getMessage()); + fail(); + } + } + + public void testGetFileName() { + assertEquals("1_en", mappingProvider.getFileName(1, "en", "", "")); + assertEquals("1_en", mappingProvider.getFileName(1, "en", "", "US")); + assertEquals("1_en", mappingProvider.getFileName(1, "en", "", "GB")); + assertEquals("41_de", mappingProvider.getFileName(41, "de", "", "CH")); + assertEquals("", mappingProvider.getFileName(44, "en", "", "GB")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "", "")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "Hans", "")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "", "CN")); + assertEquals("", mappingProvider.getFileName(86, "", "", "CN")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "Hans", "CN")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "Hans", "SG")); + assertEquals("86_zh", mappingProvider.getFileName(86, "zh", "", "SG")); + assertEquals("86_zh_Hant", mappingProvider.getFileName(86, "zh", "", "TW")); + assertEquals("86_zh_Hant", mappingProvider.getFileName(86, "zh", "", "HK")); + assertEquals("86_zh_Hant", mappingProvider.getFileName(86, "zh", "Hant", "TW")); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoderTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoderTest.java new file mode 100644 index 0000000..e8488e4 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoderTest.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.geocoding; + +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import junit.framework.TestCase; + +import java.util.Locale; + +/** + * Unit tests for PhoneNumberOfflineGeocoder.java + * + * @author Shaopeng Jia + */ +public class PhoneNumberOfflineGeocoderTest extends TestCase { + private final PhoneNumberOfflineGeocoder geocoder = + new PhoneNumberOfflineGeocoder(TEST_MAPPING_DATA_DIRECTORY); + private static final String TEST_MAPPING_DATA_DIRECTORY = + "/com/google/i18n/phonenumbers/geocoding/testing_data/"; + + // Set up some test numbers to re-use. + private static final PhoneNumber KO_NUMBER1 = + new PhoneNumber().setCountryCode(82).setNationalNumber(22123456L); + private static final PhoneNumber KO_NUMBER2 = + new PhoneNumber().setCountryCode(82).setNationalNumber(322123456L); + private static final PhoneNumber KO_NUMBER3 = + new PhoneNumber().setCountryCode(82).setNationalNumber(6421234567L); + private static final PhoneNumber KO_INVALID_NUMBER = + new PhoneNumber().setCountryCode(82).setNationalNumber(1234L); + private static final PhoneNumber US_NUMBER1 = + new PhoneNumber().setCountryCode(1).setNationalNumber(6502530000L); + private static final PhoneNumber US_NUMBER2 = + new PhoneNumber().setCountryCode(1).setNationalNumber(6509600000L); + private static final PhoneNumber US_NUMBER3 = + new PhoneNumber().setCountryCode(1).setNationalNumber(2128120000L); + private static final PhoneNumber US_NUMBER4 = + new PhoneNumber().setCountryCode(1).setNationalNumber(6174240000L); + private static final PhoneNumber US_INVALID_NUMBER = + new PhoneNumber().setCountryCode(1).setNationalNumber(123456789L); + private static final PhoneNumber BS_NUMBER1 = + new PhoneNumber().setCountryCode(1).setNationalNumber(2423651234L); + private static final PhoneNumber AU_NUMBER = + new PhoneNumber().setCountryCode(61).setNationalNumber(236618300L); + private static final PhoneNumber NUMBER_WITH_INVALID_COUNTRY_CODE = + new PhoneNumber().setCountryCode(999).setNationalNumber(2423651234L); + + public void testGetDescriptionForNumberWithNoDataFile() { + // No data file containing mappings for US numbers is available in Chinese for the unittests. As + // a result, the country name of United States in simplified Chinese is returned. + assertEquals("\u7F8E\u56FD", + geocoder.getDescriptionForNumber(US_NUMBER1, Locale.SIMPLIFIED_CHINESE)); + assertEquals("Bahamas", + geocoder.getDescriptionForNumber(BS_NUMBER1, new Locale("en", "US"))); + assertEquals("Australia", + geocoder.getDescriptionForNumber(AU_NUMBER, new Locale("en", "US"))); + assertEquals("", geocoder.getDescriptionForNumber(NUMBER_WITH_INVALID_COUNTRY_CODE, + new Locale("en", "US"))); + } + + public void testGetDescriptionForNumberWithMissingPrefix() { + // Test that the name of the country is returned when the number passed in is valid but not + // covered by the geocoding data file. + assertEquals("United States", + geocoder.getDescriptionForNumber(US_NUMBER4, new Locale("en", "US"))); + } + + public void testGetDescriptionForNumber_en_US() { + assertEquals("CA", + geocoder.getDescriptionForNumber(US_NUMBER1, new Locale("en", "US"))); + assertEquals("Mountain View, CA", + geocoder.getDescriptionForNumber(US_NUMBER2, new Locale("en", "US"))); + assertEquals("New York, NY", + geocoder.getDescriptionForNumber(US_NUMBER3, new Locale("en", "US"))); + } + + public void testGetDescriptionForKoreanNumber() { + assertEquals("Seoul", + geocoder.getDescriptionForNumber(KO_NUMBER1, Locale.ENGLISH)); + assertEquals("Incheon", + geocoder.getDescriptionForNumber(KO_NUMBER2, Locale.ENGLISH)); + assertEquals("Jeju", + geocoder.getDescriptionForNumber(KO_NUMBER3, Locale.ENGLISH)); + assertEquals("\uC11C\uC6B8", + geocoder.getDescriptionForNumber(KO_NUMBER1, Locale.KOREAN)); + assertEquals("\uC778\uCC9C", + geocoder.getDescriptionForNumber(KO_NUMBER2, Locale.KOREAN)); + } + + public void testGetDescriptionForFallBack() { + // No fallback, as the location name for the given phone number is available in the requested + // language. + assertEquals("Kalifornien", + geocoder.getDescriptionForNumber(US_NUMBER1, Locale.GERMAN)); + // German falls back to English. + assertEquals("New York, NY", + geocoder.getDescriptionForNumber(US_NUMBER3, Locale.GERMAN)); + // Italian falls back to English. + assertEquals("CA", + geocoder.getDescriptionForNumber(US_NUMBER1, Locale.ITALIAN)); + // Korean doesn't fall back to English. + assertEquals("\uB300\uD55C\uBBFC\uAD6D", + geocoder.getDescriptionForNumber(KO_NUMBER3, Locale.KOREAN)); + } + + public void testGetDescriptionForInvalidNumber() { + assertEquals("", geocoder.getDescriptionForNumber(KO_INVALID_NUMBER, Locale.ENGLISH)); + assertEquals("", geocoder.getDescriptionForNumber(US_INVALID_NUMBER, Locale.ENGLISH)); + } +} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_de b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_de Binary files differnew file mode 100644 index 0000000..2a516e0 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_de diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_en Binary files differnew file mode 100644 index 0000000..9af68fa --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1201_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1212_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1212_en Binary files differnew file mode 100644 index 0000000..0c3d5d8 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1212_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1617_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1617_en Binary files differnew file mode 100644 index 0000000..b4f7c1d --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1617_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_de b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_de Binary files differnew file mode 100644 index 0000000..1fa2f0f --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_de diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_en Binary files differnew file mode 100644 index 0000000..a95364e --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1650_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1989_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1989_en Binary files differnew file mode 100644 index 0000000..40d8716 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/1989_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_en b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_en Binary files differnew file mode 100644 index 0000000..cd18ecb --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_en diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_ko b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_ko Binary files differnew file mode 100644 index 0000000..dfa91c3 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/82_ko diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/config b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/config Binary files differnew file mode 100644 index 0000000..aab8c13 --- /dev/null +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/geocoding/testing_data/config |