Initial checkin of third party libphonenumber lib.
Change-Id: I73f58bb0e28eed413db0cb23257e534bfbd9db59
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..3df1f92
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# 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.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := protobuf
+
+LOCAL_SRC_FILES := java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java \
+ java/src/com/google/i18n/phonenumbers/NumberParseException.java \
+ java/src/com/google/i18n/phonenumbers/Phonemetadata.java \
+ java/src/com/google/i18n/phonenumbers/Phonenumber.java \
+ java/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
+
+LOCAL_JAVA_RESOURCE_DIRS := java/resources/com/google/i18n/phonenumbers/src/generated_files
+
+LOCAL_MODULE := libphonenumber
+
+LOCAL_JAVA_LIBRARIES := guava
+include $(BUILD_JAVA_LIBRARY)
+#################################
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := protobuf:java/lib/protobuf-lite.jar
+include $(BUILD_MULTI_PREBUILT)
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..36dc582
--- /dev/null
+++ b/README.android
@@ -0,0 +1,4 @@
+URL: http://code.google.com/p/libphonenumber/
+Version: r6
+License: Apache 2
+Description: Google Phone Number Library.
diff --git a/java/build.xml b/java/build.xml
new file mode 100644
index 0000000..9fd344d
--- /dev/null
+++ b/java/build.xml
@@ -0,0 +1,82 @@
+<?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="resources.dir" value="resources"/>
+ <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"/>
+
+ <path id="classpath">
+ <fileset dir="${lib.dir}" includes="**/*.jar"/>
+ </path>
+ <path id="test.classpath">
+ <pathelement location="${classes.dir}"/>
+ <pathelement location="lib/junit/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="compile" description="Compile Java source.">
+ <mkdir dir="${classes.dir}"/>
+ <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
+ <javac srcdir="${test.dir}" destdir="${classes.dir}" classpathref="classpath"/>
+ </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*"/>
+ </fileset>
+ <fileset dir="${resources.dir}">
+ <include name="**/PhoneNumberMetadataProto"/>
+ </fileset>
+ </jar>
+ </target>
+
+ <target name="test-jar" depends="compile">
+ <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="${resources.dir}">
+ <include name="**/PhoneNumberMetadataProto"/>
+ <include name="**/PhoneNumberMetadataProtoForTesting"/>
+ </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/lib/google-guava.jar b/java/lib/google-guava.jar
new file mode 100644
index 0000000..1515f56
--- /dev/null
+++ b/java/lib/google-guava.jar
Binary files differ
diff --git a/java/lib/junit-4.8.1.jar b/java/lib/junit-4.8.1.jar
new file mode 100644
index 0000000..524cd65
--- /dev/null
+++ b/java/lib/junit-4.8.1.jar
Binary files differ
diff --git a/java/lib/protobuf-lite.jar b/java/lib/protobuf-lite.jar
new file mode 100644
index 0000000..5929e54
--- /dev/null
+++ b/java/lib/protobuf-lite.jar
Binary files differ
diff --git a/java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml b/java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml
new file mode 100644
index 0000000..b83058e
--- /dev/null
+++ b/java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml
@@ -0,0 +1,5281 @@
+<!-- Copyright (C) 2009 Google Inc.
+
+ 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.
+
+ @author: Shaopeng Jia
+
+ MetaData on Phone Number Plan and formatting rules
+ Note: Territories are in alphabetical order by their IDs, which are
+ based on ISO 3166-1 two-letter country codes. The country names
+ in the comments are the official short names in English according
+ to ISO 3166-1.
+
+ For more information on what each element represents, see
+ java/com/google/i18n/phonenumbers/phonemetadata.proto
+
+ Note that if you want to add validation metadata, the generalDesc
+ nationalNumberPattern and possibleNumberPattern must be provided.
+ If this is missing, then the country will be considered to have no more
+ specific phone-number type metadata (fixedLine, mobile etc) and hence only
+ basic validation rules (numbers should be between 3 and 15 digits long)
+ will be applied.
+-->
+
+<!DOCTYPE phoneNumberMetadata [
+ <!ELEMENT phoneNumberMetadata (territories)>
+ <!ELEMENT territories (territory+)>
+ <!ELEMENT territory (availableFormats?, generalDesc?, fixedLine?, mobile?, tollFree?,
+ premiumRate?, sharedCost?, personalNumber?, voip?)>
+ <!ELEMENT generalDesc (nationalNumberPattern, possibleNumberPattern, exampleNumber?)>
+ <!ELEMENT fixedLine (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT mobile (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT tollFree (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT premiumRate (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT sharedCost (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT personalNumber (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT voip (nationalNumberPattern?, possibleNumberPattern?, exampleNumber?)>
+ <!ELEMENT availableFormats (numberFormat+, intlNumberFormat*)>
+ <!ELEMENT nationalNumberPattern (#PCDATA)>
+ <!ELEMENT possibleNumberPattern (#PCDATA)>
+ <!ELEMENT exampleNumber (#PCDATA)>
+ <!ELEMENT numberFormat (#PCDATA)>
+ <!ELEMENT intlNumberFormat (#PCDATA)>
+
+ <!ATTLIST territory id CDATA #REQUIRED>
+ <!ATTLIST territory countryCode CDATA #REQUIRED>
+ <!ATTLIST territory preferredInternationalPrefix CDATA #IMPLIED>
+ <!ATTLIST territory internationalPrefix CDATA #REQUIRED>
+ <!ATTLIST territory nationalPrefix CDATA #IMPLIED>
+ <!ATTLIST territory nationalPrefixForParsing CDATA #IMPLIED>
+ <!ATTLIST territory nationalPrefixTransformRule CDATA #IMPLIED>
+ <!ATTLIST territory preferredExtnPrefix CDATA #IMPLIED>
+ <!ATTLIST territory nationalPrefixFormattingRule CDATA #IMPLIED>
+ <!ATTLIST numberFormat nationalPrefixFormattingRule CDATA #IMPLIED>
+ <!ATTLIST numberFormat leadingDigits CDATA #IMPLIED>
+ <!ATTLIST numberFormat pattern CDATA #REQUIRED>
+ <!ATTLIST intlNumberFormat leadingDigits CDATA #IMPLIED>
+ <!ATTLIST intlNumberFormat pattern CDATA #REQUIRED>
+ ]>
+
+<phoneNumberMetadata>
+ <territories>
+ <!-- Andorra -->
+ <!-- http://www.itu.int/oth/T0202000005/en -->
+ <territory id="AD" countryCode="376" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[346-9]" pattern="(\d{3})(\d{3})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="1" pattern="(180[02])(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:[346-9]|180)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[78]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6}</possibleNumberPattern>
+ <exampleNumber>712345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[346]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6}</possibleNumberPattern>
+ <exampleNumber>312345</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- Note that the definitions of 1800 and 1802 numbers differ in the
+ plan and on the Andorran www.sta.ad website, but we consider both to be
+ freephone here. -->
+ <nationalNumberPattern>180[02]\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>18001234</exampleNumber>
+ </tollFree>
+ <!-- The national numbering plan says that numbers beginning with 9 are
+ reserved for special services, so we assume they are premium rate here,
+ although we cannot find examples online.-->
+ <premiumRate>
+ <nationalNumberPattern>9\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6}</possibleNumberPattern>
+ <exampleNumber>912345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- United Arab Emirates -->
+ <!-- http://www.itu.int/oth/T02020000DC/en -->
+ <territory id="AE" countryCode="971" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2-4679][2-8]"
+ pattern="([2-4679])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="5" pattern="(5[056])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[4679]0"
+ pattern="([4679]00)(\d)(\d{5})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(800)(\d{2})(\d{0,7})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-79]\d{7,8}|800\d{2,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[2-4679][2-8]\d|600[25])\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>22345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>5[056]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>501234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>400\d{6}|800\d{2,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,12}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[02]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>900234567</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>700[05]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>700012345</exampleNumber>
+ </sharedCost>
+ </territory>
+
+ <!-- Afghanistan -->
+ <!-- http://www.itu.int/oth/T0202000001/en -->
+ <territory id="AF" countryCode="93" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="([2-7]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-7]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[25][0-8]|[34][0-4]|6[0-5])[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>234567890</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[057-9]\d{7}</nationalNumberPattern>
+ <exampleNumber>701234567</exampleNumber>
+ </mobile>
+ </territory>
+
+ <!-- Antigua and Barbuda -->
+ <!-- http://www.itu.int/oth/T0202000008/en -->
+ <territory id="AG" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[289]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>268(?:4(?:6[0-3]|84)|56[0-2])\d{4}</nationalNumberPattern>
+ <exampleNumber>2684601234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>268(?:464|7(?:2[0-9]|64|7[0-5]|8[358]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2684641234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ <voip>
+ <!-- This is included as Centrex in the plan.-->
+ <nationalNumberPattern>26848[01]\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2684801234</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Anguilla -->
+ <!-- http://www.itu.int/oth/T0202000007/en -->
+ <territory id="AI" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[289]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2644(?:6[12]|9[78])\d{4}</nationalNumberPattern>
+ <exampleNumber>2644612345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2642351234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Albania -->
+ <territory id="AL" countryCode="355" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Armenia -->
+ <territory id="AM" countryCode="374" internationalPrefix="00"
+ nationalPrefix="8">
+ </territory>
+
+ <!-- Netherlands Antilles -->
+ <territory id="AN" countryCode="599" internationalPrefix="00">
+ </territory>
+
+ <!-- Angola -->
+ <territory id="AO" countryCode="244" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Argentina -->
+ <!-- http://www.itu.int/oth/T0202000009/en -->
+ <!-- http://www.cnc.gov.ar/numeracion/IndicativosInterurbanos.asp -->
+ <territory id="AR" countryCode="54" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixForParsing="0(?:(11|2(?:2(?:02?|[13]|2[13-79]|4[1-6]|5[2457]|6[124-8]|7[1-4]|8[13-6]|9[1-367])|3(?:[06]2|1[467]|2[02-6]|3[13-8]|[49][2-6]|5[2-8]|7)|47[3-578]|6(?:1|2[2-7]|4[6-8]?|5[125-8])|9(?:0[1-3]|[19]|2\d|3[1-6]|4[0-24-68]|5[2-4]|6[2-6]|72?|8[23]?))|3(?:3(?:2[79]|8[2578])|4(?:0[124-9]|[12]|3[5-8]?|4[24-7]|5[4-68]?|6\d|7[126]|8[237-9]|9[1-36-8])|5(?:1|2[1245]|3[2-4]?|4[1-46-9]|6[2-4]|7[1-6]|8[2-5]?)|7(?:1[15-8]|2[125]|3[1245]|4[13]|5[124-8]|7[2-57]|8[1-36])|8(?:1|2[125-7]|3[23578]|4[13-6]|5[4-8]?|6[1-357-9]|7[5-8]?|8[4-7]?|9[124])))15)?"
+ nationalPrefixTransformRule="9$1" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[68]"
+ pattern="([68]\d{2})(\d{3})(\d{4})">$1-$2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="[68]"
+ pattern="([68]\d{2})(\d{3})(\d{4})">$1-$2-$3</intlNumberFormat>
+ <numberFormat leadingDigits="91" pattern="9(11)(\d{4})(\d{4})">$1 15-$2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="91"
+ pattern="9(11)(\d{4})(\d{4})">9 $1 $2-$3</intlNumberFormat>
+ <numberFormat leadingDigits="9(?:2(?:2[013]|37|6[14]|9[179])|3(?:4[1235]|5[138]|8[1578]))"
+ pattern="9(\d{3})(\d{3})(\d{4})">$1 15-$2-$3</numberFormat>
+ <intlNumberFormat
+ leadingDigits="9(?:2(?:2[013]|37|6[14]|9[179])|3(?:4[1235]|5[138]|8[1578]))"
+ pattern="9(\d{3})(\d{3})(\d{4})">9 $1 $2-$3</intlNumberFormat>
+ <numberFormat
+ leadingDigits="9(?:2(?:2[24-9]|3[0-69]|47|6[25]|9[02-68])|3(?:3[28]|4[046-9]|5[2467]|7[1-578]|8[23469]))"
+ pattern="9(\d{4})(\d{2})(\d{4})">$1 15-$2-$3</numberFormat>
+ <intlNumberFormat
+ leadingDigits="9(?:2(?:2[24-9]|3[0-69]|47|6[25]|9[02-68])|3(?:3[28]|4[046-9]|5[2467]|7[1-578]|8[23469]))"
+ pattern="9(\d{4})(\d{2})(\d{4})">9 $1 $2-$3</intlNumberFormat>
+ <numberFormat leadingDigits="1" pattern="(11)(\d{4})(\d{4})">$1 $2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="1"
+ pattern="(11)(\d{4})(\d{4})">$1 $2-$3</intlNumberFormat>
+ <!-- Some 4-digit area codes actually are caught by this
+ rule. I'm giving however preference to the 3-digit area
+ codes, since they are considerably larger
+ communities. -->
+ <numberFormat leadingDigits="2(?:2[013]|37|6[14]|9[179])|3(?:4[1235]|5[138]|8[1578])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="2(?:2[013]|37|6[14]|9[179])|3(?:4[1235]|5[138]|8[1578])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2-$3</intlNumberFormat>
+ <numberFormat leadingDigits="[23]" pattern="(\d{4})(\d{2})(\d{4})">$1 $2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="[23]"
+ pattern="(\d{4})(\d{2})(\d{4})">$1 $2-$3</intlNumberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{9,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ <exampleNumber>1123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:11[2-9]\d{7}|(?:2(?:2[013]|37|6[14]|9[179])|3(?:4[1235]|5[138]|8[1578]))[2-9]\d{6}|\d{4}[2-9]\d{5})</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,12}</possibleNumberPattern>
+ <exampleNumber>91123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8012345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>6(?:0\d|10)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>6001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- American Samoa -->
+ <!-- http://www.itu.int/oth/T0202000004/en -->
+ <territory id="AS" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[689]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>6846(?:22|33|44|55|77|88|9[19])\d{4}</nationalNumberPattern>
+ <exampleNumber>6846221234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>684(?:733|258)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>6847331234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Austria -->
+ <!-- http://www.rtr.at/en/tk/E129 -->
+ <territory id="AT" countryCode="43" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1|5[079]" pattern="([15])(\d{3,12})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="316|46|51|732|6(?:44|5[0-3579]|[6-9])|7(?:1|[28]0)|[89]"
+ pattern="(\d{3})(\d{3,10})">$1 $2</numberFormat>
+ <numberFormat
+ leadingDigits="2|3(?:1[1-578]|[3-8])|4[2378]|5[2-6]|6(?:[12]|4[1-35-9]|5[468])|7(?:2[1-8]|35|4[1-8]|[57-9])"
+ pattern="(\d{4})(\d{3,9})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{4,13}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,13}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Note the 050, 057 and 059 prefixes are defined as "private network"
+ in the Austrian plan. This just means they are registered to companies
+ who are distributed over different geographical areas and maintain their
+ own network. Examples here: http://www.rtr.at/?id=4506&S=05&art=d Also
+ note that the full area code is not validated - just the first 3 digits.
+ This also means that even though for most Austrian numbers the minimum
+ length is 7, we allow 6 since we don't differentiate below between 3 and
+ 4 digit area codes for reasons of efficiency.
+ -->
+ <nationalNumberPattern>1\d{3,12}|(?:2(?:1[467]|2[134-8]|5[2357]|6[1-46-8]|7[1-8]|8[124-7]|8[1458])|3(?:1[1-8]|3[23568]|4[5-7]|5[1378]|6[1-38]|8[3-68])|4(?:2[1-8]|35|63|7[1368]|8[2457])|5(?:1[27]|2[1-8]|3[357]|4[147]|5[12578]|6[37])|6(?:13|2[1-47]|4[1-35-8]|5[468]|62)|7(?:2[1-8]|3[25]|4[13478]|5[68]|6[16-8]|7[1-6]|9[45]))\d{3,10}|5(?:0[1-9]|[79]\d)\d{2,10}|720\d{6,10}</nationalNumberPattern>
+ <exampleNumber>1234567890</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6(?:44|5[0-3579]|6[013-9]|[7-9]\d)\d{4,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,13}</possibleNumberPattern>
+ <exampleNumber>644123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80[02]\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,13}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>(?:711|9(?:0[01]|3[019]))\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,13}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>8(?:10|2[018])\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,13}</possibleNumberPattern>
+ <exampleNumber>810123456</exampleNumber>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>780\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,13}</possibleNumberPattern>
+ <exampleNumber>780123456</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Australia -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200000D0001MSWE.doc -->
+ <!-- http://en.wikipedia.org/wiki/Telephone_numbers_in_Australia -->
+ <territory id="AU" countryCode="61" preferredInternationalPrefix="0011"
+ internationalPrefix="(?:14(?:1[14]|34|4[17]|[56]6|7[47]|88))?001[14-689]"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2378]"
+ pattern="([2378])(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="4" pattern="(4\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="5"
+ pattern="(5[05]0)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:[38]00|9)" nationalPrefixFormattingRule="$FG"
+ pattern="(1[389]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Although the national plan doesn't explicitly say so, there is no evidence that a
+ 180 xxxx number could be 180 0xxx. -->
+ <numberFormat leadingDigits="180[1-9]" nationalPrefixFormattingRule="$FG"
+ pattern="(180)(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="13[1-9]" nationalPrefixFormattingRule="$FG"
+ pattern="(13)(\d{2})(\d{2})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-578]\d{5,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2378]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>4[0-68]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>412345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- Local-rate (SmartNumbers) are put here for now because they are
+ also a reverse-charge network, although they charge a small local call
+ connect fee (around 25c). These start with 13 or 1300. -->
+ <nationalNumberPattern>1(?:80(?:0\d{2})?|3(?:00\d{2})?)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>190[0126]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1900123456</exampleNumber>
+ </premiumRate>
+ <!-- Wikipedia was the source for these types of numbers, and number
+ allocation search here
+ http://web.acma.gov.au/numb/openAccess/inquiry/allocationSearch.do
+ confirms this. (Search from 0500000000 to 0590000000)-->
+ <personalNumber>
+ <nationalNumberPattern>500\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>500123456</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>550\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>550123456</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Aruba -->
+ <!-- http://www.itu.int/oth/T020200000B/en -->
+ <territory id="AW" countryCode="297" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([57-9]\d{2})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[57-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>5(?:2\d{2}|8(?:[2-7]\d|8[0-79]|9[48]))\d{3}</nationalNumberPattern>
+ <exampleNumber>5212345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:5[69]\d|9(?:6\d|9[02-9])|7[34]\d)\d{4}</nationalNumberPattern>
+ <exampleNumber>5601234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{4}</nationalNumberPattern>
+ <exampleNumber>8001234</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{4}</nationalNumberPattern>
+ <exampleNumber>9001234</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Azerbaijan -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200000F0001MSWE.doc -->
+ <territory id="AZ" countryCode="994" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[4-8]"
+ pattern="([4-8]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[28]|22"
+ pattern="([12]\d)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[013-79]|2[013-9]"
+ pattern="([12]\d{2})(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[124-8]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1(?:(?:2[3-5]|36|8\d|9)\d|02|1[0-589]|3[358]|4[013-79]|5[0-479]|6[0236-9]|7[0-24-8])|2(?:16|2\d|3[0-24]|4[1468]|55|6[56]|79))\d{5}</nationalNumberPattern>
+ <exampleNumber>123123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:40|5[015]|7[07])\d{7}|60540\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>401234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>88\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>881234567</exampleNumber>
+ </tollFree>
+ </territory>
+
+ <!-- Bosnia and Herzegovina -->
+ <territory id="BA" countryCode="387" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Barbados -->
+ <!-- http://www.itu.int/oth/T0202000013/en -->
+ <territory id="BB" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[289]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>246[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>2462345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>246(?:(?:2[346]|45|82)\d|25[0-4])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2462501234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Bangladesh -->
+ <territory id="BD" countryCode="880" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Belgium -->
+ <!-- http://www.bipt.be/en/161/ShowContent/502/Database/Databases.aspx -->
+ <!-- http://www.telefoonzones.be/ -->
+ <!-- Information on non-geographic numbers here: (Dutch)
+ http://www.scarletbusiness.be/business/largeenterprise/nl/products/voiceservices/servicenumbers.jsp
+ -->
+ <territory id="BE" countryCode="32" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="4[7-9]"
+ pattern="(4[7-9]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[23]|[49][23]"
+ pattern="([2-49])(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[156]|7[18]|8(?:0[1-9]|[1-79])"
+ pattern="([15-8]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="(?:80|9)0"
+ pattern="([89]\d{2})(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7[07]"
+ pattern="(7[07])(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Note that 80 is a valid area code, so we explicitly check for this
+ case that the third digit begins with 1-9 -->
+ <nationalNumberPattern>(?:1[0-69]|[23][2-8]|[49][23]|5\d|6[013-57-9]|7[18])\d{6}|8(?:0[1-9]|[1-79]\d)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>4(?:7\d|8[4-9]|9[1-9])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>470123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>(?:90|7[07])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Burkina Faso -->
+ <territory id="BF" countryCode="226" internationalPrefix="00">
+ </territory>
+
+ <!-- Bulgaria -->
+ <!-- http://www.itu.int/oth/T0202000020/en -->
+ <territory id="BG" countryCode="359" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2" pattern="(2)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="43[1-6]" pattern="(43[1-6])(\d{4,5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[35-7]|4[124-7]|8[1-6]|9[1-7]"
+ pattern="(\d{2})(\d{2,3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8[7-9]|98"
+ pattern="([89]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="48|90" pattern="([49]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="43[0789]|800" pattern="(\d{3})(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{6,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2\d{6,7}|(?:[367]\d|4[124-7]|5[1-9]|8[1-6]|9[1-7])\d{5,6}|43[1-6]\d{4,5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>2123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:8[7-9]|98)\d{7}|43[0789]\d{5}|48\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>48123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Bahrain -->
+ <territory id="BH" countryCode="973" internationalPrefix="00">
+ </territory>
+
+ <!-- Burundi -->
+ <territory id="BI" countryCode="257" internationalPrefix="00">
+ </territory>
+
+ <!-- Benin -->
+ <territory id="BJ" countryCode="229" internationalPrefix="00">
+ </territory>
+
+ <!-- French Dept. of Guadeloupe -->
+ <territory id="BL" countryCode="590" internationalPrefix="00">
+ </territory>
+
+ <!-- Bermuda -->
+ <!-- http://www.itu.int/oth/T0202000018/en -->
+ <territory id="BM" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[489]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>441(?:2(?:02|23|[3479]\d)|[46]\d{2}|5(?:40|89)|824)\d{4}</nationalNumberPattern>
+ <exampleNumber>4412345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>441(?:[37]\d{2}|5(?:[0-3]\d|9[09]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>4413701234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Brunei Darussalam -->
+ <!-- http://www.itu.int/oth/T020200001F/en -->
+ <territory id="BN" countryCode="673" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <!-- Format is from http://aiti.gov.bn/contact.html-->
+ <availableFormats>
+ <numberFormat pattern="([2-578]\d{2})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-578]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-5]\d{6}</nationalNumberPattern>
+ <exampleNumber>2345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[78]\d{6}</nationalNumberPattern>
+ <exampleNumber>7123456</exampleNumber>
+ </mobile>
+ </territory>
+
+ <!-- Bolivia -->
+ <territory id="BO" countryCode="591" internationalPrefix="001[0-3]"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Brazil -->
+ <!-- http://en.wikipedia.org/wiki/%2B55 -->
+ <territory id="BR" countryCode="55" internationalPrefix="00(?:1[45]|2[13]|31)"
+ nationalPrefix="0"
+ nationalPrefixForParsing="0(?:(?:1[245]|2[135]|[34]1)(\d{10}))?"
+ nationalPrefixTransformRule="$1">
+ <!--The national prefix for parsing here also contains a capturing group
+ for the main number, since the carrier codes here may also be area codes,
+ so we want to check the length of the number after capturing. We also need
+ a nationalTransformRule to repopulate with the number without the carrier
+ code.-->
+ <availableFormats>
+ <numberFormat leadingDigits="[1-9][1-9]"
+ pattern="(\d{2})(\d{4})(\d{4})">($1) $2-$3</numberFormat>
+ <numberFormat leadingDigits="400" pattern="(400\d)(\d{4})">$1-$2</numberFormat>
+ <numberFormat leadingDigits="[3589]00" nationalPrefixFormattingRule="$NP$FG"
+ pattern="([3589]00)(\d{2,3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>400\d{5}|(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])[2-5]\d{7}</nationalNumberPattern>
+ <exampleNumber>1123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:[14689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])[6-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1161234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6,7}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>[359]00\d{6,7}</nationalNumberPattern>
+ <exampleNumber>300123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Bahamas -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000100001MSWE.doc -->
+ <territory id="BS" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[289]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3-57]|9[2-5])|4(?:2[237]|51|64|77)|502|636|702)\d{4}</nationalNumberPattern>
+ <exampleNumber>2423456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>242(?:[3-5]57|359)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2423591234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Bhutan -->
+ <!-- http://www.itu.int/oth/T0202000019/en -->
+ <territory id="BT" countryCode="975" internationalPrefix="00">
+ <availableFormats>
+ <!-- Format is from
+ http://www.tourism.gov.bt/tour-operators/bhutan-abbot-tours-and-travels.html -->
+ <numberFormat leadingDigits="1"
+ pattern="(17)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[2-8]"
+ pattern="([2-8])(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:17|[2-8])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2[3-6]|[34][5-7]|5[236]|6[2-46]|7[246]|8[2-4])\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,7}</possibleNumberPattern>
+ <exampleNumber>2345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>17\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>17123456</exampleNumber>
+ </mobile>
+ <!-- No information on other types of phone numbers for Bhutan has been found. -->
+ </territory>
+
+ <!-- Botswana -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200001C0001MSWE.doc -->
+ <territory id="BW" countryCode="267" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="7"
+ pattern="(7[1-4])(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9" pattern="(90)(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2(?:4[0-48]|6[0-24]|9[0578])|3(?:1[0235-9]|55|6\d|7[01]|9[0-57])|4(?:6[03]|7[1267]|9[0-5])|5(?:3[0389]|4[0489]|7[1-47]|88|9[0-49])|6(?:2[1-35]|5[149]|8[067]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>2401234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[1-3]\d{6}|74[0-7]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>71123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>8123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>9012345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Belarus -->
+ <territory id="BY" countryCode="375" internationalPrefix="8~10"
+ nationalPrefix="8">
+ </territory>
+
+ <!-- Belize -->
+ <territory id="BZ" countryCode="501" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Canada -->
+ <!-- http://www.cnac.ca/canadian_dial_plan/canadian_dial_plan.htm -->
+ <territory id="CA" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[2-9]\d{9}|3\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2(?:04|26|50|89)|306|4(03|16|18|38|50|56)|5(?:00|06|14|19|81|87)|6(?:00|04|13|47)|7(?:00|05|09|10|78|80)|8(?:07|19|67))[2-9]\d{6}|310\d{4}</nationalNumberPattern>
+ <exampleNumber>2042345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:2(?:04|26|50|89)|306|4(03|16|18|38|50|56)|5(?:00|06|14|19|81|87)|6(?:00|04|13|47)|7(?:00|05|09|10|78|80)|8(?:07|19|67)|9(?:02|05))[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>2042345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}|310\d{4}</nationalNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Congo, Dem. Rep. of the (formerly Zaire) -->
+ <territory id="CD" countryCode="243" internationalPrefix="00">
+ </territory>
+
+ <!-- Central African Republic -->
+ <territory id="CF" countryCode="236" internationalPrefix="00">
+ </territory>
+
+ <!-- Congo (Rep. of the) (Brazzaville) -->
+ <territory id="CG" countryCode="242" internationalPrefix="00">
+ </territory>
+
+ <!-- Switzerland -->
+ <!-- http://www.bakom.admin.ch/themen/telekom/00479/00604/index.html?lang=en
+ under Technical prescriptions: Numbering plan for international carriers -->
+ <territory id="CH" countryCode="41" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2-6]|[7-9]1"
+ pattern="([2-9]\d)(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="7[46-9]"
+ pattern="(7[46-9])(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="8[047]|90"
+ pattern="([89]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2[12467]|3[1-4]|4[134]|5[12568]|6[12]|[7-9]1)\d{7}</nationalNumberPattern>
+ <exampleNumber>212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[46-9]\d{7}</nationalNumberPattern>
+ <exampleNumber>741234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[016]\d{6}</nationalNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>84[0248]\d{6}</nationalNumberPattern>
+ <exampleNumber>840123456</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>878\d{6}</nationalNumberPattern>
+ <exampleNumber>878123456</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Côte d'Ivoire -->
+ <!-- http://www.itu.int/oth/T0202000031/en -->
+ <territory id="CI" countryCode="225" internationalPrefix="00">
+ <availableFormats>
+ <!-- Using format from online yellow pages over format implied in
+ national numbering plan. -->
+ <numberFormat pattern="(\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[02-5]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2(?:0[023]|1[02357]|[23][045]|4[03-5])|3(?:0[06]|1[069]|[2-4][07]|5[09]|6[08]))\d{5}</nationalNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:0[1-9]|4[4-9]|50|6[067])\d{6}</nationalNumberPattern>
+ <exampleNumber>01234567</exampleNumber>
+ </mobile>
+ </territory>
+
+ <!-- Cook Islands -->
+ <territory id="CK" countryCode="682" internationalPrefix="00"
+ nationalPrefix="00">
+ </territory>
+
+ <!-- Chile -->
+ <!-- http://www.itu.int/oth/T020200002A/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B56 -->
+ <!-- Carriers listed here: http://www.turismochile.com/datos/carrier.php -->
+ <territory id="CL" countryCode="56"
+ internationalPrefix="(?:0|1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))0"
+ nationalPrefix="0"
+ nationalPrefixForParsing="(?:0|1(?:1[0-69]|2[0-57]|5[13-58]|69|7[0167]|8[018]))"
+ nationalPrefixFormattingRule="$NP$FG">
+ <!-- When dialling mobile numbers from landlines, or vice versa, you need
+ a prefix of 0, which we strip here. National destinations may be dialled
+ with a carrier if they are not local so we strip these carrier codes as
+ well. -->
+ <availableFormats>
+ <numberFormat leadingDigits="2" pattern="(2)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[357]|4[1-35]|6[13-57]"
+ pattern="(\d{2})(\d{2,3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9" pattern="(9)([6-9]\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="44" pattern="(44)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="60" nationalPrefixFormattingRule="$FG"
+ pattern="(600)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="60" nationalPrefixFormattingRule="$FG"
+ pattern="(600)(\d{3})(\d{2})(\d{3})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="8" nationalPrefixFormattingRule="$FG"
+ pattern="(800)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1" nationalPrefixFormattingRule="$FG"
+ pattern="(1230)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:[2-9]|600|123)\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2|32|41)\d{7}|(?:3[3-5]|4[235]|5[1-3578]|6[13-57]|7[1-35])\d{6,7}</nationalNumberPattern>
+ <!-- Area codes do not need to be dialled when dialling within the same
+ area, so the smallest possible number is length 6.-->
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9[6-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>961234567</exampleNumber>
+ </mobile>
+ <!-- Toll free and premium rate patterns have been collected by looking at
+ numbers on the internet, rather than from a definitive source. -->
+ <tollFree>
+ <!-- 1230 numbers are used by Visa/Mastercard helplines in Chile -->
+ <nationalNumberPattern>800\d{6}|1230\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,11}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>600\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ <exampleNumber>6001234567</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>44\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>441234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Cameroon -->
+ <!-- http://www.itu.int/oth/T0202000024/en -->
+ <territory id="CM" countryCode="237" internationalPrefix="00">
+ <availableFormats>
+ <!-- Formatting on the internet is consistently with the first 2
+ extracted, and usually in the same format as France (all 2 digit groups)
+ so we use this instead of the guidance of the national numbering plan
+ (which has 1 3 2 2 and 4 4 as its two formatting examples.)-->
+ <numberFormat leadingDigits="[2379]|88"
+ pattern="([237-9]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="80"
+ pattern="(800)(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[237-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Technically, the numbers are required only to start with a 2 or a
+ 3, but all numbers at the moment start with 22 or 33 since they have
+ been migrated from seven digit numbers beginning with these numbers.
+ This rule should be relaxed if/when we start getting numbers beginning
+ in other ways. -->
+ <nationalNumberPattern>(?:22|33)\d{6}</nationalNumberPattern>
+ <exampleNumber>22123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[79]\d{7}</nationalNumberPattern>
+ <exampleNumber>71234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{5}</nationalNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <!-- These numbers are listed as value-added in the guide, and in
+ practice seem to begin with 88 (usually 880). No information can be
+ found as to whether these are premium rate or shared cost.-->
+ <nationalNumberPattern>88\d{6}</nationalNumberPattern>
+ <exampleNumber>88012345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- China -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200002B0001XLSE.xls -->
+ <territory id="CN" countryCode="86" internationalPrefix="00"
+ nationalPrefix="0">
+ <availableFormats>
+ <numberFormat leadingDigits="21" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(21)(\d{4})(\d{4,6})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="10(?:[1-79]|8(?:0[1-9]|[1-9]))|2[02-9]"
+ nationalPrefixFormattingRule="$NP$FG"
+ pattern="([12]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="80" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(80\d{2})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[35-79]|[48][1-9]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(\d{3})(\d{3,4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[3-58]"
+ pattern="(1[3-58]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="40" pattern="(400)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="10800" pattern="(10800)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-79]\d{7,11}|8[0-357-9]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{4,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>21\d{8,10}|(?:10|2[02-57-9]|3(?:11|7[159])|4[135]1|5(?:1\d|2[37]|3[12]|7[13-79]|9[15])|7(?:31|5[457]|6[09])|898)\d{8}|(?:3(?:1[02-9]|35|49|5\d|7[02-68]|9[1-68])|4(?:1[02-9]|2[179]|[35][2-9]|6[4789]|7[0-46-9]|8[23])|5(?:3[03-9]|4[36]|5\d|6[1-6]|7[028]|80|9[2-46-9])|6(?:3[1-5]|6[0238]|9[12])|7(?:01|[1579]\d|2[248]|3[04-9]|4[3-6]|6[2368])|8(?:1[236-8]|2[5-7]|[37]\d|5[1-9]|8[3678]|9[1-7])|9(?:0[1-3689]|1[1-79]|[379]\d|4[13]|5[1-5]))\d{7}|80(?:29|6[03578]|7[018]|81)\d{4}</nationalNumberPattern>
+ <exampleNumber>1012345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1(?:3[0-9]|47|5[0135689]|8[05-9])\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>13123456789</exampleNumber>
+ </mobile>
+ <!-- Toll free, premium rate, and VoIP numbers are not clearly defined in the official Chinese
+ number plan, and do not seem to have been standardized. The information below is
+ collected from searching the web. -->
+ <!-- http://en.wikipedia.org/wiki/Toll-free_telephone_number -->
+ <tollFree>
+ <nationalNumberPattern>10800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{12}</possibleNumberPattern>
+ <exampleNumber>108001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>16[08]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>16812345</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>400\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>4001234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Colombia -->
+ <territory id="CO" countryCode="57" internationalPrefix="(?:00[579]|#555|#999)"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Costa Rica -->
+ <territory id="CR" countryCode="506" internationalPrefix="00">
+ </territory>
+
+ <!-- Cuba -->
+ <territory id="CU" countryCode="53" internationalPrefix="119"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Cape Verde -->
+ <territory id="CV" countryCode="238" internationalPrefix="0">
+ </territory>
+
+ <!-- Cyprus -->
+ <territory id="CY" countryCode="357" internationalPrefix="00">
+ </territory>
+
+ <!-- Czech Rep. -->
+ <!-- http://www.itu.int/oth/T0202000035/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B420 -->
+ <territory id="CZ" countryCode="420" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([2-9]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2\d{8}|(?:3[1257-9]|4[16-9]|5[13-9])\d{7}</nationalNumberPattern>
+ <exampleNumber>212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>60[1-8]\d{6}|7[2379]\d{7}</nationalNumberPattern>
+ <exampleNumber>601123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[0689]\d{6}</nationalNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>8[134]\d{7}</nationalNumberPattern>
+ <exampleNumber>811234567</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>70[01]\d{6}</nationalNumberPattern>
+ <exampleNumber>700123456</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Germany -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000510001XLSE.xls -->
+ <territory id="DE" countryCode="49" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="3[02]|40|[68]9"
+ pattern="(\d{2})(\d{4,11})">$1/$2</numberFormat>
+ <!-- The order of the rules on 3-5 digits area code matter as fallback is used here. -->
+ <!-- 3 digit area codes.-->
+ <numberFormat leadingDigits="2(?:\d1|0[2389]|1[24]|28|34)|3[3-9][15]|340|906|[4-9][1-9]1"
+ pattern="(\d{3})(\d{3,10})">$1/$2</numberFormat>
+ <!-- 4 digit area codes.-->
+ <numberFormat leadingDigits="[24-6]|[7-9](?:\d[1-9]|[1-9]\d)"
+ pattern="([24-9]\d{3})(\d{2,8})">$1/$2</numberFormat>
+ <numberFormat
+ leadingDigits="3(?:3(?:0[1-467]|2[127-9]|3[124578]|[46][1246]|7[1257-9]|8[1256]|9[145])|4(?:2[135]|3[1357]|4[13578]|6[1246]|7[1356]|9[1346])|5(?:0[14]|2[1-3589]|3[1357]|4[1246]|6[1-4]|7[1346]|8[13568]|9[1246])|6(?:0[356]|2[1-489]|3[124-6]|4[1347]|6[13]|7[12579]|8[1-356]|9[135])|7(?:2[1-7]|3[1357]|4[145]|6[1-5]|7[1-4])|8(?:21|3[1468]|4[1347]|6[0135-9]|7[1467]|8[136])|9(?:0[12479]|2[1358]|3[1357]|4[134679]|6[1-9]|7[136]|8[147]|9[1468]))"
+ pattern="(\d{4})(\d{2,7})">$1/$2</numberFormat>
+ <!-- 5 digit area codes.-->
+ <numberFormat leadingDigits="3" pattern="(\d{5})(\d{1,6})">$1/$2</numberFormat>
+ <!-- http://www.t-mobile.de/servicehotlines/0,13401,17660-_,00.html -->
+ <numberFormat leadingDigits="1[5-7]" pattern="(1[5-7]\d)(\d{7,8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="180" pattern="(180)(\d)(\d{4,10})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="700" pattern="(700)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="800|900[135]"
+ pattern="([89]00)(\d)(\d{6})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9009" pattern="(900)(9)(\d{7})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <!-- When deciding whether to assume a leading 49 is a country code or
+ not, the number is examined to see if it is valid with the 49 as part of
+ the number. Due to the variable length of German numbers, this test is
+ hard to do. The national pattern is hence stricter for numbers starting
+ with 49, to try and remove the country code if the number begins with 49
+ whenever possible. -->
+ <nationalNumberPattern>(?:4[0-8]|[1-35-9]\d)\d{4,12}|49(?:4[1-8]|[0-35-7]\d)\d{2,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{2,14}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[246]\d{2}|3[02-9]\d|5(?:0[2-8]|[38][0-8]|[124-6]\d|[79][0-7])|[789](?:[1-9]\d|0[2-9]))\d{3,10}</nationalNumberPattern>
+ <exampleNumber>30123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- Note: 8 digit numbers seem to be available for prefix 176 now,
+ although no official documentation can be found. See b/2364060 -->
+ <nationalNumberPattern>1(?:5\d{9}|7(?:[0-57-9]|6\d)\d{7}|6[02]\d{7,8}|63\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ <exampleNumber>15123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900(?:[135]\d{6}|9\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>180\d{5,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,14}</possibleNumberPattern>
+ <exampleNumber>18012345</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>700\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>70012345678</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Djibouti -->
+ <territory id="DJ" countryCode="253" internationalPrefix="00">
+ </territory>
+
+ <!-- Denmark -->
+ <!-- http://en.itst.dk/numbering-issues-and-domain-aspects/numbering-issues/numbering-lists -->
+ <territory id="DK" countryCode="45" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([1-9]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3[2-9]|4[3-9]|5[4-9]|6[2-9]|7[02-9]|8[26-9]|9[6-9])\d{6}</nationalNumberPattern>
+ <exampleNumber>32123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:2[0-9]|3[01]|4[0-2]|5[0-3]|6[01])\d{6}</nationalNumberPattern>
+ <exampleNumber>20123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{6}</nationalNumberPattern>
+ <exampleNumber>80123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{6}</nationalNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Dominica -->
+ <!-- http://www.itu.int/oth/T020200003B/en -->
+ <territory id="DM" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[7-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\d{4}</nationalNumberPattern>
+ <exampleNumber>7674201234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>767(?:2(?:[2346]5|7[5-7])|31[5-7]|61[4-6])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7672251234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Dominican Rep. -->
+ <territory id="DO" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[89]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>8[02]9[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>8092345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>8[02]9[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>8092345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Algeria -->
+ <territory id="DZ" countryCode="213" internationalPrefix="00"
+ nationalPrefix="7">
+ </territory>
+
+ <!-- Ecuador -->
+ <territory id="EC" countryCode="593" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Estonia -->
+ <!-- http://www.tja.ee/public/Legislation_side/Numbering_/Estonian_NP_eng.htm -->
+ <territory id="EE" countryCode="372" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat
+ leadingDigits="[34679]|5(?:[02]\d{2}|1(?:[0-8]\d|95)|5[0-478]\d|64[0-4]|65[1-589])"
+ pattern="([34-79]\d{2})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="8000" pattern="(8000)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="5|8(?:001|[1-5])"
+ pattern="([58]\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="800[2-9]" pattern="(800[2-9])(\d{3})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[3-9]\d{6,7}|800\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3[23589]|4[3-8]|6\d|7[1-9]|88)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>3212345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- 7 digit mobile numbers currently in use with special prefixes are preserved - new
+ numbers are 8 digits. -->
+ <nationalNumberPattern>(?:5\d|8[1-5])\d{6}|5(?:[02]\d{2}|1(?:[0-8]\d|95)|5[0-478]\d|64[0-4]|65[1-589])\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>51234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800(?:0\d{3}|1\d|[2-9])\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>9001234</exampleNumber>
+ </premiumRate>
+ <personalNumber>
+ <nationalNumberPattern>70\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>7012345</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Egypt -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200003E0001MSWE.doc -->
+ <territory id="EG" countryCode="20" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2" pattern="(2)(\d{8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="3" pattern="(3)(\d{7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[14-6]|[89][2-9]"
+ pattern="(\d{2})(\d{7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[89]00"
+ pattern="([89]00)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-689]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[35][23]|2[23]\d|3\d|4(?:0[2-4]|[578][23]|64)|5(?:0[234]|[57][23])|6[24-689]3|8(?:[28][2-4]|42|6[23])|9(?:[25]2|3[24]|6[23]|7[2-4]))\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>234567890</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1[0-246-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>101234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Eritrea -->
+ <territory id="ER" countryCode="291" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Spain -->
+ <!-- http://www.mityc.es/telecomunicaciones/es-ES/Servicios/Numeracion/PlanNacional/Paginas/PlanNacionalNumeracion.aspx -->
+ <territory id="ES" countryCode="34" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([5-9]\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[5-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[89][1-8]\d{7}</nationalNumberPattern>
+ <exampleNumber>812345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6\d{8}</nationalNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>[89]00\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>80[367]\d{6}</nationalNumberPattern>
+ <exampleNumber>803123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>90[12]\d{6}</nationalNumberPattern>
+ <exampleNumber>901123456</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>70\d{7}</nationalNumberPattern>
+ <exampleNumber>701234567</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Ethiopia -->
+ <territory id="ET" countryCode="251" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Finland -->
+ <!-- http://www.ficora.fi/en/index/palvelut/palvelutaiheittain/numerointi/numerotyypitjaalueet.html -->
+ <territory id="FI" countryCode="358" internationalPrefix="00|99[049]"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2[09]|[14]|50|7[135]"
+ pattern="(\d{2})(\d{4,10})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[25689][1-8]|3"
+ pattern="(\d)(\d{4,11})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[6-8]0" pattern="([6-8]00)(\d{4,7})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{4,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- This includes both geographic numbers and non-geographic nationwide
+ subscriber numbers. -->
+ <nationalNumberPattern>1(?:0[1-9]\d{3,7}|[35689][1-8]\d{3,9}|[47]\d{5,10})|2(?:0(?:[16-8]\d{3,7}|2[14-9]\d{1,6}|[3-5]\d{2,7}|9[0-7]\d{1,6})|[1-8]\d{3,9}|9\d{4,8})|3(?:0[1-9]\d{3,7}|[1-8]\d{3,9}|9\d{4,8})|[5689][1-8]\d{3,9}|7(?:1\d{7}|3\d{8}|5[03-9]\d{2,7})</nationalNumberPattern>
+ <exampleNumber>1312345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>4\d{5,10}|50\d{4,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ <exampleNumber>412345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>[67]00\d{5,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>600123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Fiji -->
+ <territory id="FJ" countryCode="679" internationalPrefix="00">
+ </territory>
+
+ <!-- Falkland Islands (Malvinas) -->
+ <territory id="FK" countryCode="500" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Micronesia, Federated States of -->
+ <territory id="FM" countryCode="691" internationalPrefix="00">
+ </territory>
+
+ <!-- Faroe Islands -->
+ <territory id="FO" countryCode="298" internationalPrefix="00">
+ </territory>
+
+ <!-- France -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200004A0001MSWE.doc -->
+ <!-- http://www.arcep.fr/index.php?id=8146 -->
+ <!-- http://en.wikipedia.org/wiki/%2B33 -->
+ <territory id="FR" countryCode="33" internationalPrefix="[04579]0"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[1-69]"
+ pattern="([1-69])(\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4 $5</numberFormat>
+ <numberFormat leadingDigits="8" nationalPrefixFormattingRule="$NP $FG"
+ pattern="(8\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-689]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-5]\d{8}</nationalNumberPattern>
+ <exampleNumber>123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6\d{8}|7[5-9]\d{7}</nationalNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{7}</nationalNumberPattern>
+ <exampleNumber>801234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>8(?:1[01]|2[0156]|84|9[0-37-9])\d{6}</nationalNumberPattern>
+ <exampleNumber>810123456</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>9\d{8}</nationalNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Gabon -->
+ <territory id="GA" countryCode="241" internationalPrefix="00">
+ </territory>
+
+ <!-- United Kingdom -->
+ <!-- http://www.ofcom.org.uk/telecoms/ioi/numbers/ -->
+ <territory id="GB" countryCode="44" internationalPrefix="00"
+ nationalPrefix="0" preferredExtnPrefix=" x" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[23]|55"
+ pattern="([235]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:1\d|\d1)"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 5-digit area codes (excluding national prefix) are very rare in GB, and are only
+ available in the following areas: 13873(Langholm), 15242(Hornby), 15394(Hawkshead),
+ 15395(Grange-Over-Sands), 15396(Sedbergh), 16973(Wigton), 16974(Raughton Head),
+ 16977(Brampton), 17683(Appleby), 17684(Pooley Bridge), 17687(Keswick), 19467(Gosforth)-->
+ <numberFormat leadingDigits="1(?:3873|5(?:242|39[4-6])|697[347]|768[347]|9467)"
+ pattern="(\d{5})(\d{4,5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="1" pattern="(\d{4})(\d{4,6})">$1 $2</numberFormat>
+ <!-- http://online.vodafone.co.uk/dispatch/Portal/appmanager/vodafone/wrp?_nfpb=true&_pageLabel=Page_BOS_ContactUsContent&pageID=PCU_0001 -->
+ <numberFormat leadingDigits="7[1-9]"
+ pattern="(7\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="500" pattern="(500)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="56|9[018]"
+ pattern="([59]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="70" pattern="(70\d{2})(\d{6})">$1 $2</numberFormat>
+ <!-- UK child line -->
+ <numberFormat leadingDigits="8001" pattern="(800)(1111)">$1 $2</numberFormat>
+ <numberFormat leadingDigits="80" pattern="(80\d)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8(?:4[3-5]|7[01])"
+ pattern="(8\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- http://en.wikipedia.org/wiki/List_of_United_Kingdom_dialling_codes -->
+ <nationalNumberPattern>1(?:1[3-8]|[2-69]1)\d{7}|1(?:2(?:0[024-9]|2[3-9]|3[3-79]|4[1-689]|[58][02-9]|6[0-47-9]|7[013-9]|8[02-9]|9[0-9])|3(?:0\d|[25][02-9]|3[02-579]|4[0-56-9]|[68][0-46-9]|7[1-35-79]|9[24578])|4(?:0[03-9]|2[02-57-9]|[378]\d|4[02-69]|5[0-8]|[69][0-79])|5(?:0[1-35-9]|2[024-9]|3[014-689]|4[02-9]|[57][03-9]|6\d|8[0-68]|9[0-57-9])|6(?:0[034689]|2[0-689]|3[13-9]|4[1-467]|5[0-69]|6[13-9]|7[0-8]|8[013-9]|9[0-24578])|7(?:0[0246-9]|2\d|3[0236-8]|4[03-9]|5[0-46-9]|6[13-9]|7[0-35-9]|8[024-9]|9[02-9])|8(?:0[35-9]|2[1-9]|3[02-578]|4[0-578]|5[124-9]|6[2-69]|7\d|8[2-9]|9[02569])|9(?:0[02-589]|2[02-689]|3[1-57-9]|4[2-9]|5[0-579]|6[2-47-9]|7[0-24578]|8\d|9[2-57]))\d{5,6}|(?:2[03489]|3[0347]|55)\d{8}</nationalNumberPattern>
+ <exampleNumber>1212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7(?:[1-57-9]\d{8}|624\d{6})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7123456789</exampleNumber>
+ </mobile>
+ <!-- Source for non geographic numbers:
+ http://en.wikipedia.org/wiki/Non-geographical_telephone_numbers_in_the_UK
+ -->
+ <tollFree>
+ <nationalNumberPattern>80(?:01111|\d{7,8})|500\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>8012345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9[018]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9012345678</exampleNumber>
+ </premiumRate>
+ <!-- Using shared cost to deal with the various revenue sharing number
+ prefixes in the United Kingdom. -->
+ <sharedCost>
+ <nationalNumberPattern>8(?:4[3-5]|7[01])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8431234567</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>70\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7012345678</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>56\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>5612345678</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Grenada -->
+ <!-- http://www.itu.int/oth/T0202000057/en -->
+ <territory id="GD" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[489]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:08|3[5-9]|4[0-49]|5[5-79]|68|73|90)|63[68]|7(?:58|84)|938)\d{4}</nationalNumberPattern>
+ <exampleNumber>4732691234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>473(?:4(?:0[3-79]|1[04-9]|20|58)|53[3-8])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>4734031234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Georgia -->
+ <!-- http://www.itu.int/oth/T0202000050/en -->
+ <territory id="GE" countryCode="995" internationalPrefix="8~10"
+ nationalPrefix="8" nationalPrefixFormattingRule="$NP $FG">
+ <availableFormats>
+ <!-- Format isn't very strictly defined - the yellow pages omits area
+ code and does 2 2 2, the chairman on the communications commission
+ listed his as 2 2 4 (Tblisi area code).-->
+ <numberFormat leadingDigits="32"
+ pattern="(32)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="2|3[13-79]|446" pattern="(\d{3})(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="44(?:2[2369]|[345])"
+ pattern="(\d{4})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="442[57]" pattern="(442[57])(\d{3})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[5679]" pattern="(\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8"
+ pattern="(800)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-3579]\d{7}|8\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Added the 253 and 250 prefixes as there are lots of numbers on the
+ internet with that prefix -->
+ <nationalNumberPattern>(?:122|2(?:22|36|5[03])|3(?:1[0-35-8]|[256]\d|3[1-35679]|4[024-79]|7[0-39]|9[1-35-7])|44[2-6])\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,8}</possibleNumberPattern>
+ <exampleNumber>32123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- Added the 99 prefix here as it is a common prefix for mobile
+ numbers on the internet -->
+ <nationalNumberPattern>(?:5[014578]|62|7[1479]|9[0135-9])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>55123456</exampleNumber>
+ </mobile>
+ <!-- Information from www.yell.ge, examples such as Wissol Petroleum Georgia hotline. -->
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ </territory>
+
+ <!-- French Guiana (French Dept. of) -->
+ <territory id="GF" countryCode="594" internationalPrefix="00">
+ </territory>
+
+ <!-- Ghana -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000520001MSWE.doc -->
+ <territory id="GH" countryCode="233" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[27][12]|4[12]|[35689]1"
+ pattern="(\d{2})(\d{3,6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="25|31|[4-9]"
+ pattern="([2-9]\d{2})(\d{3,5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="3[02-9]" pattern="(3\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[47]" pattern="(2[47])(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[0368]|54"
+ pattern="([25]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{4,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- This validation rule checks area code and length and is sorted by the
+ subscriber number length. -->
+ <nationalNumberPattern>(?:251|3[467]2|41|5(?:[36]1|[78]2)|61|882|9(?:1|6[268]))\d{3}|(?:31[24]|567|6(?:1|5[23])|7(?:2|43)|9(?:1|35))\d{4}|(?:2[12]|3(?:45|9[24])|4(?:2|32])|5(?:1|6[58])|64[28]|7(?:1[567]?|46|5[26]|62)|8(?:1|4[268]|7[26])|9(?:31|53))\d{5}|(?:2[12]|42|51)\d{6}|3\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ <exampleNumber>251234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>2(?:755\d{4}|(?:4|08)\d{6}|[368]\d{7})|54\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>27551234</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Gibraltar -->
+ <territory id="GI" countryCode="350" internationalPrefix="00">
+ </territory>
+
+ <!-- Greenland -->
+ <territory id="GL" countryCode="299" internationalPrefix="00">
+ </territory>
+
+ <!-- Gambia -->
+ <territory id="GM" countryCode="220" internationalPrefix="00">
+ </territory>
+
+ <!-- Guinea -->
+ <territory id="GN" countryCode="224" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Guadeloupe -->
+ <territory id="GP" countryCode="590" internationalPrefix="00">
+ </territory>
+
+ <!-- Equatorial Guinea -->
+ <territory id="GQ" countryCode="240" internationalPrefix="00">
+ </territory>
+
+ <!-- Greece -->
+ <!-- http://www.itu.int/oth/T0202000055/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B30 -->
+ <territory id="GR" countryCode="30" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="21|7"
+ pattern="([27]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[2-9]1|[689]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[2-9][02-9]"
+ pattern="(2\d{3})(\d{6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[26-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2(?:1\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\d|2[1-5]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\d|2[1-3]|4[124]|5[1-6]|[39][1-4])|6(?:1\d|3[24]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-35])|7(?:1\d|[23][1-5]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\d|2[1-5]|[34][1-4]|9[1-7]))\d{6}</nationalNumberPattern>
+ <exampleNumber>2123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>69\d{8}</nationalNumberPattern>
+ <exampleNumber>6912345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[19]\d{7}</nationalNumberPattern>
+ <exampleNumber>9091234567</exampleNumber>
+ </premiumRate>
+ <!-- Including calls with maximum charge of 0,25 EUR/minute here instead
+ of under premium rate. -->
+ <sharedCost>
+ <nationalNumberPattern>8(?:0[16]|12|25)\d{7}</nationalNumberPattern>
+ <exampleNumber>8011234567</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>70\d{8}</nationalNumberPattern>
+ <exampleNumber>7012345678</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Guatemala -->
+ <territory id="GT" countryCode="502" internationalPrefix="00">
+ </territory>
+
+ <!-- Guam -->
+ <!-- http://en.wikipedia.org/wiki/%2B1_671 -->
+ <territory id="GU" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[689]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>671(?:3\d{2}|47\d|56\d|6[3-5]\d|7(?:3\d|89)|828)\d{4}</nationalNumberPattern>
+ <exampleNumber>6713123456</exampleNumber>
+ </fixedLine>
+ <!-- We assume mobile phone numbers to be the same as fixed-line - further info unavailable -->
+ <mobile>
+ <nationalNumberPattern>671(?:3\d{2}|47\d|56\d|6[3-5]\d|7(?:3\d|89)|828)\d{4}</nationalNumberPattern>
+ <exampleNumber>6713123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Guinea-Bissau -->
+ <territory id="GW" countryCode="245" internationalPrefix="00">
+ </territory>
+
+ <!-- Guyana -->
+ <territory id="GY" countryCode="592" internationalPrefix="001"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Hong Kong -->
+ <!-- http://www.ofta.gov.hk/numbering/main.html -->
+ <territory id="HK" countryCode="852" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[235-7]|[89](?:0[1-9]|[1-9])"
+ pattern="(\d{4})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="800" pattern="(800)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="900"
+ pattern="(900)(\d{2})(\d{3})(\d{3})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[235-9]\d{7,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[23]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[5-79]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>51234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>90012345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Honduras -->
+ <territory id="HN" countryCode="504" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Croatia -->
+ <!-- http://www.itu.int/oth/T0202000032/en -->
+ <territory id="HR" countryCode="385" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- The plan says 1 XXX XXXX but the government and local telecom
+ websites are formatted 1 XXXX XXX, so we prefer that formatting
+ here. These same sources prefer XXX XXX to XX XXXX as well. -->
+ <numberFormat leadingDigits="1" pattern="(1)(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="62" pattern="(62)(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[2-5]"
+ pattern="([2-5]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9"
+ pattern="(9[12589])(\d{3,4})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9"
+ pattern="(9[12589])(\d{3,4})(\d{3})(\d{3})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="60" pattern="(60)(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="61" pattern="(61)(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(800)(\d{2})(\d{2,3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(800)(\d{3,4})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-7]\d{5,8}|[89]\d{6,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Supporting 062 (universal access) numbers here too. -->
+ <nationalNumberPattern>(?:1|62)\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9[12589]\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,12}</possibleNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- The plan says it shall be 0800 followed by 7 digits, but online
+ examples vary between 4 and 7.-->
+ <nationalNumberPattern>800\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <!-- 061 is for TeleVoting numbers - but these are charged at similar
+ rates to premium rate so we include them here.-->
+ <nationalNumberPattern>6(?:0\d{3}|1)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>601234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Haiti -->
+ <territory id="HT" countryCode="509" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Hungary -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000610001MSWE.doc -->
+ <territory id="HU" countryCode="36" internationalPrefix="00"
+ nationalPrefix="06" nationalPrefixFormattingRule="($FG)">
+ <!-- Although the national prefix is necessary for dialling, the preferred
+ format (confirmed by the following the yellow pages) is
+ to omit this when formatting. Yellow pages: www.aranyoldalak.hu -->
+ <availableFormats>
+ <numberFormat leadingDigits="1" pattern="(1)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[4-689]|[237][2-9]"
+ pattern="(\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[237][01]"
+ pattern="([237][01])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{8,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Includes numbers for corporate networks. -->
+ <nationalNumberPattern>(?:1\d|2(?:1\d|[2-9])|3[2-7]|4[24-9]|5[2-79]|6[23689]|7(?:1\d|[2-9])|8[2-57-9]|9[2-69])\d{6}</nationalNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:[237]0|31)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>201234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>80123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9[01]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>40\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>40123456</exampleNumber>
+ </sharedCost>
+ </territory>
+
+ <!-- Indonesia -->
+ <!-- http://www.itu.int/oth/T0202000064/en (from 2001, very out-of-date) -->
+ <!-- http://en.wikipedia.org/wiki/%2B62 -->
+ <territory id="ID" countryCode="62" internationalPrefix="0(?:0[1789]|10(?:00|1[67]))"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2[124]|[36]1" nationalPrefixFormattingRule="($NP$FG)"
+ pattern="(\d{2})(\d{7,8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[4579]|2[035-9]|[36][02-9]"
+ nationalPrefixFormattingRule="($NP$FG)"
+ pattern="(\d{3})(\d{5,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="8[1-35-9]"
+ pattern="(8\d{2})(\d{3,4})(\d{3,4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="1" pattern="(177)(\d{6,8})">$1 $2</numberFormat>
+ <!-- http://en.wikipedia.org/wiki/Toll-free_telephone_number, and
+ examples on the web show that sometimes they are followed by less
+ digits. -->
+ <numberFormat leadingDigits="800" pattern="(800)(\d{5,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="809"
+ pattern="(809)(\d)(\d{3})(\d{3})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Area codes taken from wikipedia, with missing ones added from
+ http://www.telkom.co.id/customer-services/area-and-country-code/?type=area
+ -->
+ <nationalNumberPattern>2[124]\d{7,8}|(?:2(?:[35][1-4]|6[0-8]|7[1-6]|8\d|9[1-8])|3(?:1|2[1-578]|3[1-68]|4[1-3]|5[1-8]|6[1-3568]|7[0-46]|8\d)|4(?:0[1-589]|1[01347-9]|2[0-36-8]|3[0-24-68]|5[1-378]|6[1-5]|7[134]|8[1245])|5(?:1[1-35-9]|2[25-8]|3[1246-9]|4[1-3589]|5[1-46]|6[1-8])|6(?:19?|[25]\d|3[1-469]|4[1-6])|7(?:1[1-46-9]|2[14-9]|[36]\d|4[1-8]|5[1-9]|7[1-36-9])|9(?:0[12]|1[0134-8]|2[0-479]|5[125-8]|6[23679]|7[159]|8[01346]))\d{5,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>8[1-35-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,11}</possibleNumberPattern>
+ <exampleNumber>812345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>177\d{6,8}|800\d{5,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,11}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>809\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8091234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Ireland -->
+ <!-- http://www.comreg.ie/_fileupload/publications/ComReg0435.pdf -->
+ <!-- http://www.comreg.ie/_fileupload/publications/ComReg03147.pdf -->
+ <territory id="IE" countryCode="353" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="($NP$FG)">
+ <availableFormats>
+ <numberFormat leadingDigits="1" pattern="(1)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[2-9]|4[347]|5[2-58]|6[2-47-9]|9[3-9]"
+ pattern="(\d{2})(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="40[24]|50[45]" pattern="(\d{3})(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="48" pattern="(48)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="81" pattern="(818)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[24-69]|7[14]"
+ pattern="(\d{2})(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8[35-9]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(8[35-9])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="76" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(76)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="70" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(700)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:8[059]0|5)" nationalPrefixFormattingRule="$FG"
+ pattern="(\d{4})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[124-9]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- We allow 6-7 digit subscriber numbers for the 021 area code since
+ that seems to be reflected by the numbers in the Yellow Pages. The 023,
+ 043, 052 and 064 area codes also may have 7 digit subscriber numbers,
+ although limited to 5 in the plan. This was caused by a numbering update
+ in 2008 (http://www.wtng.info/wtng-353-ie.html has more details). Other
+ changes not in the plan include consolidating 0502, 0506 and 0509 into
+ 057 and 054, 055 and 053 into 053, and making 044 be followed by 7
+ digits in some cases.
+ We also include Universal Access numbers here in the fixed-line list.
+ Another peculiarity is that 048 actually replaces 00 44 28 when Irish
+ people dial, allowing them to easily dial Northern Ireland. We support
+ these numbers here, although technically they are numbers for the UK.
+ -->
+ <nationalNumberPattern>(?:2[24-9]|4(?:0[24]|7)|5(?:0[45]|8)|6[237-9]|9[3-9])\d{5}|(?:45|[569]1|818)\d{6}|(?:1|4[12469]|5[3679]|6[56]|7[14]|9[04])\d{7}|21\d{6,7}|(?:23|4[34]|52|64)\d{5,7}|48\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ <exampleNumber>2212345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>8[35-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>850123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>15(?:1[2-9]|[2-9]0|59)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1520123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>18[59]0\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1850123456</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>700\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>700123456</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>76\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>761234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Israel -->
+ <!-- http://www.itu.int/oth/T020200006A/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B972 -->
+ <!-- http://www.wtng.info/wtng-972-il.html -->
+ <!-- http://www.moc.gov.il/new/documents/engineering/MISP0200.ppt (in Hebrew) -->
+ <!-- Formatting practice following wikipedia, and government sites.-->
+ <territory id="IL" countryCode="972" internationalPrefix="0(?:0|1[2-48])"
+ nationalPrefix="0" nationalPrefixFormattingRule="$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2-489]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="([2-489])(\d{3})(\d{4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="[57]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="([57]\d)(\d{3})(\d{4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="1[7-9]"
+ pattern="(1)([7-9]\d{2})(\d{3})(\d{3})">$1-$2-$3-$4</numberFormat>
+ <!-- The following number is for hospitals.-->
+ <numberFormat leadingDigits="125" pattern="(1255)(\d{3})">$1-$2</numberFormat>
+ <numberFormat leadingDigits="120" pattern="(1200)(\d{3})(\d{3})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="121" pattern="(1212)(\d{2})(\d{2})">$1-$2-$3</numberFormat>
+ </availableFormats>
+ <generalDesc >
+ <nationalNumberPattern>[1-57-9]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[2-489]|7[2-46-8])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>5[024679]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>501234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1(?:80[01]\d{3}|255)\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <!-- Peculiarly, one source states that 1956 and 1957 are the new
+ premium rate prefixes. However, no online numbers starting with these
+ prefixes can be found, and this data is not found in any other source.
+ Instead, 1919 numbers are commonly used online for these services, so
+ we support them. -->
+ <!-- 1200 and 1212 numbers are for televoting.-->
+ <nationalNumberPattern>1(?:212|(?:919|200)\d{2})\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ <exampleNumber>1919123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>1(?:700|809)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1700123456</exampleNumber>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>77\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>771234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- India -->
+ <!-- http://www.itu.int/oth/T0202000063/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B91 -->
+ <!-- Note that several changes in area codes have occurred since the
+ numbering plan was released - changes are notified on the www.bsnl.co.in
+ website. Area codes can be verified here at
+ http://www.bsnl.co.in/stdsearch.php. -->
+ <territory id="IN" countryCode="91" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="8(?:0[01589]|1[024]|80)|9"
+ pattern="(\d{2})(\d{2})(\d{6})">$1 $2 $3</numberFormat>
+ <!-- 2 digits area code -->
+ <numberFormat leadingDigits="11|2[02]|33|4[04]|79|80[2-6]"
+ pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 3 digits area code -->
+ <numberFormat
+ leadingDigits="1(?:2[0-249]|3[0-25]|4[145]|5[14]|6[14]|7[1257]|8[1346]|9[14]|[68][1-9])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat
+ leadingDigits="4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="5(?:1[25]|22|3[25]|4[28]|5[12]|6[25]|[78]1|9[15])"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="6(?:12|[2345]1|57|6[13]|7[14]|80)"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91)"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 4 digits area code -->
+ <!-- Fallback for fixed-line numbers. -->
+ <numberFormat leadingDigits="1(?:[2-579]|[68][1-9])|[2-8]"
+ pattern="(\d{4})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1600" nationalPrefixFormattingRule="$FG"
+ pattern="(1600)(\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1800" nationalPrefixFormattingRule="$FG"
+ pattern="(1800)(\d{2,3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- This is a list of the 2 and 3 digit area codes and the first 3
+ digits of 4 digit area codes, so we can check the following digit
+ belongs to one of the operator-codes (2-6). Operator codes from
+ wikipedia, with the addition of 5 (HFCL Infotel). -->
+ <nationalNumberPattern>(?:11|2[02]|33|4[04]|79|80)[2-6]\d{7}|(?:1(?:2[0-249]|3[0-25]|4[145]|5[14]|6[014]|7[1257]|8[01346]|9[14])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:1[25]|22|3[25]|4[28]|5[12]|6[25]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)|7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)|8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91))[2-6]\d{6}|(?:1(?:2[35-8]|3[346-9]|4[236-9]|5[0235-9]|6[235-9]|7[34689]|8[257-9]|9[0235-9])|2(?:1[134689]|3[24-8]|4[2-8]|5[25689]|6[2-4679]|7[13-79]|8[2-479]|9[235-9])|3(?:01|1[79]|2[1-5]|4[25-8]|5[125689]|6[235-7]|7[157-9]|8[2-467])|4(?:1[14578]|2[5689]|3[2-467]|5[4-7]|6[35]|73|8[2689]|9[2389])|5(?:1[146-9]|2[14-8]|3[1346]|4[14-69]|5[46]|6[146-9]|7[2-4]|8[2-8]|9[246])|6(?:1[1358]|2[2457]|3[2-4]|4[235-7]|5[2-689]|6[24-58]|7[23-689]|8[1-6])|7(?:1[013-9]|2[0235-9]|3[2679]|4[1-35689]|5[2-46-9]|[67][02-9]|8[0-8]|9\d)|8(?:1[1357-9]|2[235-8]|3[03-57-9]|4[0-24-9]|5\d|6[2457-9]|7[1-6]|8[1256]|9[2-4]))\d[2-6]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ <exampleNumber>1123456789</exampleNumber>
+ </fixedLine>
+ <!--http://en.wikipedia.org/wiki/Mobile_telephone_numbering_in_India -->
+ <mobile>
+ <!-- According to PhoneFilters tests, digits 3-5 can't be either 000 or 099.
+ -->
+ <nationalNumberPattern>(?:9\d(?:0(?:0[1-9]|9[0-8]|[1-8]\d)|[1-9]\d{2})|8(?:0[01589]|1[024]|80)\d{2})\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- Information gathered from sites such as
+ http://www.surfindia.com/india-facts/toll-free-no.html and
+ http://indmusings.blogspot.com/2008/09/free-help-line-numbersindia.html
+ -->
+ <nationalNumberPattern>1(?:800\d?|600)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <!-- The metadata on premium rate is temporarily commented out as wikipedia says 900 is
+ mobile, conflicting with the national numbering plan.
+ -->
+ <!--
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ -->
+ </territory>
+
+ <!-- British Indian Ocean Territory / Diego Garcia -->
+ <territory id="IO" countryCode="246" internationalPrefix="00">
+ </territory>
+
+ <!-- Iraq -->
+ <!-- http://en.wikipedia.org/wiki/%2B964 -->
+ <!-- http://wtng.info/wtng-964-ik.html -->
+ <territory id="IQ" countryCode="964" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1" pattern="(1)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[2-6]"
+ pattern="([2-6]\d)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7"
+ pattern="(7[5-9]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-7]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>1\d{7}|(?:2[13-5]|3[02367]|4[023]|5[03]|6[026])\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[5-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7912345678</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found. -->
+ </territory>
+
+ <!-- Iran, Islamic Republic of -->
+ <!-- http://en.wikipedia.org/wiki/%2B98 -->
+ <!-- http://www.itu.int/oth/T0202000066/en -->
+ <territory id="IR" countryCode="98" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="21" pattern="(21)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[13-89]|2[02-9]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-8]\d{9}</nationalNumberPattern>
+ <exampleNumber>2123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:1\d|3[1-8])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9123456789</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found. -->
+ </territory>
+
+ <!-- Iceland -->
+ <territory id="IS" countryCode="354" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Italy -->
+ <!-- http://en.wikipedia.org/wiki/%2B39 -->
+ <territory id="IT" countryCode="39" internationalPrefix="00">
+ <availableFormats>
+ <!-- The leading zero for fixed numbers will be prepended before the
+ matching of these regular expressions.-->
+ <numberFormat leadingDigits="0[26]"
+ pattern="(0[26])(\d{3,4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="0[26]" pattern="(0[26])(\d{4})(\d{5})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="0[26]" pattern="(0[26])(\d{6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="0(?:[13-57-9][0159]|36)"
+ pattern="(0\d{2})(\d{3,4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="0(?:[13-57-9][0159]|36)"
+ pattern="(0\d{2})(\d{5,6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="0[13-57-9]" pattern="(0\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="0[13-57-9]" pattern="(0\d{3})(\d{4,6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[13]|84[78]"
+ pattern="(\d{3})(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="800" pattern="(800)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="803" pattern="(803)(\d{3})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="89" pattern="(89\d)(\d{3,6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[01389]\d{5,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>0\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,11}</possibleNumberPattern>
+ <exampleNumber>0212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>3\d{8,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>312345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80(?:0\d{6}|3\d{3})</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>89(?:2\d{3}|9\d{6})</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>899123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>84[78]\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>8481234567</exampleNumber>
+ </sharedCost>
+ <!-- The plan says these should be 6 digits long, but when you go to
+ telephone companies in Italy, such as
+ http://www.gnetwork.it/EmailServizi/Numerazioni178/tabid/91/Default.aspx
+ and when you search for 178 numbers, they seem to all be 7 digits, so we
+ cover both lengths here.-->
+ <personalNumber>
+ <nationalNumberPattern>178\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>1781234567</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Jamaica -->
+ <!-- http://www.itu.int/oth/T020200006C/en -->
+ <territory id="JM" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[89]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>876(?:(?:5[0-26]|6\d|7[1-6]|9[2-8])\d{5}|(?:7(?:0[2-689]|8[056]|9[45])|9(?:0[1-8]|1[02378]|9[2-468]))\d{4})</nationalNumberPattern>
+ <exampleNumber>8765123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>876(?:(?:21|3[02-9]|[48]\d|5[78]|77)\d|7(?:0[07]|8[1-47-9]|9[0-36-9])|9(?:[01]9|9[0579]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8762101234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Jordan -->
+ <!-- http://www.trc.gov.jo/images/stories/pdf/National_Numbering_Plan_ar.pdf (In Arabic) -->
+ <territory id="JO" countryCode="962" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2356]"
+ pattern="([2356])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7[4789]"
+ pattern="(7)(\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4 $5</numberFormat>
+ <numberFormat leadingDigits="70" pattern="(70\d)(\d{6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[89]" pattern="([89]\d{2})(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[235-9]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[2356][2-8])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>62345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7(?:4[5-7]|7[569]|8[5-8]|9[05-7])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>790123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>90012345</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>(?:8[57]\d|810)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>85012345</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>70\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>700123456</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Japan -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006D0001MSWE.doc -->
+ <!-- http://en.wikipedia.org/wiki/Telephone_numbers_in_Japan -->
+ <!-- http://www.japanvisitor.com/index.php?cID=374&pID=754&pName=travel-dialing-codes -->
+ <territory id="JP" countryCode="81" internationalPrefix="010"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[36][1-9]"
+ pattern="(\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[57-9]0"
+ pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 4 digit area code -->
+ <numberFormat leadingDigits="124|4992"
+ pattern="(\d{4})(\d)(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 3 digit area codes that clash with the prefixes of 2 digit area
+ codes and hence are tested for first-->
+ <numberFormat
+ leadingDigits="1(?:38|66)|5(?:32|6[458]|86)|7(?:42|76|98)|852|9(?:42|5[26]|85)"
+ pattern="(\d{3})(\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- 2 digit area codes -->
+ <numberFormat leadingDigits="(?:1[17-9]|[24][2-9]|5[2-589]|60|[79][235-9]|8[26-8])[1-9]"
+ pattern="(\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="(?:12|99)0"
+ pattern="(\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:(?:1[1-9]|9[2-9])[1-9]|(?:[36][1-9]|[24578][2-9])\d)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>312345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[7-9]0\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7012345678</exampleNumber>
+ </mobile>
+ <!-- Toll free and premium rate numbers are not clearly defined in the official Japanese
+ number plan, and do not seem to have been standardized. The information below is
+ collected from searching the web. -->
+ <tollFree>
+ <nationalNumberPattern>120\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>120123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>990\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>990123456</exampleNumber>
+ </premiumRate>
+ <!-- Uncertain on number length allowed here. -->
+ <personalNumber>
+ <nationalNumberPattern>60\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>601234567</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>50\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>5012345678</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Kenya -->
+ <!-- http://www.cck.go.ke/numbering_plan/ -->
+ <!-- http://www.cck.go.ke/UserFiles/File/Premium_Rate_Services.pdf -->
+ <territory id="KE" countryCode="254" internationalPrefix="000"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2-6]" pattern="([2-6]\d)(\d{4,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="7" pattern="(7\d{2})(\d{6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="8|90" pattern="(\d{3})(\d{6,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="91" pattern="(91)(\d{6,7})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{6,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{4,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:20|4[0-6]|5\d|6[0-24-9])\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{4,9}</possibleNumberPattern>
+ <exampleNumber>201234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7(?:1[0-5]|2\d|3[2-8]|5[0-2]|7[023])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>712123456</exampleNumber>
+ </mobile>
+ <!-- There is no document that has the information on the actual length
+ of premium rates and tollfree numbers. The information below comes from
+ research on existing numbers. -->
+ <tollFree>
+ <nationalNumberPattern>8(?:00|88)\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9(?:00|1)\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Kyrgyzstan -->
+ <!-- http://www.itu.int/oth/T0202000074/en -->
+ <territory id="KG" countryCode="996" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="31[25]|[5-8]"
+ pattern="(\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3(?:1[36]|[2-9])" pattern="(\d{4})(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[356-8]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3(?:1(?:2\d|3[1-9]|52|6[1-8])|2(?:22|3[0-479]|6[0-7])|4(?:22|5[6-9]|6[0-4])|5(?:22|3[4-7]|59|6[0-5])|6(?:22|5[35-7]|6[0-3])|7(?:22|3[468]|4[1-8]|59|6\d|7[5-7])|9(?:22|4[1-7]|6[0-8]))|6(?:09|12|2[2-4])\d)\d{5}</nationalNumberPattern>
+ <exampleNumber>312123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>5[124-7]\d{7}|7(?:00|7\d)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>700123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <!-- No premiumRate information can be found.-->
+ </territory>
+
+ <!-- Cambodia -->
+ <!-- http://www.itu.int/oth/T0202000023/en -->
+ <territory id="KH" countryCode="855" internationalPrefix="00[178]"
+ nationalPrefix="0">
+ <availableFormats>
+ <numberFormat leadingDigits="1\d[2-9]|[2-79]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[89]0"
+ pattern="(1[89]00)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-79]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2[3-6]|3[2-6]|4[2-4]|[5-7][2-5])[2-47-9]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>23456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:1[0-25689]|9[1-49])[2-9]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>91234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1800(?:1\d|2[09])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1900(?:1\d|2[09])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Kiribati -->
+ <territory id="KI" countryCode="686" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Comoros -->
+ <territory id="KM" countryCode="269" internationalPrefix="00">
+ </territory>
+
+ <!-- Saint Kitts and Nevis -->
+ <!-- http://www.itu.int/oth/T02020000B0/en -->
+ <territory id="KN" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[89]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>869(?:2(?:29|36)|4(?:6[5-9]|70))\d{4}</nationalNumberPattern>
+ <exampleNumber>8692361234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>869(?:5(?:5[6-8]|6[5-7])|66[2-9]|76[2-5])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8695561234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Korea, Dem. People's Rep. of -->
+ <territory id="KP" countryCode="850" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Korea (Rep. of) -->
+ <!-- http://www.itu.int/oth/T0202000072/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B82 -->
+ <territory id="KR" countryCode="82" internationalPrefix="00(?:[12]|700)"
+ nationalPrefix="0" nationalPrefixForParsing="0(?:8[1-6])?"
+ nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1" pattern="(1\d)(\d{4})(\d{4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="1" pattern="(1\d)(\d{3})(\d{3,4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="21" pattern="(2)(1\d{2,3})">$1-$2</numberFormat>
+ <numberFormat leadingDigits="2[2-9]"
+ pattern="(2)([2-9]\d{2,3})(\d{4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="[3-7]"
+ pattern="([3-7]\d)(\d{3,4})(\d{4})">$1-$2-$3</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(80)(\d{3})(\d{4})">$1-$2-$3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-79]\d{3,9}|8\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{4,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Despite the complex ITU document, I can find no evidence to suggest
+ that numbers starting with two-digit area codes are anything other than
+ 7 or 8 digits long.-->
+ <nationalNumberPattern>2(?:1\d{2,3}|[2367]\d{6,7}|[4589]\d{6})|(?:[34][1-3]|5[13-5]|6[124])\d{7}|(?:52|63)\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{4,10}</possibleNumberPattern>
+ <exampleNumber>22123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1[0-26-9]\d{5,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>801234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>60\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>601234567</exampleNumber>
+ </premiumRate>
+ <personalNumber>
+ <nationalNumberPattern>50\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>501234567</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>70\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>701234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Kuwait -->
+ <!-- http://www.itu.int/oth/T0202000073/en -->
+ <territory id="KW" countryCode="965" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- Format is from http://www.kuwait.com/index.php?option=com_mtree&task=viewlink&link_id=139&Itemid=15 -->
+ <numberFormat leadingDigits="1" pattern="(18\d{2})(\d{3})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="2" pattern="(2[2-5]\d{2})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[69]" pattern="([69]\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="5" pattern="(5[05]\d)(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[12569]\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:18|2[2-5]\d)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>22345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:5[05]|6[05-7]|9[0479])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>50012345</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found. -->
+ </territory>
+
+ <!-- Cayman Islands -->
+ <!-- http://www.itu.int/oth/T0202000027/en -->
+ <territory id="KY" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[389]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:6[6-9]|77)|8(?:00|1[45]|25|4[89]|88)|9(?:14|4[035-9]))\d{4}</nationalNumberPattern>
+ <exampleNumber>3452221234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>345(?:32[3-79]|5(?:1[467]|2[5-7]|4[5-9])|9(?:1[679]|2[4-9]|3[89]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>3453231234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}|345976\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Kazakhstan -->
+ <!-- http://en.wikipedia.org/wiki/Telephone_numbers_in_Kazakhstan -->
+ <territory id="KZ" countryCode="7" internationalPrefix="8~10"
+ nationalPrefix="8" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[6-8]"
+ pattern="([6-8]\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:[67]\d{2}|80[09])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>7(?:1\d[2-7]|2(?:[0-689][2-7]|75[279]))\d{6}</nationalNumberPattern>
+ <exampleNumber>7123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- Wikipedia says that 6xx is used for mobile phone numbers. Other
+ metadata comes from ITU document. -->
+ <nationalNumberPattern>7(?:(?:(?:1[2-578]|2[13-7])9[01]|2758)\d{5}|(?:0[0-257]|6[02-4]|7[57])\d{7})|6\{9}</nationalNumberPattern>
+ <exampleNumber>7129012345</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>809\d{7}</nationalNumberPattern>
+ <exampleNumber>8091234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Lao People's Dem. Rep. -->
+ <!-- http://www.itu.int/oth/T0202000075/en -->
+ <territory id="LA" countryCode="856" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="20"
+ pattern="(20)([2579])(\d{3})(\d{3})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="21|[3-57]"
+ pattern="([2-57]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-57]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[2-57]1|54)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>21212862</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>20[2579]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>202345678</exampleNumber>
+ </mobile>
+ <!-- No information on other types of phone numbers for Lao P.D.R. has been found. -->
+ </territory>
+
+ <!-- Lebanon -->
+ <territory id="LB" countryCode="961" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Saint Lucia -->
+ <!-- http://www.itu.int/oth/T02020000B1/en -->
+ <territory id="LC" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[789]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>758(?:234|4(?:5[0-9]|6[2-9]|8[0-2])|638|758)\d{4}</nationalNumberPattern>
+ <exampleNumber>7582345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>758(?:28[4-7]|384|4(?:6[01]|8[4-9])|5(?:1[89]|20|84)|7(?:1[2-9]|2[034]))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7582845678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Liechtenstein -->
+ <!-- http://www.llv.li/amtsstellen/llv-ak-nummerierung.htm -->
+ <!-- http://www.telecom.li has some different patterns for tollfree and
+ shared cost numbers - look at "Mehrwertnummer". -->
+ <territory id="LI" countryCode="423" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[23]|7[4-9]|87"
+ pattern="(\d{3})(\d{2})(\d{2})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="6" pattern="(6\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[7-9]0"
+ pattern="([7-9]0\d)(\d{2})(\d{2})">$1 $2 $3</numberFormat>
+ <!-- 0800 and 0900 are valid prefixes, but Liechtenstein
+ doesn't have a general national prefix, so we include it manually here
+ when formatting. We can tell whether it needs one by number length.-->
+ <numberFormat leadingDigits="[89]0"
+ pattern="([89]0\d)(\d{2})(\d{2})(\d{2})">0$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:66|80|90)\d{7}|[237-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Regular Cost services are included here as well. -->
+ <nationalNumberPattern>(?:2(?:17|3\d|6[02-58]|96)|3(?:02|7[01357]|8[048]|9[0269])|870)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>2345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>66(?:[0178][0-4]|2[025-9]|[36]\d|4[129]|5[45]|9[019])\d{5}|7(?:4[2-59]|56|[6-9]\d)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>661234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80(?:0(?:07|2[238]|79|\d{4})|9\d{2})\d{2}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>8002222</exampleNumber>
+ </tollFree>
+ <sharedCost>
+ <nationalNumberPattern>90(?:0(?:2[278]|79|\d{4})|1(?:23|\d{4})|6(?:66|\d{4}))\d{2}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>9002222</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>701\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>7011234</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Sri Lanka -->
+ <territory id="LK" countryCode="94" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Liberia -->
+ <territory id="LR" countryCode="231" internationalPrefix="00"
+ nationalPrefix="22">
+ </territory>
+
+ <!-- Lesotho -->
+ <territory id="LS" countryCode="266" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Lithuania -->
+ <!-- http://www.itu.int/oth/T020200007C/en -->
+ <territory id="LT" countryCode="370" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- Two-digit area codes -->
+ <numberFormat leadingDigits="37|4(?:1|5[45]|6[2-4])"
+ pattern="([34]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <!-- Three-digit area codes -->
+ <numberFormat leadingDigits="3[148]|4(?:[24]|6[09])|5(?:[0189]|28)|[689]"
+ pattern="([3-689]\d{2})(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="52[0-79]"
+ pattern="(5)(2[0-79]\d)(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[3-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3[1478]|4[124-6]|52)\d{6}</nationalNumberPattern>
+ <exampleNumber>31234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6\d{7}</nationalNumberPattern>
+ <exampleNumber>61234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{5}</nationalNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[0239]\d{5}</nationalNumberPattern>
+ <exampleNumber>90012345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Luxembourg -->
+ <territory id="LU" countryCode="352" internationalPrefix="00">
+ </territory>
+
+ <!-- Latvia -->
+ <!-- http://www.itu.int/oth/T0202000076/en -->
+ <territory id="LV" countryCode="371" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([2689]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2689]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>6\d{7}</nationalNumberPattern>
+ <exampleNumber>61234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>2\d{7}</nationalNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{6}</nationalNumberPattern>
+ <exampleNumber>80123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{6}</nationalNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Libya (Soc. People’s Libyan Arab Jamahiriya) -->
+ <territory id="LY" countryCode="218" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Morocco -->
+ <territory id="MA" countryCode="212" internationalPrefix="00">
+ </territory>
+
+ <!-- Monaco -->
+ <territory id="MC" countryCode="377" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Moldova, Rep. of -->
+ <territory id="MD" countryCode="373" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Montenegro -->
+ <territory id="ME" countryCode="382" internationalPrefix="99"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Madagascar -->
+ <territory id="MG" countryCode="261" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Marshall Islands -->
+ <territory id="MH" countryCode="692" internationalPrefix="011"
+ nationalPrefix="1">
+ </territory>
+
+ <!-- Macedonia, Former Yugoslav Rep. of -->
+ <territory id="MK" countryCode="389" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Mali -->
+ <territory id="ML" countryCode="223" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Myanmar -->
+ <!-- http://www.itu.int/oth/T0202000092/en -->
+ <territory id="MM" countryCode="95" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="1" pattern="(1)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- This overlaps the previous pattern. -->
+ <numberFormat leadingDigits="13"
+ pattern="(1)(3)(33\d)(\d{3})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="2"
+ pattern="(2)(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[4-8]"
+ pattern="(\d{2})(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Format is from http://www.aitaa.ait.ac.th/chapters/copy17_of_aitaa-national-chapters-1 -->
+ <numberFormat leadingDigits="94" pattern="(9444)(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="9[25689]"
+ pattern="(9)([25689]\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[124-8]\d{5,7}|9\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Fixed satellite network numbers (1 3 33X XXX) are also included here. -->
+ <nationalNumberPattern>(?:1\d|2|4[2-6]|5[2-9]|6\d|7[0-5]|8[1-6])\d{5}|1333\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,8}</possibleNumberPattern>
+ <exampleNumber>1234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:[25689]\d|444)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>92123456</exampleNumber>
+ </mobile>
+ <!-- No information on other types of phone numbers for Myanmar has been found. -->
+ </territory>
+
+ <!-- Mongolia -->
+ <!-- http://www.itu.int/oth/T020200008E/en -->
+ <territory id="MN" countryCode="976" internationalPrefix="001"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[12]1|[7-9]"
+ pattern="([127-9]\d)(\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[12]2[1-3]" pattern="([12]2\d)(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[12](?:27|[3-5]\d)2"
+ pattern="([12]\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[12](?:27|[3-5]\d)[4-9]"
+ pattern="([12]\d{4})(\d{3})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[127-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Note the leading digit is the access code: 1 is used by Mongolia Telecom subscribers
+ and 2 is used by Mongolian Railway subscribers. The area code then follows the access
+ code, and could be 1 to 4 digits long. -->
+ <nationalNumberPattern>(?:[12](?:1\d|2[1-37]|3[2-8]|4[2-68]|5[1-4689])|70)\d{6}</nationalNumberPattern>
+ <exampleNumber>70123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:88|9[1569])\d{6}</nationalNumberPattern>
+ <exampleNumber>88123456</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Macao, China -->
+ <!-- http://www.itu.int/oth/T020200007E/en -->
+ <territory id="MO" countryCode="853" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([268]\d{3})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[268]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:28[2-57-9]|8[2-57-9]\d)\d{5}</nationalNumberPattern>
+ <exampleNumber>28212345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>66\d{6}</nationalNumberPattern>
+ <exampleNumber>66123456</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Northern Mariana Islands -->
+ <!-- http://www.itu.int/oth/T02020000EE/en -->
+ <!-- www.cnmiphonebook.com/ -->
+ <territory id="MP" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[689]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\d))\d{4}</nationalNumberPattern>
+ <exampleNumber>6702345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\d))\d{4}</nationalNumberPattern>
+ <exampleNumber>6702345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Martinique (French Dept. of) -->
+ <territory id="MQ" countryCode="596" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Mauritania -->
+ <territory id="MR" countryCode="222" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Montserrat -->
+ <!-- http://www.itu.int/oth/T020200008F/en -->
+ <territory id="MS" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[689]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>664491\d{4}</nationalNumberPattern>
+ <exampleNumber>6644912345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>664492\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>6644923456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Malta -->
+ <territory id="MT" countryCode="356" internationalPrefix="00"
+ nationalPrefix="21">
+ </territory>
+
+ <!-- Mauritius -->
+ <!-- http://www.itu.int/oth/T0202000088/en - covers mobile only -->
+ <!-- http://www.icta.mu/telecommunications/numbering.htm -->
+ <territory id="MU" countryCode="230" internationalPrefix="020">
+ <!-- There is a proposal to change this to 8 digits - this is supposed to
+ happen August 2010, and 7 digit numbers will be phased out by 1 November
+ 2010. -->
+ <availableFormats>
+ <numberFormat pattern="([2-8]\d{2})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-8]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Wireless local loop numbers are considered to be fixed, since there
+ is almost no roaming capability. -->
+ <nationalNumberPattern>(?:2(?:[034789]\d|1[0-8]|2[0-79])|4(?:[013-8]\d|2[4-7])|[56]\d{2}|8(?:14|3[129]))\d{4}</nationalNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:25\d|4(?:2[12389]|9\d)|7\d{2}|87[15-7]|9[13-8]\d)\d{4}</nationalNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80[012]\d{4}</nationalNumberPattern>
+ </tollFree>
+ <!-- These may be either shared cost or premium rate - they don't
+ differentiate between these in the plan. This is expected to change with
+ the introduction of the new numbering plan in late 2010 - at that time,
+ this will be updated appropriately. -->
+ <premiumRate>
+ <nationalNumberPattern>30\d{5}</nationalNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Maldives -->
+ <territory id="MV" countryCode="960" internationalPrefix="020"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Malawi -->
+ <territory id="MW" countryCode="265" internationalPrefix="00">
+ </territory>
+
+ <!-- Mexico -->
+ <!-- http://www.itu.int/oth/T020200008A/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B52 -->
+ <!-- http://en.wikipedia.org/wiki/Premium-rate_telephone_number#Mexico -->
+ <!-- http://en.wikipedia.org/wiki/Toll-free_telephone_number -->
+ <territory id="MX" countryCode="52" internationalPrefix="0[09]"
+ nationalPrefix="01"
+ nationalPrefixForParsing="0[12]|04[45](\d{10})"
+ nationalPrefixTransformRule="1$1"
+ nationalPrefixFormattingRule="$NP $FG">
+ <!-- When a number starts with 01 or 02, we remove the prefixes; when a
+ number starts with 045 or 046 followed by 10 digits, we replace the
+ prefixes with 1. This way all the mobile numbers, regardless written
+ in international format (leading 1) or national format
+ (leading 045/046), will be parsed into the same form. -->
+ <availableFormats>
+ <numberFormat leadingDigits="33|55|81"
+ pattern="([358]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="33|55|81"
+ pattern="([358]\d)(\d{4})(\d{4})">$1 $2 $3</intlNumberFormat>
+ <numberFormat leadingDigits="[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</intlNumberFormat>
+ <numberFormat leadingDigits="1(?:33|55|81)"
+ nationalPrefixFormattingRule="$FG"
+ pattern="1([358]\d)(\d{4})(\d{4})">045 $1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="1(?:33|55|81)"
+ pattern="(1)([358]\d)(\d{4})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ <numberFormat leadingDigits="1(?:[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9])"
+ nationalPrefixFormattingRule="$FG"
+ pattern="1(\d{3})(\d{3})(\d{4})">045 $1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="1(?:[2467]|3[12457-9]|5[89]|8[2-9]|9[1-35-9])"
+ pattern="(1)(\d{3})(\d{3})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ <numberFormat leadingDigits="[89]0"
+ pattern="([89]00)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="[89]0"
+ pattern="([89]00)(\d{3})(\d{4})">$1 $2 $3</intlNumberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- http://en.wikipedia.org/wiki/Area_codes_in_Mexico_by_code -->
+ <nationalNumberPattern>(?:33|55|81)\d{8}|(?:2(?:2[2-9]|3[1-35-8]|4[13-9]|7[1-689]|8[1-58]|9[467])|3(?:1[1-79]|[2458][1-9]|7[1-8]|9[1-5])|4(?:1[1-57-9]|[24-6][1-9]|[37][1-8]|8[1-35-9]|9[2-689])|5(?:88|9[1-79])|6(?:1[2-68]|[234][1-9]|5[1-3689]|6[12457-9]|7[1-7]|8[67]|9[4-8])|7(?:[13467][1-9]|2[1-8]|5[13-9]|8[1-69]|9[17])|8(?:2[13-689]|3[1-6]|4[124-6]|6[1246-9]|7[1-378]|9[12479])|9(?:1[346-9]|2[1-4]|3[2-46-8]|5[1348]|[69][1-9]|7[12]|8[1-8]))\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>2221234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1(?:(?:33|55|81)\d{8}|(?:2(?:2[2-9]|3[1-35-8]|4[13-9]|7[1-689]|8[1-58]|9[467])|3(?:1[1-79]|[2458][1-9]|7[1-8]|9[1-5])|4(?:1[1-57-9]|[24-6][1-9]|[37][1-8]|8[1-35-9]|9[2-689])|5(?:88|9[1-79])|6(?:1[2-68]|[2-4][1-9]|5[1-3689]|6[12457-9]|7[1-7]|8[67]|9[4-8])|7(?:[13467][1-9]|2[1-8]|5[13-9]|8[1-69]|9[17])|8(?:2[13-689]|3[1-6]|4[124-6]|6[1246-9]|7[1-378]|9[12479])|9(?:1[346-9]|2[1-4]|3[2-46-8]|5[1348]|[69][1-9]|7[12]|8[1-8]))\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>12221234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Malaysia -->
+ <!-- http://en.wikipedia.org/wiki/%2B60 -->
+ <!-- http://www.skmm.gov.my/what_we_do/numbering/index.asp -->
+ <territory id="MY" countryCode="60" internationalPrefix="00"
+ nationalPrefix="0">
+ <availableFormats>
+ <numberFormat leadingDigits="[4-79]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="([4-79])(\d{3})(\d{4})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="3" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(3)(\d{4})(\d{4})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="8" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(8[2-9])(\d{3})(\d{3})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="1[0-46-9][1-9]" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(1\d)(\d{3})(\d{4})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="1[36-8]0"
+ pattern="(1)([36-8]00)(\d{2})(\d{4})">$1-$2-$3-$4</numberFormat>
+ <numberFormat leadingDigits="15" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(154)(\d{3})(\d{4})">$1-$2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[13-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3\d{2}|[4-79]\d|8[2-9])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>312345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1[0-46-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1[38]00\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1300123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1600\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1600123456</exampleNumber>
+ </premiumRate>
+ <personalNumber>
+ <nationalNumberPattern>1700\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1700123456</exampleNumber>
+ </personalNumber>
+ <voip>
+ <nationalNumberPattern>154\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1541234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Mozambique -->
+ <territory id="MZ" countryCode="258" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Namibia -->
+ <territory id="NA" countryCode="264" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- New Caledonia (Territoire français d'outre-mer) -->
+ <territory id="NC" countryCode="687" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Niger -->
+ <territory id="NE" countryCode="227" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Norfolk Island -->
+ <territory id="NF" countryCode="672" internationalPrefix="00">
+ </territory>
+
+ <!-- Nigeria -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T020200009C0001MSWE.doc -->
+ <territory id="NG" countryCode="234" internationalPrefix="009"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[12]"
+ pattern="([12])(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9"
+ pattern="(9)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[3-6]|7(?:[1-79]|0[1-9])|8[2-9]"
+ pattern="([3-8]\d)(\d{3})(\d{2,3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="70[3-9]|8(?:0[1-9]|12)"
+ pattern="([78]\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="702|819"
+ pattern="([78]\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[78]00"
+ pattern="([78]00)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[78]00"
+ pattern="([78]00)(\d{4})(\d{4,5})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[78]00"
+ pattern="([78]00)(\d{5})(\d{5,6})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="78"
+ pattern="(78)(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-69]\d{5,8}|[78]\d{5,13}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,14}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[12]\d{6,7}|9\d{7}|(?:4[023568]|5[02368]|6[02-469]|7[569]|8[2-9])\d{6}|(?:4[47]|5[14579]|6[1578]|7[0-357])\d{5,6}|(?:78|41)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:70[3-9]|8(?:0[2-9]|12))\d{7}|(?:702[1-9]|819[01])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8021234567</exampleNumber>
+ </mobile>
+ <!-- Info on these numbers from http://www.alphatechnologieslimited.com. -->
+ <tollFree>
+ <nationalNumberPattern>800\d{7,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,14}</possibleNumberPattern>
+ <exampleNumber>80017591759</exampleNumber>
+ </tollFree>
+ <personalNumber>
+ <nationalNumberPattern>700\d{7,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,14}</possibleNumberPattern>
+ <exampleNumber>7001234567</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Nicaragua -->
+ <territory id="NI" countryCode="505" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Netherlands -->
+ <!-- http://en.wikipedia.org/wiki/%2B31 -->
+ <!-- http://www2.opta.nl/asp/en/numbers/ -->
+ <territory id="NL" countryCode="31" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1[035]|2[0346]|3[03568]|4[0356]|5[0358]|7|8[458]"
+ pattern="([1-578]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[16-8]|2[259]|3[124]|4[17-9]|5[124679]"
+ pattern="([1-5]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="6" pattern="(6)(\d{8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="80|9" pattern="([89]0\d)(\d{4,7})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[0135-8]|2[02-69]|3[0-68]|4[0135-9]|[57]\d|8[478])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>101234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6[1-58]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>8001234</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[069]\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>9001234</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>85\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </voip>
+ </territory>
+
+ <!-- Norway -->
+ <!-- http://www.npt.no/portal/page/portal/PG_NPT_ENG/PAG_RESOURCES_FREQ/TAB_NUMBERING -->
+ <territory id="NO" countryCode="47" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[489]"
+ pattern="([489]\d{2})(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[235-7]"
+ pattern="([235-7]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- Includes some 810 local-rate numbers, and long-distance rate
+ numbers. -->
+ <nationalNumberPattern>(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7\d)\d{6}|81(?:0(?:0[7-9]|1\d)|5\d{2})\d{3}</nationalNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:4[015-8]|9\d)\d{6}</nationalNumberPattern>
+ <exampleNumber>41234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80[01]\d{5}</nationalNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>82[09]\d{5}</nationalNumberPattern>
+ <exampleNumber>82012345</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>810(?:0[0-6]|[2-8]\d)\d{3}</nationalNumberPattern>
+ <exampleNumber>81021234</exampleNumber>
+ </sharedCost>
+ <personalNumber>
+ <nationalNumberPattern>880\d{5}</nationalNumberPattern>
+ <exampleNumber>88012345</exampleNumber>
+ </personalNumber>
+ </territory>
+
+ <!-- Nepal -->
+ <!-- http://www.itu.int/oth/T0202000095/en -->
+ <!-- http://www.ntc.net.np/mobile/mob_postpaid_number_scheme.php -->
+ <territory id="NP" countryCode="977" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1[4-6]"
+ pattern="(1)([4-6]\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1[01]|[2-8]|9[1-79]"
+ pattern="(\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Format is from http://www.fco.gov.uk/en/travel-and-living-abroad/travel-advice-by-country/country-profile/asia-oceania/nepal/ -->
+ <numberFormat leadingDigits="98"
+ pattern="(98[45])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-8]\d{5,7}|98[45]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[014-6]|2[13-79]|3[135-8]|4[146-9]|5[135-7]|6[13-9]|7[15-9]|8[1-4679]|9[1-79])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>14567890</exampleNumber>
+ </fixedLine>
+ <!-- There is no definitive source of information for mobile numbers in Nepal. The infomation
+ here is collected by searching the Internet. -->
+ <mobile>
+ <nationalNumberPattern>98[45]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9841234567</exampleNumber>
+ </mobile>
+ <!-- No information on other types of phone numbers for Nepal has been found. -->
+ </territory>
+
+ <!-- Nauru -->
+ <territory id="NR" countryCode="674" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Niue -->
+ <territory id="NU" countryCode="683" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- New Zealand -->
+ <!-- http://www.itu.int/oth/T0202000099/en-->
+ <!-- Includes Ross Dependency, Antarctica -->
+ <territory id="NZ" countryCode="64" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[3467]|9[1-9]"
+ pattern="([34679])(\d{3})(\d{4})">$1-$2 $3</numberFormat>
+ <!-- Mobile numbers do not have exclusive leading digits - formatting
+ depends on number length.-->
+ <!-- Vodafone numbers are formatted with 021 separated. -->
+ <numberFormat leadingDigits="21"
+ pattern="(21)(\d{4})(\d{3,4})">$1 $2 $3</numberFormat>
+ <!-- Adding in the toll free numbers here as well since they follow the
+ same format. -->
+ <numberFormat leadingDigits="2[0247-9]|5|[89]00"
+ pattern="([2589]\d{2})(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <!-- Vodafone and Orcon numbers can also be 8 digits (without leading
+ 0), and these are formatted differently. -->
+ <numberFormat leadingDigits="2[019]"
+ pattern="(2[019])(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Antarctica -->
+ <numberFormat leadingDigits="24099"
+ pattern="(24099)(\d{3})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3[2-79]|[479][2-689]|6[235-9])\d{6}|24099\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>32345678</exampleNumber>
+ </fixedLine>
+ <!-- 025 numbers were shut down 31 March 2007, and have been migrated to
+ 027, so are no longer supported. -->
+ <mobile>
+ <nationalNumberPattern>2(?:[027]\d{7}|9\d{6,7}|1(?:0\d{5,7}|[12]\d{5,6}|[3-9]\d{5})|4[1-9]\d{6}|8\d{7,8})</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ <exampleNumber>211234567</exampleNumber>
+ </mobile>
+ <!-- These are the toll free patterns used, by Telecom and Telstra/Clear,
+ but they are referred to as 'Value-added service' in the phone
+ plan for some reason -->
+ <tollFree>
+ <nationalNumberPattern>(?:800|508)\d{6,7}</nationalNumberPattern>
+ <!-- Technically this is 8-10 as per the plan, but current companies
+ support only 9 digit numbers. -->
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <!-- This is the premium rate pattern used, but it is not mentioned in
+ the phone number plan -->
+ <premiumRate>
+ <nationalNumberPattern>900\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Oman -->
+ <!-- http://www.itu.int/oth/T020200009F/en -->
+ <territory id="OM" countryCode="968" internationalPrefix="00" >
+ <availableFormats>
+ <numberFormat leadingDigits="2" pattern="(2\d)(\d{6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="9" pattern="(9\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(800)(7\d{4,5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="5" pattern="(500)(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:2[3-6]|5|9[25-9])\d{6}|800\d{5,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2[3-6]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>23123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9[25-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>92123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- Link to document about toll-free numbers on www.tra.gov.om, which
+ suggests they should be 8007 followed by 4 digits. However, the only
+ examples I can find, including the customer help line for the main
+ telephony company there (omantel), is 8007 followed by 5 digits, so am
+ allowing both for now to be on the safe side. 500 numbers seem to
+ offer international toll-free dialing numbers - +968 500 1300 for
+ international help desk for omantel, for example. -->
+ <nationalNumberPattern>8007\d{4,5}|500\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>80071234</exampleNumber>
+ </tollFree>
+ <!-- No premiumRate information can be found.-->
+ </territory>
+
+ <!-- Panama -->
+ <territory id="PA" countryCode="507" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Peru -->
+ <territory id="PE" countryCode="51" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- French Polynesia (Tahiti) (Territoire français d'outre-mer) -->
+ <territory id="PF" countryCode="689" internationalPrefix="00">
+ </territory>
+
+ <!-- Papua New Guinea -->
+ <!-- http://www.itu.int/oth/T02020000A4/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B675 -->
+ <territory id="PG" countryCode="675" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="[1-689]|73" pattern="(\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="7[126]"
+ pattern="(7[126]\d)(\d{2})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3\d|47|[56]4|73|85|9[78])\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>3123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:6[357-9]|7[126]\d)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>6345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>180\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>1801234</exampleNumber>
+ </tollFree>
+ <voip>
+ <nationalNumberPattern>275\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ <exampleNumber>2751234</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Philippines -->
+ <!-- http://en.wikipedia.org/wiki/%2B63 -->
+ <territory id="PH" countryCode="63" internationalPrefix="00"
+ nationalPrefix="0">
+ <availableFormats>
+ <!--Area code separated from number. Area codes found here:
+ http://en.wikipedia.org/wiki/Telecommunications_in_the_Philippines#Area_Codes-->
+ <numberFormat leadingDigits="2" nationalPrefixFormattingRule="($NP$FG)"
+ pattern="(2)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3(?:230|397|461)|4(?:2(?:35|[46]4|51)|396|4(?:22|63)|59[347]|76[15])|5(?:221|446)|642[23]|8(?:622|8(?:[24]2|5[13]))" nationalPrefixFormattingRule="($NP$FG)"
+ pattern="(\d{4})(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="3469|4(?:279|9(?:30|56))|8834"
+ nationalPrefixFormattingRule="($NP$FG)"
+ pattern="(\d{5})(\d{4})">$1 $2</numberFormat>
+ <!-- This rule is a fallback for the more specific area codes.-->
+ <numberFormat leadingDigits="[3-8]" nationalPrefixFormattingRule="($NP$FG)"
+ pattern="([3-8]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9" nationalPrefixFormattingRule="$NP$FG"
+ pattern="(9\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <!-- Formatting from
+ http://www.uniontelecard.com/calling-guides/philippines/guide1.aspx -->
+ <numberFormat leadingDigits="1"
+ pattern="(1800)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1"
+ pattern="(1800)(\d{1,2})(\d{3})(\d{4})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7,9}|1800\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,13}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2|3[2-68]|4[2-9]|5[2-6]|6[2-58]|7[24578]|8[2-8])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:0[5-9]|1[025-9]|2[0-36-9]|3[235-8]|7[349])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9051234567</exampleNumber>
+ </mobile>
+ <!-- shaopengjia collected the info on tollfree numbers from searching the internet -->
+ <tollFree>
+ <nationalNumberPattern>1800\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11,13}</possibleNumberPattern>
+ <exampleNumber>180012345678</exampleNumber>
+ </tollFree>
+ <!-- No information can be found about other types of numbers (such as
+ premium rate) in the Philippines. -->
+ </territory>
+
+ <!-- Pakistan -->
+ <!-- http://www.itu.int/oth/T02020000A1/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B92 -->
+ <territory id="PK" countryCode="92" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="21|42" pattern="([24]\d)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat
+ leadingDigits="2[25]|4[0146-9]|5[1-35-8]|6[1-8]|7[14]|8[16]|91"
+ pattern="(\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[349]|3|45|54|60|72|8[2-5]|9[2-9]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="89" pattern="([89]00)(\d{3})(\d{2})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:21|42)\d{8}|(?:2(?:[25]|3[2358]|4[2-4]|9[78])|4(?:[0146-9]|5[3479])|5(?:[1-35-8]|4[2-467])|6(?:[1-8]|0[468])|7(?:[14]|2[236])|8(?:[16]|2[2-689]|3[23578]|4[3478]|5[2356])|9(?:1|2[2-8]|3[27-9]|4[2-6]|6[3569]|9[25-8]))\d{7}</nationalNumberPattern>
+ <exampleNumber>2112345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>3[0-6]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>3012345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>90012345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Poland -->
+ <!-- http://en.wikipedia.org/wiki/%2B48 -->
+ <!--
+ http://www.uke.gov.pl/uke/index.jsp?place=Lead24&news_cat_id=277&news_id=3791&layout=9&page=text
+ (in Polish) -->
+ <territory id="PL" countryCode="48" internationalPrefix="0~0"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[124-7]|3[2-4]|8[1-9]"
+ pattern="(\d{2})(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="80"
+ pattern="(80[01])(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="39" pattern="(39\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[2-8]|2[2-59]|3[2-4]|4[1-468]|5[24-689]|6[1-3578]|7[14-7]|8[1-79]|9[145])\d{7}</nationalNumberPattern>
+ <exampleNumber>123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:5[01]|6[069]|7[289]|88)\d{7}</nationalNumberPattern>
+ <exampleNumber>512345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>70\d{7}</nationalNumberPattern>
+ <exampleNumber>701234567</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>801\d{6}</nationalNumberPattern>
+ <exampleNumber>801234567</exampleNumber>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>39\d{7}</nationalNumberPattern>
+ <exampleNumber>391234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Saint Pierre and Miquelon (Collectivité territoriale de la République française) -->
+ <territory id="PM" countryCode="508" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Puerto Rico -->
+ <!-- http://www.itu.int/oth/T02020000AA/en -->
+ <territory id="PR" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[789]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:787|939)[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>7872345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:787|939)[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>7872345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Palestinian Authority -->
+ <territory id="PS" countryCode="970" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Portugal -->
+ <!-- http://www.anacom.pt/render.jsp?categoryId=279098 -->
+ <territory id="PT" countryCode="351" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([2-46-9]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-46-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2(?:[12]\d|[35][1-689]|4[1-59]|6[1-35689]|7[1-9]|8[1-69]|9[1256])\d{6}</nationalNumberPattern>
+ <exampleNumber>212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:[136]\d{2}|2[25-79]\d|4(?:80|9\d))\d{5}</nationalNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>4\d{8}|80[02]\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>71\d{7}</nationalNumberPattern>
+ <exampleNumber>712345678</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>30\d{7}</nationalNumberPattern>
+ <exampleNumber>301234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Palau -->
+ <territory id="PW" countryCode="680" internationalPrefix="011">
+ </territory>
+
+ <!-- Paraguay -->
+ <territory id="PY" countryCode="595" internationalPrefix="002"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Qatar -->
+ <!-- http://www.itu.int/oth/T02020000AB/en -->
+ <!-- http://wtng.info/wtng-qq.html -->
+ <territory id="QA" countryCode="974" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat pattern="([3-8]\d{2})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[3-8]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>4\d{6}</nationalNumberPattern>
+ <exampleNumber>4123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:3[0-5]|[5-7]\d)\d{5}</nationalNumberPattern>
+ <exampleNumber>3123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{5}</nationalNumberPattern>
+ <exampleNumber>8012345</exampleNumber>
+ </tollFree>
+ <!-- No premiumRate information can be found. -->
+ </territory>
+
+ <!-- Réunion (French Departments and Territories in the Indian Ocean) -->
+ <!-- Note this shares the same country code as La Mayotte and French
+ Southern Territories, and the formatting patterns here are used by all of
+ them. -->
+ <!-- http://www.itu.int/oth/T020200004B/en -->
+ <territory id="RE" countryCode="262" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="([268]\d{2})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[268]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- 0876 numbers are mentioned in the plan, but none in use can be
+ found. -->
+ <nationalNumberPattern>262\d{6}</nationalNumberPattern>
+ <exampleNumber>262161234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6(?:9[23]|47)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>692123456</exampleNumber>
+ </mobile>
+ <!-- 08* Numbers in Réunion are the same as those valid in France. -->
+ <tollFree>
+ <nationalNumberPattern>80\d{7}</nationalNumberPattern>
+ <exampleNumber>801234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>8(?:1[01]|2[0156]|84|9[0-37-9])\d{6}</nationalNumberPattern>
+ <exampleNumber>810123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Romania -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000AC0001MSWE.doc -->
+ <!-- http://en.wikipedia.org/wiki/Romania_telephone_area_codes -->
+ <territory id="RO" countryCode="40" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[23]1|7"
+ pattern="([237]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[23][02-9]|[89]"
+ pattern="(\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[237-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[23][3-6]\d{7}</nationalNumberPattern>
+ <exampleNumber>231234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>712345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Serbia -->
+ <!-- http://www.itu.int/oth/T02020000B9/en -->
+ <territory id="RS" countryCode="381" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="(?:2[389]|39)0"
+ pattern="([23]\d{2})(\d{4,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="1|2(?:[0-24-7]|[389][1-9])|3(?:[0-8]|9[1-9])"
+ pattern="([1-3]\d)(\d{5,8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="6" pattern="(6[0-689])(\d{3,10})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="42" pattern="(42)(\d{4,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[89]" pattern="([89]0\d)(\d{3,6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-46-9]\d{4,11}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,12}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-3]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ <exampleNumber>1012345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>6[0-689]\d{3,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,12}</possibleNumberPattern>
+ <exampleNumber>6012345</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{3,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>80012345</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>(?:9[0-2]|42)\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>90012345</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Russian Federation -->
+ <!-- http://www.itu.int/oth/T02020000AD/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B7 -->
+ <territory id="RU" countryCode="7" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP ($FG)">
+ <availableFormats>
+ <!-- Formatting from wikipedia, confirmed on Goverment websites such
+ as http://www.minjust.ru/ru/structure/contact/ -->
+ <numberFormat pattern="([3489]\d{2})(\d{3})(\d{2})(\d{2})">$1 $2-$3-$4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[3489]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <!-- The Ivanovo area code 493 was omitted on the official document, but
+ this is still used in the yellow pages, and on their own website and is
+ listed on wikipedia. This applies also to 395 (Irkutsk). Also including
+ the 840 prefix for Abkhazia.-->
+ <nationalNumberPattern>(?:3(?:0[12]|4[1-35-79]|5[1-3]|8[1-58]|9[0145])|4(?:01|1[1356]|2[13467]|7[1-5]|8[1-7]|9[1-689])|8(?:1[1-8]|2[01]|3[13-6]|4[0-8]|5[15]|6[1-35-7]|7[1-37-9]))\d{7}</nationalNumberPattern>
+ <exampleNumber>3011234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9\d{9}</nationalNumberPattern>
+ <exampleNumber>9123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>809\d{7}</nationalNumberPattern>
+ <exampleNumber>8091234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Rwanda -->
+ <!-- http://www.rura.gov.rw/docs/RWANDA_NATIONAL_NUMBERING_PLAN.pdf -->
+ <territory id="RW" countryCode="250" internationalPrefix="000"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2" nationalPrefixFormattingRule="$FG"
+ pattern="(25\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[7-9]"
+ pattern="([7-9]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[27-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>25\d{7}</nationalNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[258]\d{7}</nationalNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{6}</nationalNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Saudi Arabia -->
+ <!-- http://en.wikipedia.org/wiki/Telephone_numbers_in_Saudi_Arabia -->
+ <!-- http://www.itu.int/oth/T02020000B7/en -->
+ <territory id="SA" countryCode="966" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[1-467]"
+ pattern="([1-467])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9" pattern="(9200)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="5" pattern="(5\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="80" pattern="(800)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="81" pattern="(8111)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[24-7]|2[24-8]|3[35-8]|4[34-68]|6[2-5]|7[235-7])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- Including "Nomadic" numbers from the Telecom Company "Go" -->
+ <nationalNumberPattern>(?:5[013-69]\d|8111)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>512345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9200\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>92001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Solomon Islands -->
+ <territory id="SB" countryCode="677" internationalPrefix="00">
+ </territory>
+
+ <!-- Seychelles -->
+ <territory id="SC" countryCode="248" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Sudan -->
+ <territory id="SD" countryCode="249" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Sweden -->
+ <!-- http://www.pts.se/upload/Ovrigt/Tele/Nummerfragor/Sv_nrplan_telefoni_enl_TU-T_rek_E.164.pdf -->
+ <!-- Formatting patterns are from that document and from the Swedish yellow
+ pages http://gulasidorna.eniro.se -->
+ <territory id="SE" countryCode="46" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="8"
+ pattern="(8)(\d{2,3})(\d{2,3})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="1[013689]|2[136]|3[1356]|4[0246]|54|6[03]|90"
+ pattern="([1-69]\d)(\d{2,3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="1[13689]|2[136]|3[1356]|4[0246]|54|6[03]|90"
+ pattern="([1-69]\d)(\d{3})(\d{2})">$1 $2 $3</numberFormat>
+ <numberFormat
+ leadingDigits="1[2457]|2[2457-9]|3[0247-9]|4[1357-9]|5[0-35-9]|6[124-9]|9(?:[125-8]|3[0-5]|4[0-3])"
+ pattern="(\d{3})(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat
+ leadingDigits="1[2457]|2[2457-9]|3[0247-9]|4[1357-9]|5[0-35-9]|6[124-9]|9(?:[125-8]|3[0-5]|4[0-3])"
+ pattern="(\d{3})(\d{2,3})(\d{2})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7[02-46]"
+ pattern="(7[02-46])(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="20"
+ pattern="(20)(\d{2,3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="20"
+ pattern="(20)(\d{2,3})(\d{2})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9[034]"
+ pattern="(9[034]\d)(\d{2})(\d{2})(\d{3})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>1(?:0[1-8]\d{6}|[136]\d{5,7}|(?:2[0-35]|4[0-4]|5[0-25-9]|7[13-6]|[89]\d)\d{5,6})|2(?:[136]\d{5,7}|(?:2[0-7]|4[0136-8]|5[0-38]|7[018]|8[01]|9[0-57])\d{5,6})|3(?:[356]\d{5,7}|(?:0[0-4]|1\d|2[0-25]|4[056]|7[0-2]|8[0-3]|9[023])\d{5,6})|4(?:[0246]\d{5,7}|(?:1[01-8]|3[0135]|5[14-79]|7[0-246-9]|8[0156]|9[0-689])\d{5,6})|5(?:0[0-6]|1[1-5]|2[0-68]|3[0-4]|4\d|5[0-5]|6[03-5]|7[013]|8[0-79]|9[01])\d{5,6}|6(?:[03]\d{5,7}|(?:1[1-3]|2[0-4]|4[02-57]|5[0-37]|6[0-3]|7[0-2]|8[0247]|9[0-356])\d{5,6})|8\d{6,8}|9(?:0\d{5,7}|(?:1[0-68]|2\d|3[02-59]|4[0-4]|5[0-4]|6[01]|7[0135-8]|8[01])\d{5,6})</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ <exampleNumber>8123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[02-46]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>701234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>20\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ <exampleNumber>201234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9(?:00|39|44)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Singapore -->
+ <!-- http://www.ida.gov.sg/policies%20and%20regulation/20060508120124.aspx -->
+ <territory id="SG" countryCode="65" internationalPrefix="0[0-3][0-9]">
+ <availableFormats>
+ <numberFormat leadingDigits="[369]|8[1-9]"
+ pattern="([3689]\d{3})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="1[89]"
+ pattern="(1[89]00)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="80"
+ pattern="(800)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[13689]\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[36]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>31234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[89]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>81234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1?800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ <exampleNumber>18001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ <exampleNumber>19001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Saint Helena -->
+ <territory id="SH" countryCode="290" internationalPrefix="00">
+ </territory>
+
+ <!-- Slovenia -->
+ <!-- http://www.itu.int/oth/T02020000BE/en -->
+ <territory id="SI" countryCode="386" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[12]|3[4-8]|4[24-8]|5[4-8]|7[3-8]"
+ pattern="(\d)(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[347][01]|51|64"
+ pattern="([3-7]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[89]" pattern="([89]0)(\d{4,6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{5,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-57]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ <exampleNumber>1123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:[347][01]|51|64)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>31234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{4,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>80123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{4,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>90123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Slovakia -->
+ <!-- http://www.itu.int/oth/T02020000BD/en -->
+ <territory id="SK" countryCode="421" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2"
+ pattern="(2)(\d{3})(\d{3})(\d{2})">$1/$2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[3-5]"
+ pattern="([3-5]\d)(\d{3})(\d{2})(\d{2})">$1/$2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="[689]"
+ pattern="([689]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-689]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-5]\d{8}</nationalNumberPattern>
+ <exampleNumber>212345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <!-- 948 isn't in the number pattern, but many examples using this have
+ been found, so deeming it valid for now.-->
+ <nationalNumberPattern>9(?:0[1-8]|1[0-24-9]|4[0489])\d{6}</nationalNumberPattern>
+ <exampleNumber>912123456</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9(?:[78]\d{7}|00\d{6})</nationalNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>8[5-9]\d{7}</nationalNumberPattern>
+ <exampleNumber>850123456</exampleNumber>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>6(?:5[0-4]|9[0-6])\d{6}</nationalNumberPattern>
+ <exampleNumber>690123456</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Sierra Leone -->
+ <territory id="SL" countryCode="232" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- San Marino -->
+ <territory id="SM" countryCode="378" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Senegal -->
+ <!-- http://www.itu.int/oth/T02020000B8/en -->
+ <territory id="SN" countryCode="221" internationalPrefix="00">
+ <availableFormats>
+ <!-- Using yellow pages and online telecom company formatting, rather
+ than that implied in the national numbering plan. -->
+ <numberFormat pattern="(\d{2})(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[37]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>3(?:010|3(?:8[1-9]|9[2-9]))\d{5}</nationalNumberPattern>
+ <exampleNumber>301012345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7(?:0[1256]0|6(?:1[23]|2[89]|3[3489]|4[6-9]|5[1-389]|6[6-9]|7[45]|8[3-8])|7(?:1[014-8]|2[0-7]|3[0-35-8]|4[0-6]|[56]\d|7[0-389]|[89][01]))\d{5}</nationalNumberPattern>
+ <exampleNumber>701012345</exampleNumber>
+ </mobile>
+ <voip>
+ <nationalNumberPattern>33301\d{4}</nationalNumberPattern>
+ <exampleNumber>333011234</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Somalia -->
+ <territory id="SO" countryCode="252" internationalPrefix="00">
+ </territory>
+
+ <!-- Suriname -->
+ <territory id="SR" countryCode="597" internationalPrefix="00">
+ </territory>
+
+ <!-- Sao Tome and Principe -->
+ <territory id="ST" countryCode="239" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- El Salvador -->
+ <territory id="SV" countryCode="503" internationalPrefix="00">
+ </territory>
+
+ <!-- Syrian Arab Republic -->
+ <!-- http://www.itu.int/oth/T02020000C9/en -->
+ <territory id="SY" countryCode="963" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[13]"
+ pattern="([13]\d)(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[245]"
+ pattern="([245]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9"
+ pattern="(9[3-689])(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-59]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1(?:|1\d?|4\d|[2356])|2[1-35]|3(?:1\d|[34])|4[13]|5[1-3])\d{6}</nationalNumberPattern>
+ <exampleNumber>112345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9(?:3[23]|4[47]|55|66|88|99)\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>944567890</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found. -->
+ </territory>
+
+ <!-- Swaziland -->
+ <territory id="SZ" countryCode="268" internationalPrefix="00">
+ </territory>
+
+ <!-- Turks and Caicos Islands -->
+ <!-- http://www.itu.int/oth/T02020000D8/en -->
+ <territory id="TC" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[689]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>649(?:712|9(?:4\d|50))\d{4}</nationalNumberPattern>
+ <exampleNumber>6497121234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>649(?:2(?:3[12]|4[1-5])|3(?:3[1-39]|4[1-57])|4[34][12])\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>6492311234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>64971[01]\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>6497101234</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Chad -->
+ <territory id="TD" countryCode="235" internationalPrefix="15">
+ </territory>
+
+ <!-- French Southern Territories -->
+ <territory id="TF" countryCode="262" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Togo -->
+ <territory id="TG" countryCode="228" internationalPrefix="00">
+ </territory>
+
+ <!-- Thailand -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000CD0001MSWE.doc -->
+ <territory id="TH" countryCode="66" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- Formatting patterns from wikipedia and the document itself -
+ http://en.wikipedia.org/wiki/%2B66 -->
+ <numberFormat leadingDigits="2" pattern="(2)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="6" pattern="(60)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[3-57]"
+ pattern="([3-57]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(8)(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1" nationalPrefixFormattingRule="$FG"
+ pattern="(1[89]00)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-8]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2[1-9]|3[24-9]|4[2-5]|5[3-6]|7[3-7])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>8[13-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>812345678</exampleNumber>
+ </mobile>
+ <!-- http://en.wikipedia.org/wiki/Toll-free_telephone_number -->
+ <tollFree>
+ <nationalNumberPattern>1800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1900\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>1900123456</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>60\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>601234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Tajikistan -->
+ <!-- http://www.itu.int/oth/T02020000CA/en -->
+ <territory id="TJ" countryCode="992" internationalPrefix="8~10"
+ nationalPrefix="8" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[34]7|91[78]"
+ pattern="([349]\d{2})(\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="4[48]" pattern="(4[48])(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3317" pattern="(331700)(\d)(\d{2})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3(?:[1245]|3(?:[02-9]|1[0-589])"
+ pattern="(\d{4})(\d)(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9(?:19|[235-9])"
+ pattern="(9\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[349]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3(?:1[3-5]|2[245]|31|4[24-7]|5[25]|72)|4(?:46|74|87))\d{6}</nationalNumberPattern>
+ <exampleNumber>372123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9[1-35-9]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>917123456</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Tokelau -->
+ <territory id="TK" countryCode="690" internationalPrefix="00">
+ </territory>
+
+ <!-- Timor-Leste -->
+ <territory id="TL" countryCode="670" internationalPrefix="00">
+ </territory>
+
+ <!-- Turkmenistan -->
+ <!-- http://www.itu.int/oth/T02020000D7/en -->
+ <territory id="TM" countryCode="993" internationalPrefix="8~10"
+ nationalPrefix="8" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- There doesn't seem to be a standardized format. The format below is based on the
+ Turkmenistan embassy at
+ http://www.turkmenistanembassy.org/turkmen/info/contact.html-->
+ <numberFormat pattern="([1-5]\d)(\d{2})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:12\d|243|[3-5]22)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ <exampleNumber>12345678</exampleNumber>
+ </generalDesc>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Tunisia -->
+ <territory id="TN" countryCode="216" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Tonga -->
+ <territory id="TO" countryCode="676" internationalPrefix="00">
+ </territory>
+
+ <!-- Turkey -->
+ <!-- http://en.wikipedia.org/wiki/%2B90 -->
+ <!-- http://www.itu.int/oth/T02020000D6/en -->
+ <territory id="TR" countryCode="90" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="([2-589]\d{2})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-589]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-4]\d{9}|850\d{7}</nationalNumberPattern>
+ <exampleNumber>2123456789</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>5\d{9}</nationalNumberPattern>
+ <exampleNumber>5123456789</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <exampleNumber>8001234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <exampleNumber>9001234567</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Trinidad and Tobago -->
+ <!-- http://www.itu.int/oth/T02020000D4/en -->
+ <territory id="TT" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>[89]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>868(?:22[1-4]|6(?:1[4-6]|[2-6]\d|7[0-79]|9[0-8])|82[12])\d{4}</nationalNumberPattern>
+ <exampleNumber>8682211234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>868(?:29\d|3(?:0[1-9]|1[02-9]|[2-9]\d)|4([679]\d|8[0-4])|6(?:20|78|8\d)|7(?:1[02-9]|[2-9]\d))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8682911234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Tuvalu -->
+ <territory id="TV" countryCode="688" internationalPrefix="00">
+ </territory>
+
+ <!-- Taiwan, China -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000EB0003MSWE.doc -->
+ <!-- Extension symbols found on the internet so far have been #, X and Ext -
+ so # has been chosen as the preferred extension prefix. -->
+ <territory id="TW" countryCode="886" internationalPrefix="0(?:0[25679]|19)"
+ nationalPrefix="0" preferredExtnPrefix="#" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[2-7]|8[1-9]"
+ pattern="([2-8])(\d{3,4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="80|9"
+ pattern="([89]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-8]\d{7,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>21234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Tanzania -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000CB0001MSWE.doc -->
+ <territory id="TZ" countryCode="255" internationalPrefix="00[056]"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[24]" pattern="([24]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[67]"
+ pattern="([67]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Formatting for special numbers from www.tcra.go.tz -->
+ <numberFormat leadingDigits="[89]"
+ pattern="([89]\d{2})(\d{2})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>2[2-8]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ <exampleNumber>222345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:6[158]|7[1-9])(\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80[08]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>8(?:40|6[01])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>840123456</exampleNumber>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>41\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>412345678</exampleNumber>
+ </voip>
+ </territory>
+
+ <!-- Ukraine -->
+ <!-- http://www.itu.int/oth/T02020000DB/en -->
+ <!-- http://en.wikipedia.org/wiki/%2B380 -->
+ <territory id="UA" countryCode="380" internationalPrefix="0~0"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- City codes separated out. No definitive list has been found of what
+ constitutes the area code - http://www.ua.all-biz.info/guide/phonecodes
+ is useful but not error-free. Have used local yellow pages guidelines,
+ Google searches and regression tests to reverse-engineer these rules.
+ -->
+ <numberFormat leadingDigits="39|4(?:[45][0-5]|87)|5(?:0|7[37])|6[36-8]|9[1-9]"
+ pattern="([3-69]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat
+ leadingDigits="3(?:[1-46-8]2[013-9]|52)|4[1378]2|5(?:[124-7]2|64)|6(?:[49]2|[12][29]|5[24])|8|90"
+ pattern="([3-689]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat
+ leadingDigits="3(?:5[013-9]|[1-46-8](?:22|[013-9]))|4(?:[137][013-9]|6|[45][6-9]|8[4-6])|5(?:[1245][013-9]|6[0135-9]|3|7[4-6])|6(?:[49][013-9]|5[0135-9]|[12][13-8])"
+ pattern="([3-6]\d{3})(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[3-689]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:3[1-8]|4[13-8]|5[1-7]|6[12459])\d{7}</nationalNumberPattern>
+ <exampleNumber>311234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:39|50|6[36-8]|9[1-9])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>391234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Uganda -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000F10001MSWE.doc -->
+ <!-- http://www.ucc.co.ug/licensing/ugandaNumberingPlan.pdf -->
+ <territory id="UG" countryCode="256" internationalPrefix="00[057]"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[7-9]|200|4(?:6[45]|[7-9])"
+ pattern="([247-9]\d{2})(\d{6})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="3|4(?:[1-5]|6[0-36-9])"
+ pattern="([34]\d)(\d{7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="202" pattern="(2024)(\d{5})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>3\d{8}|4(?:[1-6]\d|7[136]|8[1356]|96)\d{6}|20(?:0\d|24)\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,9}</possibleNumberPattern>
+ <exampleNumber>312345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7(?:[1578]\d|0[0-4])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>712345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800[123]\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>90[123]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>901123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- United States -->
+ <!-- http://www.nanpa.com/reports/reports_npa.html -->
+ <!-- http://en.wikipedia.org/wiki/North_American_Numbering_Plan -->
+ <!-- Note the national prefix of US is the same as its country code, and when formatting phone
+ numbers in the national format, it is not included. Therefore, we omit it here to make
+ formatting consistent with the rest of the world. The same applies to all the
+ countries/regions under NANPA -->
+ <territory id="US" countryCode="1" internationalPrefix="011">
+ <availableFormats>
+ <numberFormat pattern="(\d{3})(\d{3})(\d{4})">($1) $2-$3</numberFormat>
+ <numberFormat pattern="(\d{3})(\d{4})">$1-$2</numberFormat>
+ <!-- A different pattern is used when formatting internationally, as
+ the area code is no longer optional and should not be in brackets. -->
+ <intlNumberFormat pattern="(\d{3})(\d{3})(\d{4})">$1-$2-$3</intlNumberFormat>
+ <intlNumberFormat pattern="(\d{3})(\d{4})">$1-$2</intlNumberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|69|7[089]|8[04])|5(?:0[1-57-9]|1[0235-8]|[23]0|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[167]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>2012345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|69|7[089]|8[04])|5(?:0[1-57-9]|1[0235-8]|[23]0|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[167]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\d{6}</nationalNumberPattern>
+ <exampleNumber>2012345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Uruguay -->
+ <territory id="UY" countryCode="598" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Uzbekistan -->
+ <!-- http://www.itu.int/oth/T02020000E1/en -->
+ <territory id="UZ" countryCode="998" internationalPrefix="8~10"
+ nationalPrefix="8" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="([679]\d)(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[679]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:6[125679]|7[1-69])\d{7}</nationalNumberPattern>
+ <exampleNumber>612345678</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9[0-37-9]\d{7}</nationalNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+
+ <!-- Saint Vincent and the Grenadines -->
+ <!-- http://www.itu.int/oth/T02020000B3/en -->
+ <territory id="VC" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>(?:784|8(?:00|66|77|88)|900)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>784(?:266|3(?:6[6-9]|7\d|8[0-24-6])|4(?:38|5[0-36-8]|8\d|9[01])|555|638|784)\d{4}</nationalNumberPattern>
+ <exampleNumber>7842661234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>784(?:4(?:3[0-24]|5[45]|9[2-5])|5(?:2[6-9]|3[0-3]|93))\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>7844301234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Venezuela -->
+ <territory id="VE" countryCode="58" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Virgin Islands, British -->
+ <!-- http://www.itu.int/oth/T020200001E/en -->
+ <territory id="VG" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>(?:284|8(?:00|66|77|88)|900)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>284(?:(?:229|4(?:46|9[45])|8(?:52|6[459]))\d{4}|496[0-5]\d{3})</nationalNumberPattern>
+ <exampleNumber>2842291234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>284(?:(?:30[0-3]|4(?:4[0-5]|68|99)|54[0-4])\d{4}|496[6-9]\d{3})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>2843001234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(?:00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Virgin Islands, United States -->
+ <!-- http://www.itu.int/oth/T02020000DF/en -->
+ <territory id="VI" countryCode="1" internationalPrefix="011">
+ <generalDesc>
+ <!-- NANPA country - uses US formatting rules -->
+ <nationalNumberPattern>340(?:6[49]2|7[17]\d)\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <exampleNumber>3406421234</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <exampleNumber>3406421234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(00|66|77|88)[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>8002345678</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900[2-9]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ <exampleNumber>9002345678</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Viet Nam (Vietnam) -->
+ <!-- http://www.itu.int/oth/T02020000E4/en -->
+ <territory id="VN" countryCode="84" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="[48]" pattern="([48])(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[025-79]|3[0136-9]|5[2-9]|6[0-46-9]|7[02-79]"
+ pattern="([235-7]\d)(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="2[1348]|3[25]|5[01]|65|7[18]"
+ pattern="([235-7]\d{2})(\d{4})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9"
+ pattern="(9[0-8])(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="1(?:[26]|99)"
+ pattern="(1[269]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:8|90)" nationalPrefixFormattingRule="$FG"
+ pattern="(1[89]00)(\d{4,6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-8]\d{6,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>2123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:9[0-8]|1(?:2[1-369]|6[46-9]|99))\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ <exampleNumber>912345678</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1800\d{4,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ <exampleNumber>1800123456</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1900\d{4,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ <exampleNumber>1900123456</exampleNumber>
+ </premiumRate>
+ </territory>
+
+ <!-- Vanuatu -->
+ <territory id="VU" countryCode="678" internationalPrefix="00">
+ </territory>
+
+ <!-- Wallis and Futuna (Territoire français d'outre-mer) -->
+ <territory id="WF" countryCode="681" internationalPrefix="19">
+ </territory>
+
+ <!-- Samoa -->
+ <!-- http://www.itu.int/oth/T02020000B4/en -->
+ <territory id="WS" countryCode="685" internationalPrefix="0"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- Should be formatted in one block, apart from the specific series
+ below. For this reason the leadingDigits is more detailed than would
+ appear necessary. -->
+ <numberFormat leadingDigits="840" pattern="(840)(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="7[25-7]" pattern="(7[25-7])(\d{5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="800" pattern="(800)(\d{3})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-8]\d{4,6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,7}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[2-5]\d|6[1-9]|840\d)\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,7}</possibleNumberPattern>
+ <exampleNumber>22123</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:60|7[25-7]\d)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,7}</possibleNumberPattern>
+ <exampleNumber>601234</exampleNumber>
+ </mobile>
+ <tollFree>
+ <!-- The 800 number series is new, and is used by companies such as the
+ ANZ bank in Samoa to provide 24 hour eMerchant support. It is marked as
+ "Customized Services" in the plan for now, so may be also used for other
+ purposes than toll free, but until we have further evidence of these we
+ will keep it as toll free.-->
+ <nationalNumberPattern>800\d{3}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6}</possibleNumberPattern>
+ <exampleNumber>800123</exampleNumber>
+ </tollFree>
+ <!-- Current research suggests other types of numbers are not used in
+ Samoa.-->
+ </territory>
+
+ <!-- Yemen -->
+ <!-- http://www.itu.int/oth/T02020000E7/en -->
+ <territory id="YE" countryCode="967" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="1[2-68]|[2-6]|7[24-68]"
+ pattern="([1-7])(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="17"
+ pattern="(1)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="7[137]"
+ pattern="(7[137]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-7]\d{6,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1(?:7\d|[2-68])|2[2-68]|3[2358]|4[2-58]|5[2-6]|6[3-58]|7[24-68])\d{5}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,8}</possibleNumberPattern>
+ <exampleNumber>1234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[137]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>712345678</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found. -->
+ </territory>
+
+ <!-- Mayotte -->
+ <territory id="YT" countryCode="262" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- South Africa -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000C10001PDFE.pdf -->
+ <!-- http://en.wikipedia.org/wiki/Telephone_numbers_in_South_Africa -->
+ <territory id="ZA" countryCode="27" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="([1-578]\d)(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[0-8]|2[1-478]|3[1-69]|4\d|5[1346-8])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,9}</possibleNumberPattern>
+ <exampleNumber>101234567</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:7[1-4689]|8[1-5789])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>711234567</exampleNumber>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>801234567</exampleNumber>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>86\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>861234567</exampleNumber>
+ </premiumRate>
+ <voip>
+ <nationalNumberPattern>87\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ <exampleNumber>871234567</exampleNumber>
+ </voip>
+ </territory>
+
+ <!--Zambia -->
+ <territory id="ZM" countryCode="260" internationalPrefix="00"
+ nationalPrefix="0">
+ </territory>
+
+ <!-- Zimbabwe -->
+ <!-- http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000E90001MSWE.doc -->
+ <territory id="ZW" countryCode="263" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <!-- One-digit area codes -->
+ <numberFormat leadingDigits="4|9[2-9]"
+ pattern="([49])(\d{3})(\d{2,5})">$1 $2 $3</numberFormat>
+ <!-- Mobile numbers -->
+ <numberFormat leadingDigits="[19]1|7"
+ pattern="([179]\d)(\d{3})(\d{3,5})">$1 $2 $3</numberFormat>
+ <!-- Two-digit area codes -->
+ <numberFormat
+ leadingDigits="1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])"
+ pattern="([1-356]\d)(\d{3,5})">$1 $2</numberFormat>
+ <numberFormat
+ leadingDigits="1[3-9]|2(?:[1-469]|0[0-35-9]|[45][0-79])|3(?:0[0-79]|1[0-689]|[24-69]|3[0-69])|5(?:[02-46-9]|[15][0-69])|6(?:[0145]|[29][0-79]|3[0-689]|[68][0-69])"
+ pattern="([1-356]\d)(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Three-digit area codes -->
+ <numberFormat
+ leadingDigits="2(?:[278]|0[45]|48)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])"
+ pattern="([2356]\d{2})(\d{3,5})">$1 $2</numberFormat>
+ <numberFormat
+ leadingDigits="2(?:[278]|0[45]|48)|3(?:08|17|3[78]|[78])|5[15][78]|6(?:[29]8|37|[68][78])"
+ pattern="([2356]\d{2})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <!-- Four-digit area codes -->
+ <numberFormat leadingDigits="258[23]|5483"
+ pattern="([25]\d{3})(\d{3,5})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="258[23]|5483"
+ pattern="([25]\d{3})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(?:[19]1|23)\d{3,8}|[1-69]\d{4,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:1[346-8]|2(?:0[45]|2[28]|48|58[23]|[69]|7[2-46-8]|8[13-9])|3(?:08?|17?|3[78]|[45]|7[1569]|8[379])|5(?:18|483|[57-9])|6(?:37?|[459]|88)|848)\d{3,6}|(?:2(?:27|5|7[159]|82)|39|5[346]|6[16-8])\d{4,6}|2(?:0|70)\d{5,6}|(?:9[2-8]|4\d)\d{4,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,10}</possibleNumberPattern>
+ <exampleNumber>1312345</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>(?:[19]1|73)\d{3,8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{3,10}</possibleNumberPattern>
+ <exampleNumber>11123456</exampleNumber>
+ </mobile>
+ <!-- No tollFree or premiumRate information can be found.-->
+ </territory>
+ </territories>
+</phoneNumberMetadata>
diff --git a/java/resources/com/google/i18n/phonenumbers/src/generated_files/PhoneNumberMetadataProto b/java/resources/com/google/i18n/phonenumbers/src/generated_files/PhoneNumberMetadataProto
new file mode 100644
index 0000000..1c6227f
--- /dev/null
+++ b/java/resources/com/google/i18n/phonenumbers/src/generated_files/PhoneNumberMetadataProto
Binary files differ
diff --git a/java/resources/com/google/i18n/phonenumbers/test/PhoneNumberMetaDataForTesting.xml b/java/resources/com/google/i18n/phonenumbers/test/PhoneNumberMetaDataForTesting.xml
new file mode 100644
index 0000000..21d2da3
--- /dev/null
+++ b/java/resources/com/google/i18n/phonenumbers/test/PhoneNumberMetaDataForTesting.xml
@@ -0,0 +1,381 @@
+<!-- Copyright (C) 2009 Google Inc.
+
+ 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.
+
+ @author: Shaopeng Jia
+
+ MetaData on Phone Number Plan and formatting rules. This file is used
+ solely for the purpose of unittesting, so data in this file is not
+ necessarily consistent with that of PhoneNumberMetaData.xml
+-->
+
+<phoneNumberMetadata>
+ <territories>
+ <!-- Andorra -->
+ <territory id="AD" countryCode="376" internationalPrefix="00">
+ </territory>
+
+ <!-- Argentina -->
+ <territory id="AR" countryCode="54" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG"
+ nationalPrefixForParsing="0(?:(11|343|3715)15)?"
+ nationalPrefixTransformRule="9$1">
+ <!-- Note in nationalPrefixForParsing, the areacode (such as 11, 343, etc.), when present in
+ front of carrier selection code 15, is captured to replace $1 in
+ nationalPrefixTransformRule -->
+ <availableFormats>
+ <numberFormat leadingDigits="11" pattern="(\d{2})(\d{4})(\d{4})">$1 $2-$3</numberFormat>
+ <numberFormat leadingDigits="1[02-9]|[23]" pattern="(\d{4})(\d{2})(\d{4})">$1 $2-$3</numberFormat>
+ <numberFormat leadingDigits="911" pattern="9(11)(\d{4})(\d{4})">$1 15 $2-$3</numberFormat>
+ <numberFormat leadingDigits="9(?:1[02-9]|[23])" pattern="9(\d{4})(\d{2})(\d{4})">$1 15 $2-$3</numberFormat>
+ <numberFormat leadingDigits="[68]" pattern="(\d{3})(\d{3})(\d{4})">$1-$2-$3</numberFormat>
+ <intlNumberFormat leadingDigits="11" pattern="(\d{2})(\d{4})(\d{4})">$1 $2-$3</intlNumberFormat>
+ <intlNumberFormat leadingDigits="1[02-9]|[23]" pattern="(\d{4})(\d{2})(\d{4})">$1 $2-$3</intlNumberFormat>
+ <intlNumberFormat leadingDigits="911" pattern="(9)(11)(\d{4})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ <intlNumberFormat leadingDigits="9(?:1[02-9]|[23])" pattern="(9)(\d{4})(\d{2})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ <intlNumberFormat leadingDigits="[68]" pattern="(\d{3})(\d{3})(\d{4})">$1-$2-$3</intlNumberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-3689]\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-3]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>9\d{10}|[1-3]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>6(0\d|10)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Australia -->
+ <territory id="AU" countryCode="61" internationalPrefix="001[12]"
+ nationalPrefix="0" preferredInternationalPrefix="0011"
+ nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat nationalPrefixFormattingRule="$FG" leadingDigits="1" pattern="(\d{4})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[2-478]" pattern="(\d{1})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc >
+ <nationalNumberPattern>[1-578]\d{4,14}</nationalNumberPattern>
+ <possibleNumberPattern>\d{5,15}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2378]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>4\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1800\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>190[0126]\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Bahamas -->
+ <territory id="BS" countryCode="1" internationalPrefix="011">
+ <availableFormats>
+ <numberFormat pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>(242|8(00|66|77|88)|900)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3-57]|9[2-5])|4(?:2[237]|51|64|77)|502|636|702)\d{4}</nationalNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>242(357|359|457|557)\d{4}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>8(00|66|77|88)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Germany -->
+ <territory id="DE" countryCode="49" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="2|3[3-9]|906|[4-9][1-9]1" pattern="(\d{3})(\d{3,8})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[34]0|[68]9" pattern="(\d{2})(\d{4,9})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="[4-9]" pattern="([4-9]\d{3})(\d{2,7})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="800" pattern="(\d{3})(\d{1})(\d{6})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="900[135]" pattern="(\d{3})(\d{3})(d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="9009" pattern="(\d{3})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{4,14}</nationalNumberPattern>
+ <possibleNumberPattern>\d{2,14}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>(?:[24-6]\d{2}|3[03-9]\d|[789](?:[1-9]\d|0[2-9]))\d{3,8}</nationalNumberPattern>
+ <exampleNumber>30123456</exampleNumber>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1(5\d{9}|7\d{8}|6[02]\d{8}|63\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900([135]\d{6}|9\d{7})</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- United Kingdom -->
+ <territory id="GB" countryCode="44" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="($NP$FG)">
+ <availableFormats>
+ <numberFormat leadingDigits="[1-59]|[78]0"
+ pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="6"
+ pattern="(\d)(\d{3})(\d{3})(\d{3})">$1 $2 $3 $4</numberFormat>
+ <numberFormat leadingDigits="7[1-57-9]"
+ pattern="(\d{4})(\d{3})(\d{3})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8[47]"
+ pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>\d{10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[1-6]\d{9}</nationalNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>7[1-57-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>9[018]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ <sharedCost>
+ <nationalNumberPattern>8(?:4[3-5]|7[0-2])\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </sharedCost>
+ <voip>
+ <nationalNumberPattern>56\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </voip>
+ <personalNumber>
+ <nationalNumberPattern>70\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </personalNumber>
+ </territory>
+
+ <!-- Italy -->
+ <!-- http://en.wikipedia.org/wiki/%2B39 -->
+ <territory id="IT" countryCode="39" internationalPrefix="00">
+ <availableFormats>
+ <numberFormat leadingDigits="0[26]" pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="0[13-57-9]" pattern="(\d{3})(\d{4})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="3" pattern="(\d{3})(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="8" pattern="(\d{3})(\d{3,6})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[0389]\d{5,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>0\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>3\d{8,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>80(?:0\d{6}|3\d{3})</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>89(?:2\d{3}|9\d{6})</nationalNumberPattern>
+ <possibleNumberPattern>\d{6,9}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Mexico -->
+ <territory id="MX" countryCode="52" internationalPrefix="00"
+ nationalPrefix="01" nationalPrefixForParsing="01|04[45](\d{10})"
+ nationalPrefixTransformRule="1$1">
+ <availableFormats>
+ <numberFormat leadingDigits="[89]00" pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="33|55|81" pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="[2467]|3[0-24-9]|5[0-46-9]|8[2-9]|9[1-9]" pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:33|55|81)" pattern="1(\d{2})(\d{4})(\d{4})">045 $1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="1(?:[124579]|3[0-24-9]|5[0-46-9]|8[02-9])" pattern="1(\d{3})(\d{3})(\d{4})">045 $1 $2 $3</numberFormat>
+ <intlNumberFormat leadingDigits="[89]00" pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</intlNumberFormat>
+ <intlNumberFormat leadingDigits="33|55|81" pattern="(\d{2})(\d{4})(\d{4})">$1 $2 $3</intlNumberFormat>
+ <intlNumberFormat leadingDigits="[2467]|3[0-24-9]|5[0-46-9]|8[2-9]|9[1-9]" pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</intlNumberFormat>
+ <intlNumberFormat leadingDigits="1(?:33|55|81)" pattern="(1)(\d{2})(\d{4})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ <intlNumberFormat leadingDigits="1(?:[124579]|3[0-24-9]|5[0-46-9]|8[02-9])" pattern="(1)(\d{3})(\d{3})(\d{4})">$1 $2 $3 $4</intlNumberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{9,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[2-9]\d{9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>1\d{10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- New Zealand -->
+ <territory id="NZ" countryCode="64" internationalPrefix="00"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat leadingDigits="24|[34679]" pattern="(\d)(\d{3})(\d{4})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="2[179]" pattern="(\d)(\d{3})(\d{3,5})">$1-$2 $3</numberFormat>
+ <numberFormat leadingDigits="[89]" pattern="(\d{3})(\d{3})(\d{3,4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[2-9]\d{7,9}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>24099\d{3}|(?:3[2-79]|[479][2-689]|6[235-9])\d{6}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,8}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>2(?:[027]\d{7}|9\d{6,7}|1(?:0\d{5,7}|[12]\d{5,6}|[3-9]\d{5})|4[1-9]\d{6}|8\d{7,8})</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,10}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{6,7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9,10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Poland -->
+ <!-- http://en.wikipedia.org/wiki/%2B48 -->
+ <territory id="PL" countryCode="48" internationalPrefix="0~0"
+ nationalPrefix="0" nationalPrefixFormattingRule="$NP$FG">
+ <availableFormats>
+ <numberFormat pattern="(\d{2})(\d{3})(\d{2})(\d{2})">$1 $2 $3 $4</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[1-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{9}</possibleNumberPattern>
+ </generalDesc>
+ <mobile>
+ <nationalNumberPattern>(?:5[01]|6[069]|7[289]|88)\d{7}</nationalNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>800\d{6}</nationalNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>70\d{7}</nationalNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- Singapore -->
+ <!-- http://www.ida.gov.sg/policies%20and%20regulation/20060508120124.aspx -->
+ <territory id="SG" countryCode="65" internationalPrefix="0[0-3][0-9]">
+ <availableFormats>
+ <numberFormat leadingDigits="[369]|8[1-9]" pattern="(\d{4})(\d{4})">$1 $2</numberFormat>
+ <numberFormat leadingDigits="1[89]" pattern="(\d{4})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat leadingDigits="800" pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[13689]\d{7,10}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8,11}</possibleNumberPattern>
+ </generalDesc>
+ <fixedLine>
+ <nationalNumberPattern>[36]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </fixedLine>
+ <mobile>
+ <nationalNumberPattern>[89]\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{8}</possibleNumberPattern>
+ </mobile>
+ <tollFree>
+ <nationalNumberPattern>1?800\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10,11}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>1900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{11}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+
+ <!-- United States -->
+ <!-- http://www.nanpa.com/reports/reports_npa.html -->
+ <!-- For testing purposes, numbers starting with 24 are not considered US
+ numbers.-->
+ <territory id="US" countryCode="1" internationalPrefix="011"
+ preferredExtnPrefix=" extn. ">
+ <availableFormats>
+ <numberFormat pattern="(\d{3})(\d{3})(\d{4})">$1 $2 $3</numberFormat>
+ <numberFormat pattern="(\d{3})(\d{4})">$1 $2</numberFormat>
+ </availableFormats>
+ <generalDesc>
+ <nationalNumberPattern>[13-9]\d{9}|2[0-35-9]\d{8}</nationalNumberPattern>
+ <possibleNumberPattern>\d{7,10}</possibleNumberPattern>
+ <exampleNumber>1234567890</exampleNumber>
+ </generalDesc>
+ <tollFree>
+ <nationalNumberPattern>8(00|66|77|88)\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </tollFree>
+ <premiumRate>
+ <nationalNumberPattern>900\d{7}</nationalNumberPattern>
+ <possibleNumberPattern>\d{10}</possibleNumberPattern>
+ </premiumRate>
+ </territory>
+ </territories>
+</phoneNumberMetadata>
diff --git a/java/resources/com/google/i18n/phonenumbers/test/generated_files/PhoneNumberMetadataProtoForTesting b/java/resources/com/google/i18n/phonenumbers/test/generated_files/PhoneNumberMetadataProtoForTesting
new file mode 100644
index 0000000..769c0fd
--- /dev/null
+++ b/java/resources/com/google/i18n/phonenumbers/test/generated_files/PhoneNumberMetadataProtoForTesting
Binary files differ
diff --git a/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java
new file mode 100644
index 0000000..4e09357
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.NumberFormat;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A formatter which formats phone numbers as they are entered.
+ *
+ * An AsYouTypeFormatter could be created by invoking the getAsYouTypeFormatter method of the
+ * PhoneNumberUtil. After that digits could be added by invoking the inputDigit method on the
+ * formatter instance, and the partially formatted phone number will be returned each time a digit
+ * is added. The clear method could be invoked before a new number needs to be formatted.
+ *
+ * See testAsYouTypeFormatterUS(), testAsYouTestFormatterGB() and testAsYouTypeFormatterDE() in
+ * PhoneNumberUtilTest.java for more details on how the formatter is to be used.
+ *
+ * @author Shaopeng Jia
+ */
+public class AsYouTypeFormatter {
+ private StringBuffer currentOutput;
+ private String formattingTemplate;
+ private StringBuffer accruedInput;
+ private StringBuffer accruedInputWithoutFormatting;
+ private boolean ableToFormat;
+ private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+ private String defaultCountry;
+ private PhoneMetadata defaultMetaData;
+ private PhoneMetadata currentMetaData;
+
+ // 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;
+ private Pattern nationalPrefixForParsing;
+ private Pattern internationalPrefix;
+ private StringBuffer prefixBeforeNationalNumber;
+ private StringBuffer nationalNumber;
+
+ /**
+ * Constructs a light-weight formatter which does no formatting, but outputs exactly what is
+ * fed into the inputDigit method.
+ *
+ * @param regionCode the country/region where the phone number is being entered
+ */
+ AsYouTypeFormatter(String regionCode) {
+ accruedInput = new StringBuffer();
+ accruedInputWithoutFormatting = new StringBuffer();
+ currentOutput = new StringBuffer();
+ prefixBeforeNationalNumber = new StringBuffer();
+ ableToFormat = true;
+ nationalNumber = new StringBuffer();
+ defaultCountry = regionCode;
+ initializeCountrySpecificInfo(defaultCountry);
+ defaultMetaData = currentMetaData;
+ }
+
+ private void initializeCountrySpecificInfo(String regionCode) {
+ currentMetaData = phoneUtil.getMetadataForRegion(regionCode);
+ nationalPrefixForParsing =
+ Pattern.compile(currentMetaData.getNationalPrefixForParsing());
+ internationalPrefix =
+ Pattern.compile("\\+|" + currentMetaData.getInternationalPrefix());
+ }
+
+ private void chooseFormatAndCreateTemplate(String leadingFourDigitsOfNationalNumber) {
+ List<NumberFormat> formatList = getAvailableFormats(leadingFourDigitsOfNationalNumber);
+ if (formatList.size() < 1) {
+ ableToFormat = false;
+ } else {
+ // When there are multiple available formats, the formatter uses the first format.
+ NumberFormat format = formatList.get(0);
+ if (!createFormattingTemplate(format)) {
+ ableToFormat = false;
+ } else {
+ currentOutput = new StringBuffer(formattingTemplate);
+ }
+ }
+ }
+
+ private List<NumberFormat> getAvailableFormats(String leadingFourDigits) {
+ List<NumberFormat> matchedList = new ArrayList<NumberFormat>();
+ List<NumberFormat> formatList = currentMetaData.getNumberFormatList();
+ for (NumberFormat format : formatList) {
+ if (format.hasLeadingDigits()) {
+ Pattern leadingDigitsPattern = Pattern.compile(format.getLeadingDigits());
+ Matcher m = leadingDigitsPattern.matcher(leadingFourDigits);
+ if (m.lookingAt()) {
+ matchedList.add(format);
+ }
+ } else {
+ matchedList.add(format);
+ }
+ }
+ return matchedList;
+ }
+
+ private boolean createFormattingTemplate(NumberFormat format) {
+ String numberFormat = format.getFormat();
+ String numberPattern = format.getPattern();
+
+ // The formatter doesn't format numbers when numberPattern contains "|" or ",", e.g.
+ // (20|3)\d{4,5}. In those cases we quickly return.
+ Matcher unsupportedSyntax = Pattern.compile("\\||,").matcher(numberPattern);
+ if (unsupportedSyntax.find()) {
+ return false;
+ }
+
+ // Replace anything in the form of [..] with \d
+ numberPattern = numberPattern.replaceAll("\\[([^\\[\\]])*\\]","\\\\d");
+
+ // Replace any standalone digit (not the one in d{}) with \d
+ numberPattern = numberPattern.replaceAll("\\d(?=[^}])", "\\\\d");
+
+ formattingTemplate = getFormattingTemplate(numberPattern, numberFormat);
+ return true;
+ }
+
+ // Gets a formatting template which could 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 = Pattern.compile(numberPattern).matcher(longestPhoneNumber);
+ m.find(); // this will always succeed
+ String aPhoneNumber = m.group();
+ // 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 could be reused.
+ */
+ public void clear() {
+ accruedInput = new StringBuffer();
+ accruedInputWithoutFormatting = new StringBuffer();
+ currentOutput = new StringBuffer();
+ lastMatchPosition = 0;
+ prefixBeforeNationalNumber = new StringBuffer();
+ nationalNumber = new StringBuffer();
+ ableToFormat = true;
+ if (!currentMetaData.equals(defaultMetaData)) {
+ initializeCountrySpecificInfo(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 they are removed from the result. Full width digits and Arabic-indic digits
+ * are allowed, and will be shown as they are.
+ * @return the partially formatted phone number, with the remaining digits each denoted by
+ * \u2008. Clients could display the result as it is, as \u2008 will be displayed as a normal
+ * white space.
+ */
+ public String inputDigit(char nextChar) {
+ accruedInput.append(nextChar);
+ // * and # are normally used in mobile codes, which we do not format.
+ if (nextChar == '*' || nextChar == '#') {
+ ableToFormat = false;
+ }
+ if (!ableToFormat) {
+ return accruedInput.toString();
+ }
+
+ nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar);
+
+ // We start to attempt to format only when at least 6 digits (the plus sign is counted as a
+ // digit as well for this purpose) have been entered.
+ switch (accruedInputWithoutFormatting.length()) {
+ case 0: // this is the case where the first few inputs are neither digits nor the plus sign.
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return accruedInput.toString();
+ case 6:
+ if (!extractIddAndValidCountryCode()) {
+ ableToFormat = false;
+ return accruedInput.toString();
+ }
+ removeNationalPrefixFromNationalNumber();
+ return attemptToChooseFormattingPattern();
+ default:
+ if (nationalNumber.length() > 4) { // The formatting pattern is already chosen.
+ return prefixBeforeNationalNumber + inputDigitHelper(nextChar);
+ } else {
+ return attemptToChooseFormattingPattern();
+ }
+ }
+ }
+
+ // 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 4 digits of national number (excluding
+ // national prefix) have been entered.
+ if (nationalNumber.length() >= 4) {
+ chooseFormatAndCreateTemplate(nationalNumber.substring(0, 4));
+ 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) {
+ for (int i = 0; i < lengthOfNationalNumber - 1; i++) {
+ inputDigitHelper(nationalNumber.charAt(i));
+ }
+ return prefixBeforeNationalNumber
+ + inputDigitHelper(nationalNumber.charAt(lengthOfNationalNumber - 1));
+ } else {
+ return prefixBeforeNationalNumber.toString();
+ }
+ }
+
+ private void removeNationalPrefixFromNationalNumber() {
+ int startOfNationalNumber = 0;
+ if (currentMetaData.hasNationalPrefix()) {
+ Matcher m = nationalPrefixForParsing.matcher(nationalNumber);
+ if (m.lookingAt()) {
+ startOfNationalNumber = m.end();
+ prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber));
+ }
+ }
+ nationalNumber.delete(0, startOfNationalNumber);
+ }
+
+ /**
+ * Extracts IDD, plus sign and country code to prefixBeforeNationalNumber when they are available,
+ * and places the remaining input into nationalNumber.
+ *
+ * @return false when accruedInputWithoutFormatting begins with the plus sign or valid IDD for
+ * defaultCountry, but the sequence of digits after that does not form a valid country code.
+ * It returns true for all other cases.
+ */
+ private boolean extractIddAndValidCountryCode() {
+ nationalNumber = new StringBuffer();
+ Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting);
+ if (iddMatcher.lookingAt()) {
+ int startOfCountryCode = iddMatcher.end();
+ StringBuffer numberIncludeCountryCode =
+ new StringBuffer(accruedInputWithoutFormatting.substring(startOfCountryCode));
+ int countryCode = phoneUtil.extractCountryCode(numberIncludeCountryCode, nationalNumber);
+ if (countryCode == 0) {
+ return false;
+ } else {
+ String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode);
+ if (!newRegionCode.equals(defaultCountry)) {
+ initializeCountrySpecificInfo(newRegionCode);
+ }
+ prefixBeforeNationalNumber.append(
+ accruedInputWithoutFormatting.substring(0, startOfCountryCode));
+ if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN ) {
+ prefixBeforeNationalNumber.append(" ");
+ }
+ prefixBeforeNationalNumber.append(countryCode).append(" ");
+ }
+ } else {
+ nationalNumber = new StringBuffer(accruedInputWithoutFormatting);
+ }
+ 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.
+ private char normalizeAndAccrueDigitsAndPlusSign(char nextChar) {
+ if (nextChar == PhoneNumberUtil.PLUS_SIGN) {
+ accruedInputWithoutFormatting.append(nextChar);
+ }
+
+ if (PhoneNumberUtil.DIGIT_MAPPINGS.containsKey(nextChar)) {
+ nextChar = PhoneNumberUtil.DIGIT_MAPPINGS.get(nextChar);
+ accruedInputWithoutFormatting.append(nextChar);
+ nationalNumber.append(nextChar);
+ }
+ return nextChar;
+ }
+
+ private String inputDigitHelper(char nextChar) {
+ if (!PhoneNumberUtil.DIGIT_MAPPINGS.containsKey(nextChar)) {
+ return currentOutput.toString();
+ }
+
+ Matcher digitMatcher = digitPattern.matcher(currentOutput);
+ if (digitMatcher.find(lastMatchPosition)) {
+ currentOutput = new StringBuffer(digitMatcher.replaceFirst(Character.toString(nextChar)));
+ lastMatchPosition = digitMatcher.start();
+ } else { // More digits are entered than we could handle.
+ currentOutput.append(nextChar);
+ ableToFormat = false;
+ }
+ return currentOutput.toString();
+ }
+}
diff --git a/java/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java b/java/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java
new file mode 100644
index 0000000..b850cd5
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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 org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+/**
+ * Tool to convert phone number metadata from the XML format to protocol buffer format. It is
+ * wrapped in the genrule of the BUILD file and run as a preprocessing step when building the
+ * phone number library. Example command line invocation:
+ *
+ * ./BuildMetadataProtoFromXml PhoneNumberMetadata.xml PhoneNumberMetadataProto true
+ *
+ * When liteBuild flag is set to true, the outputFile generated omits certain metadata which is not
+ * needed for clients using liteBuild. At this moment, example numbers information is omitted.
+ *
+ * @author Shaopeng Jia
+ */
+public class BuildMetadataProtoFromXml {
+ private BuildMetadataProtoFromXml() {
+ }
+ private static final Logger LOGGER = Logger.getLogger(BuildMetadataProtoFromXml.class.getName());
+ private static Boolean liteBuild;
+
+ public static void main(String[] args) {
+ String inputFile = args[0];
+ String outputFile = args[1];
+ liteBuild = args.length > 2 && Boolean.getBoolean(args[2]);
+ File xmlFile = new File(inputFile);
+ try {
+ FileOutputStream output = new FileOutputStream(outputFile);
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ Document document = builder.parse(xmlFile);
+ document.getDocumentElement().normalize();
+ Element rootElement = document.getDocumentElement();
+ NodeList territory = rootElement.getElementsByTagName("territory");
+ PhoneMetadataCollection.Builder metadataCollection = PhoneMetadataCollection.newBuilder();
+ int numOfTerritories = territory.getLength();
+ for (int i = 0; i < numOfTerritories; i++) {
+ Element territoryElement = (Element) territory.item(i);
+ String regionCode = territoryElement.getAttribute("id");
+ PhoneMetadata metadata = loadCountryMetadata(regionCode, territoryElement);
+ metadataCollection.addMetadata(metadata);
+ }
+ metadataCollection.build().writeTo(output);
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, e.toString());
+ } catch (SAXException e) {
+ LOGGER.log(Level.SEVERE, e.toString());
+ } catch (ParserConfigurationException e) {
+ LOGGER.log(Level.SEVERE, e.toString());
+ }
+ }
+
+ private static PhoneMetadata loadCountryMetadata(String regionCode, Element element) {
+ PhoneMetadata.Builder metadata = PhoneMetadata.newBuilder();
+ metadata.setId(regionCode);
+ metadata.setCountryCode(Integer.parseInt(element.getAttribute("countryCode")));
+ metadata.setInternationalPrefix(element.getAttribute("internationalPrefix"));
+ if (element.hasAttribute("preferredInternationalPrefix")) {
+ String preferredInternationalPrefix = element.getAttribute("preferredInternationalPrefix");
+ metadata.setPreferredInternationalPrefix(preferredInternationalPrefix);
+ }
+ String nationalPrefix = "";
+ if (element.hasAttribute("nationalPrefix")) {
+ nationalPrefix = element.getAttribute("nationalPrefix");
+ metadata.setNationalPrefix(nationalPrefix);
+ metadata.setNationalPrefixFormattingRule(
+ getNationalPrefixFormattingRuleFromElement(element, nationalPrefix));
+
+ if (element.hasAttribute("nationalPrefixForParsing")) {
+ metadata.setNationalPrefixForParsing(element.getAttribute("nationalPrefixForParsing"));
+ if (element.hasAttribute("nationalPrefixTransformRule")) {
+ metadata.setNationalPrefixTransformRule(
+ element.getAttribute("nationalPrefixTransformRule"));
+ }
+ } else {
+ metadata.setNationalPrefixForParsing(nationalPrefix);
+ }
+ }
+ if (element.hasAttribute("preferredExtnPrefix")) {
+ metadata.setPreferredExtnPrefix(element.getAttribute("preferredExtnPrefix"));
+ }
+
+ // Extract availableFormats
+ NodeList numberFormatElements = element.getElementsByTagName("numberFormat");
+ int numOfFormatElements = numberFormatElements.getLength();
+ if (numOfFormatElements > 0) {
+ for (int i = 0; i < numOfFormatElements; i++) {
+ Element numberFormatElement = (Element) numberFormatElements.item(i);
+ NumberFormat.Builder format = NumberFormat.newBuilder();
+ if (numberFormatElement.hasAttribute("nationalPrefixFormattingRule")) {
+ format.setNationalPrefixFormattingRule(
+ getNationalPrefixFormattingRuleFromElement(numberFormatElement, nationalPrefix));
+ } else {
+ format.setNationalPrefixFormattingRule(metadata.getNationalPrefixFormattingRule());
+ }
+ if (numberFormatElement.hasAttribute("leadingDigits")) {
+ format.setLeadingDigits(numberFormatElement.getAttribute("leadingDigits"));
+ }
+ format.setPattern(numberFormatElement.getAttribute("pattern"));
+ String formatValue = numberFormatElement.getFirstChild().getNodeValue();
+ format.setFormat(formatValue);
+ metadata.addNumberFormat(format.build());
+ }
+ }
+
+ NodeList intlNumberFormatElements = element.getElementsByTagName("intlNumberFormat");
+ int numOfIntlFormatElements = intlNumberFormatElements.getLength();
+ if (numOfIntlFormatElements > 0) {
+ for (int i = 0; i < numOfIntlFormatElements; i++) {
+ Element numberFormatElement = (Element) intlNumberFormatElements.item(i);
+ NumberFormat.Builder format = NumberFormat.newBuilder();
+ if (numberFormatElement.hasAttribute("leadingDigits")) {
+ format.setLeadingDigits(numberFormatElement.getAttribute("leadingDigits"));
+ }
+ format.setPattern(numberFormatElement.getAttribute("pattern"));
+ format.setFormat(numberFormatElement.getFirstChild().getNodeValue());
+ metadata.addIntlNumberFormat(format.build());
+ }
+ }
+
+ PhoneNumberDesc generalDesc =
+ processPhoneNumberDescElement(PhoneNumberDesc.newBuilder().build(),
+ element, "generalDesc");
+ metadata.setGeneralDesc(generalDesc);
+ metadata.setFixedLine(processPhoneNumberDescElement(generalDesc, element, "fixedLine"));
+ metadata.setMobile(processPhoneNumberDescElement(generalDesc, element, "mobile"));
+ metadata.setTollFree(processPhoneNumberDescElement(generalDesc, element, "tollFree"));
+ metadata.setPremiumRate(processPhoneNumberDescElement(generalDesc, element, "premiumRate"));
+ metadata.setSharedCost(processPhoneNumberDescElement(generalDesc, element, "sharedCost"));
+ metadata.setVoip(processPhoneNumberDescElement(generalDesc, element, "voip"));
+ metadata.setPersonalNumber(processPhoneNumberDescElement(generalDesc, element,
+ "personalNumber"));
+
+ if (metadata.getMobile().getNationalNumberPattern().equals(
+ metadata.getFixedLine().getNationalNumberPattern())) {
+ metadata.setSameMobileAndFixedLinePattern(true);
+ }
+ return metadata.build();
+ }
+
+ private static String getNationalPrefixFormattingRuleFromElement(Element element,
+ String nationalPrefix) {
+ String nationalPrefixFormattingRule = element.getAttribute("nationalPrefixFormattingRule");
+ // Replace $NP with national prefix and $FG with the first group ($1).
+ nationalPrefixFormattingRule =
+ nationalPrefixFormattingRule.replaceFirst("\\$NP", nationalPrefix)
+ .replaceFirst("\\$FG", "\\$1");
+ return nationalPrefixFormattingRule;
+ }
+
+ /**
+ * Processes a phone number description element from the XML file and returns it as a
+ * PhoneNumberDesc. If the description element is a fixed line or mobile number, the general
+ * description will be used to fill in the whole element if necessary, or any components that are
+ * missing. For all other types, the general description will only be used to fill in missing
+ * components if the type has a partial definition. For example, if no "tollFree" element exists,
+ * we assume there are no toll free numbers for that locale, and return a phone number description
+ * with "NA" for both the national and possible number patterns.
+ *
+ * @param generalDesc a generic phone number description that will be used to fill in missing
+ * parts of the description
+ * @param countryElement the XML element representing all the country information
+ * @param numberType the name of the number type, corresponding to the appropriate tag in the XML
+ * file with information about that type
+ * @return complete description of that phone number type
+ */
+ private static PhoneNumberDesc processPhoneNumberDescElement(PhoneNumberDesc generalDesc,
+ Element countryElement,
+ String numberType) {
+ NodeList phoneNumberDescList = countryElement.getElementsByTagName(numberType);
+ PhoneNumberDesc.Builder numberDesc = PhoneNumberDesc.newBuilder();
+ if (phoneNumberDescList.getLength() == 0 &&
+ (!numberType.equals("fixedLine") && !numberType.equals("mobile") &&
+ !numberType.equals("generalDesc"))) {
+ numberDesc.setNationalNumberPattern("NA");
+ numberDesc.setPossibleNumberPattern("NA");
+ return numberDesc.build();
+ }
+ numberDesc.mergeFrom(generalDesc);
+ if (phoneNumberDescList.getLength() > 0) {
+ Element element = (Element) phoneNumberDescList.item(0);
+ NodeList possiblePattern = element.getElementsByTagName("possibleNumberPattern");
+ if (possiblePattern.getLength() > 0) {
+ numberDesc.setPossibleNumberPattern(possiblePattern.
+ item(0).getFirstChild().getNodeValue());
+ }
+
+ NodeList validPattern = element.getElementsByTagName("nationalNumberPattern");
+ if (validPattern.getLength() > 0) {
+ numberDesc.setNationalNumberPattern(validPattern.
+ item(0).getFirstChild().getNodeValue());
+ }
+
+ if (!liteBuild) {
+ NodeList exampleNumber = element.getElementsByTagName("exampleNumber");
+ if (exampleNumber.getLength() > 0) {
+ numberDesc.setExampleNumber(exampleNumber.item(0).getFirstChild().getNodeValue());
+ }
+ }
+ }
+ return numberDesc.build();
+ }
+}
diff --git a/java/src/com/google/i18n/phonenumbers/NumberParseException.java b/java/src/com/google/i18n/phonenumbers/NumberParseException.java
new file mode 100644
index 0000000..19a5f7a
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/NumberParseException.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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
+ */
+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;
+ }
+
+ public String toString() {
+ return "Error type: " + errorType + ". " + message;
+ }
+}
diff --git a/java/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
new file mode 100644
index 0000000..96e8208
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
@@ -0,0 +1,1682 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+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.protobuf.MessageLite;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+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.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.
+ *
+ * @author Shaopeng Jia
+ * @author Lara Rennie
+ */
+public class PhoneNumberUtil {
+ // The maximum and minimum length of the national significant number.
+ private static final int MAX_LENGTH_FOR_NSN = 15;
+ private static final int MIN_LENGTH_FOR_NSN = 3;
+ private static final String META_DATA_FILE =
+ "/com/google/i18n/phonenumbers/src/generated_files/PhoneNumberMetadataProto";
+ private static final Logger LOGGER = Logger.getLogger(PhoneNumberUtil.class.getName());
+
+ // A mapping from a country code to a region code which denotes the country/region
+ // represented by that country code. Note countries under NANPA share the country code 1,
+ // Russia and Kazakhstan share the country code 7, and many French territories in the Indian
+ // Ocean share the country code 262. Under this map, 1 is mapped to US, 7 is mapped to RU,
+ // and 262 is mapped to RE.
+ private final Map<Integer, String> countryCodeToRegionCodeMap = new HashMap<Integer, String>();
+
+ // The set of countries that share country code 1.
+ private final Set<String> nanpaCountries = new HashSet<String>();
+ private static final int NANPA_COUNTRY_CODE = 1;
+
+ // The set of countries that share country code 7.
+ private final Set<String> russiaFederationCountries = new HashSet<String>(2);
+ private static final int RUSSIAN_FED_COUNTRY_CODE = 7;
+
+ // The set of countries that share country code 262.
+ private final Set<String> frenchIndianOceanTerritories = new HashSet<String>(6);
+
+ private static final int FRENCH_INDIAN_OCEAN_COUNTRY_CODE = 262;
+
+ // The PLUS_SIGN signifies the international prefix.
+ static final char PLUS_SIGN = '+';
+
+ // These mappings map a character (key) to a specific digit that should replace it for
+ // normalization purposes. Non-European digits that may be used in phone numbers are mapped to a
+ // European equivalent.
+ static final Map<Character, Character> DIGIT_MAPPINGS =
+ new ImmutableMap.Builder<Character, Character>()
+ .put('0', '0')
+ .put('\uFF10', '0') // Fullwidth digit 0
+ .put('\u0660', '0') // Arabic-indic digit 0
+ .put('1', '1')
+ .put('\uFF11', '1') // Fullwidth digit 1
+ .put('\u0661', '1') // Arabic-indic digit 1
+ .put('2', '2')
+ .put('\uFF12', '2') // Fullwidth digit 2
+ .put('\u0662', '2') // Arabic-indic digit 2
+ .put('3', '3')
+ .put('\uFF13', '3') // Fullwidth digit 3
+ .put('\u0663', '3') // Arabic-indic digit 3
+ .put('4', '4')
+ .put('\uFF14', '4') // Fullwidth digit 4
+ .put('\u0664', '4') // Arabic-indic digit 4
+ .put('5', '5')
+ .put('\uFF15', '5') // Fullwidth digit 5
+ .put('\u0665', '5') // Arabic-indic digit 5
+ .put('6', '6')
+ .put('\uFF16', '6') // Fullwidth digit 6
+ .put('\u0666', '6') // Arabic-indic digit 6
+ .put('7', '7')
+ .put('\uFF17', '7') // Fullwidth digit 7
+ .put('\u0667', '7') // Arabic-indic digit 7
+ .put('8', '8')
+ .put('\uFF18', '8') // Fullwidth digit 8
+ .put('\u0668', '8') // Arabic-indic digit 8
+ .put('9', '9')
+ .put('\uFF19', '9') // Fullwidth digit 9
+ .put('\u0669', '9') // Arabic-indic digit 9
+ .build();
+
+ // Only upper-case variants of alpha characters are stored.
+ private static final Map<Character, Character> ALPHA_MAPPINGS =
+ new ImmutableMap.Builder<Character, Character>()
+ .put('A', '2')
+ .put('B', '2')
+ .put('C', '2')
+ .put('D', '3')
+ .put('E', '3')
+ .put('F', '3')
+ .put('G', '4')
+ .put('H', '4')
+ .put('I', '4')
+ .put('J', '5')
+ .put('K', '5')
+ .put('L', '5')
+ .put('M', '6')
+ .put('N', '6')
+ .put('O', '6')
+ .put('P', '7')
+ .put('Q', '7')
+ .put('R', '7')
+ .put('S', '7')
+ .put('T', '8')
+ .put('U', '8')
+ .put('V', '8')
+ .put('W', '9')
+ .put('X', '9')
+ .put('Y', '9')
+ .put('Z', '9')
+ .build();
+
+ // For performance reasons, amalgamate both into one map.
+ private static final Map<Character, Character> ALL_NORMALIZATION_MAPPINGS =
+ new ImmutableMap.Builder<Character, Character>()
+ .putAll(ALPHA_MAPPINGS)
+ .putAll(DIGIT_MAPPINGS)
+ .build();
+
+ // Pattern that makes it easy to distinguish whether a country has a unique international dialing
+ // prefix or not. If a country 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 country, 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.
+ private static final String VALID_PUNCTUATION = "[-x\u2010-\u2015\u2212\uFF0D-\uFF0F " +
+ "\u00A0\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E]";
+
+ // Digits accepted in phone numbers
+ private static final String VALID_DIGITS =
+ Arrays.toString(DIGIT_MAPPINGS.keySet().toArray()).replaceAll(", ", "");
+ // 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(", ", "");
+ private static final String PLUS_CHARS = "+\uFF0B";
+ private static final Pattern CAPTURING_DIGIT_PATTERN =
+ Pattern.compile("([" + VALID_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 + VALID_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";
+ private static final Pattern SECOND_NUMBER_START_PATTERN = Pattern.compile(SECOND_NUMBER_START);
+
+ // 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 - this is read in from the
+ // PhoneNumberMetaData.xml file at initialisation time.
+ // 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.
+ // Corresponds to the following:
+ // plus_sign?([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])*
+ private static final String VALID_PHONE_NUMBER =
+ "[" + PLUS_CHARS + "]?(?:" + VALID_PUNCTUATION + "*[" + VALID_DIGITS + "]){3,}[" +
+ VALID_ALPHA + VALID_PUNCTUATION + VALID_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 country-specific preferences.
+ private static final String DEFAULT_EXTN_PREFIX = " ext. ";
+
+ // 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. There are two regular expressions here: the 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!
+ private static final String KNOWN_EXTN_PATTERNS = "[ \\u00A0\\t,]*(?:ext(?:ensio)?n?|" +
+ "\\uFF45\\uFF58\\uFF54\\uFF4E?|[,x\\uFF58#\\uFF03~\\uFF5E]|int|\\uFF49\\uFF4E\\uFF54)" +
+ "[:\\.\\uFF0E]?[ \\u00A0\\t,]*([" + VALID_DIGITS + "]{1,7})|[- ]+([" + VALID_DIGITS +
+ "]{1,5})#";
+
+ // Regexp of all known extension prefixes used by different countries followed by 1 or more valid
+ // digits, for use when parsing.
+ private static final Pattern EXTN_PATTERN =
+ Pattern.compile("(?:" + KNOWN_EXTN_PATTERNS + ")$",
+ Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
+
+ // 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_PATTERN + ")?",
+ Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
+
+ private static PhoneNumberUtil instance = null;
+
+ // A mapping from a region code to the PhoneMetadata for that region.
+ private Map<String, PhoneMetadata> countryToMetadataMap =
+ Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
+
+ /**
+ * INTERNATIONAL and NATIONAL formats are consistent with the definition in ITU-T Recommendation
+ * E. 123. For example, the number of the Google Zurich 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.
+ *
+ * Note: If you are considering storing the number in a neutral format, you are highly advised to
+ * use the phonenumber.proto.
+ */
+ public enum PhoneNumberFormat {
+ E164,
+ INTERNATIONAL,
+ NATIONAL
+ }
+
+ /**
+ * Type of phone numbers.
+ */
+ public enum PhoneNumberType {
+ FIXED_LINE,
+ MOBILE,
+ // In some countries (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,
+ // A phone number is of type UNKNOWN when it does not fit any of the known patterns for a
+ // specific country.
+ UNKNOWN
+ }
+
+ /**
+ * Types of phone number matches. See detailed description beside the isNumberMatch() method.
+ */
+ public enum MatchType {
+ 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,
+ }
+
+ /**
+ * This class implements a singleton, so the only constructor is private.
+ */
+ private PhoneNumberUtil() {
+ }
+
+ private void init(InputStream source) {
+ // Read in metadata for each country.
+ try {
+ PhoneMetadataCollection metadataCollection = PhoneMetadataCollection.parseFrom(source);
+ for (PhoneMetadata metadata : metadataCollection.getMetadataList()) {
+ String regionCode = metadata.getId();
+ countryToMetadataMap.put(regionCode, metadata);
+ int countryCode = metadata.getCountryCode();
+ switch (countryCode) {
+ case NANPA_COUNTRY_CODE:
+ nanpaCountries.add(regionCode);
+ break;
+ case RUSSIAN_FED_COUNTRY_CODE:
+ russiaFederationCountries.add(regionCode);
+ break;
+ case FRENCH_INDIAN_OCEAN_COUNTRY_CODE:
+ frenchIndianOceanTerritories.add(regionCode);
+ break;
+ default:
+ countryCodeToRegionCodeMap.put(countryCode, regionCode);
+ break;
+ }
+ }
+
+ // Override the value, so that 1 is always mapped to US, 7 is always mapped to RU, and 262 to
+ // RE.
+ countryCodeToRegionCodeMap.put(NANPA_COUNTRY_CODE, "US");
+ countryCodeToRegionCodeMap.put(RUSSIAN_FED_COUNTRY_CODE, "RU");
+ countryCodeToRegionCodeMap.put(FRENCH_INDIAN_OCEAN_COUNTRY_CODE, "RE");
+ } 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 could not 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
+ */
+ @VisibleForTesting
+ static String extractPossibleNumber(String number) {
+ // Remove leading and trailing whitespace.
+ number = number.trim();
+ Matcher m = VALID_START_CHAR_PATTERN.matcher(number);
+ if (m.find()) {
+ number = number.substring(m.start());
+ // 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:
+ * Wide-ascii digits are converted to normal ASCII (European) digits.
+ * 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 -
+ * otherwise alpha characters are stripped.
+ * Punctuation is stripped.
+ * Arabic-Indic numerals are converted to European numerals.
+ *
+ * @param number a string of characters representing a phone number
+ * @return the normalized string version of the phone number
+ */
+ static String normalize(String number) {
+ if (number.matches("(?:.*?[A-Za-z]){3}.*")) {
+ return normalizeHelper(number, ALL_NORMALIZATION_MAPPINGS, true);
+ } else {
+ return normalizeHelper(number, DIGIT_MAPPINGS, true);
+ }
+ }
+
+ /**
+ * Normalizes a string of characters representing a phone number. This is a wrapper for
+ * normalize(String number) but does in-place normalization of the StringBuffer provided.
+ *
+ * @param number a StringBuffer of characters representing a phone number that will be normalized
+ * in place
+ */
+ static void normalize(StringBuffer 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 normalizeHelper(number, DIGIT_MAPPINGS, true);
+ }
+
+ /**
+ * Converts all alpha characters in a number to their respective digits on a keypad, but retains
+ * existing formatting. Also converts wide-ascii digits to normal ascii digits, and converts
+ * Arabic-Indic numerals to European numerals.
+ */
+ public static String convertAlphaCharactersInNumber(String number) {
+ return normalizeHelper(number, ALL_NORMALIZATION_MAPPINGS, false);
+ }
+
+ /**
+ * 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) {
+ StringBuffer normalizedNumber = new StringBuffer(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();
+ }
+
+ @VisibleForTesting
+ static synchronized PhoneNumberUtil getInstance(InputStream source) {
+ if (instance == null) {
+ instance = new PhoneNumberUtil();
+ instance.init(source);
+ }
+ return instance;
+ }
+
+ /**
+ * Used for testing purposes only to reset the PhoneNumberUtil singleton to null.
+ */
+ @VisibleForTesting
+ static synchronized void resetInstance() {
+ instance = null;
+ }
+
+ @VisibleForTesting
+ PhoneMetadata getPhoneMetadata(String regionCode) {
+ PhoneMetadata metadata = countryToMetadataMap.get(regionCode);
+ // makes a defensive copy
+ PhoneMetadata.Builder metadataCopy = metadata.newBuilder();
+ metadataCopy.mergeFrom(metadata);
+ return metadataCopy.build();
+ }
+
+ /**
+ * Convenience method to enable tests to get a list of what countries the library has metadata
+ * for.
+ */
+ @VisibleForTesting
+ Set<String> getSupportedCountries() {
+ return countryToMetadataMap.keySet();
+ }
+
+ /**
+ * Gets a PhoneNumberUtil instance to carry out international phone number formatting, parsing,
+ * or validation. The instance is loaded with phone number metadata for a number of most commonly
+ * used countries/regions.
+ *
+ * The 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) {
+ instance = new PhoneNumberUtil();
+ InputStream in = PhoneNumberUtil.class.getResourceAsStream(META_DATA_FILE);
+ instance.init(in);
+ }
+ return instance;
+ }
+
+ /**
+ * Helper function to check region code is not unknown or null. The number supplied is used only
+ * for the resultant log message.
+ */
+ private boolean isValidRegionCode(String regionCode, int countryCode, String number) {
+ if (regionCode == null || regionCode.equals("ZZ")) {
+ LOGGER.log(Level.WARNING,
+ "Number " + number + "has invalid or missing country code (" + countryCode + ")");
+ 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 code of 0 or an otherwise invalid country 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) {
+ int countryCode = number.getCountryCode();
+ String nationalSignificantNumber = getUnformattedNationalNumber(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.
+ return formatNumberByFormat(countryCode, PhoneNumberFormat.E164,
+ nationalSignificantNumber, "");
+ }
+ // Note here that all NANPA formatting rules are contained by US, so we use that to format NANPA
+ // numbers. The same applies to Russian Fed countries - rules are contained by Russia. French
+ // Indian Ocean country rules are contained by Reunion.
+ String regionCode = getRegionCodeForCountryCode(countryCode);
+ if (!isValidRegionCode(regionCode, countryCode, nationalSignificantNumber)) {
+ return nationalSignificantNumber;
+ }
+ String formattedExtension = maybeGetFormattedExtension(number, regionCode);
+ return formatNumberByFormat(countryCode, numberFormat,
+ formatNationalNumber(nationalSignificantNumber,
+ regionCode,
+ numberFormat),
+ formattedExtension);
+ }
+
+ /**
+ * Formats a phone number in the specified format using client-defined formatting rules. Note that
+ * if the phone number has a country code of zero or an otherwise invalid country 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 countryCode = number.getCountryCode();
+ // For performance reasons, we use US to represent NANPA countries here. This means that
+ // the extension symbol will be chosen from the US metadata.
+ String regionCode = getRegionCodeForCountryCode(countryCode);
+ String nationalSignificantNumber = getUnformattedNationalNumber(number);
+ if (!isValidRegionCode(regionCode, countryCode, nationalSignificantNumber)) {
+ return nationalSignificantNumber;
+ }
+ int size = userDefinedFormats.size();
+ for (int i = 0; i < size; i++) {
+ NumberFormat numFormat = userDefinedFormats.get(i);
+ String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule();
+ if (nationalPrefixFormattingRule.length() > 0) {
+ String nationalPrefix = getMetadataForRegion(regionCode).getNationalPrefix();
+ // Replace $NP with national prefix and $FG with the first group ($1).
+ nationalPrefixFormattingRule =
+ nationalPrefixFormattingRule.replaceFirst("\\$NP", nationalPrefix)
+ .replaceFirst("\\$FG", "\\$1");
+ userDefinedFormats.set(i, NumberFormat.newBuilder(numFormat)
+ .setNationalPrefixFormattingRule(nationalPrefixFormattingRule).build());
+ }
+ }
+
+ String formattedExtension = maybeGetFormattedExtension(number, regionCode);
+ return formatNumberByFormat(countryCode,
+ numberFormat,
+ formatAccordingToFormats(nationalSignificantNumber,
+ userDefinedFormats,
+ numberFormat),
+ formattedExtension);
+ }
+
+ /**
+ * Formats a phone number for out-of-country dialing purpose. If no countryCallingFrom
+ * is supplied, we format the number in its INTERNATIONAL format. If the countryCallingFrom is
+ * the same as the country where the number is from, then NATIONAL formatting will be applied.
+ *
+ * If the number itself has a country code of zero or an otherwise invalid country code, then we
+ * return the number with no formatting applied.
+ *
+ * Note this function takes care of the case for calling inside of NANPA and between Russia and
+ * Kazakhstan (who share the same country code). In those cases, no international prefix is used.
+ * For countries which have multiple international prefixes, the number in its INTERNATIONAL
+ * format will be returned instead.
+ *
+ * @param number the phone number to be formatted
+ * @param countryCallingFrom the ISO 3166-1 two-letter country code that denotes the foreign
+ * country where the call is being placed
+ * @return the formatted phone number
+ */
+ public String formatOutOfCountryCallingNumber(PhoneNumber number,
+ String countryCallingFrom) {
+ if (countryCallingFrom == null || countryCallingFrom.equals("ZZ")) {
+ LOGGER.log(Level.WARNING,
+ "Trying to format number from invalid region. International formatting applied.");
+ return format(number, PhoneNumberFormat.INTERNATIONAL);
+ }
+ int countryCode = number.getCountryCode();
+ if (countryCode == NANPA_COUNTRY_CODE && nanpaCountries.contains(countryCallingFrom)) {
+ // For NANPA countries, return the national format for these countries but prefix it with the
+ // country code.
+ return countryCode + " " + format(number, PhoneNumberFormat.NATIONAL);
+ }
+ if (countryCode == FRENCH_INDIAN_OCEAN_COUNTRY_CODE &&
+ frenchIndianOceanTerritories.contains(countryCallingFrom)) {
+ // For dialling between FRENCH_INDIAN_OCEAN countries, the 10 digit number is all we need.
+ // 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 code.
+ // Details here: http://www.petitfute.com/voyage/225-info-pratiques-reunion
+ return format(number, PhoneNumberFormat.NATIONAL);
+ }
+ // If the country code is the Russian Fed country code, we check the number itself to determine
+ // which region code it is for. We don't do this for NANPA countries because of performance
+ // reasons, and instead use US rules for all NANPA numbers. Also, NANPA countries share the
+ // same national and international prefixes, which is not the case for Russian Fed countries.
+ // There is also a special case for toll-free and premium rate numbers dialled within Russian
+ // Fed countries.
+ String regionCode;
+ if (countryCode == RUSSIAN_FED_COUNTRY_CODE) {
+ if (russiaFederationCountries.contains(countryCallingFrom)) {
+ // For toll-free numbers and premium rate numbers dialled from within Russian Fed countries,
+ // we should format them as if they are local numbers.
+ // A toll-free number would be dialled from KZ as 8-800-080-7777 but from Russia as
+ // 0-800-080-7777. (Confirmation on government websites such as e.gov.kz).
+ PhoneNumberType numberType = getNumberType(number);
+ if (numberType == PhoneNumberType.TOLL_FREE || numberType == PhoneNumberType.PREMIUM_RATE) {
+ return format(number, PhoneNumberFormat.NATIONAL);
+ }
+ }
+ // Otherwise, we should find out what region the number really belongs to before continuing,
+ // since they have different formatting rules.
+ regionCode = getRegionCodeForNumber(number);
+ } else {
+ regionCode = getRegionCodeForCountryCode(countryCode);
+ }
+ String nationalSignificantNumber = getUnformattedNationalNumber(number);
+ if (!isValidRegionCode(regionCode, countryCode, nationalSignificantNumber)) {
+ return nationalSignificantNumber;
+ }
+ if (regionCode.equals(countryCallingFrom)) {
+ return format(number, PhoneNumberFormat.NATIONAL);
+ }
+ String formattedNationalNumber =
+ formatNationalNumber(nationalSignificantNumber,
+ regionCode, PhoneNumberFormat.INTERNATIONAL);
+ PhoneMetadata metadata = getMetadataForRegion(countryCallingFrom);
+ String internationalPrefix = metadata.getInternationalPrefix();
+ String formattedExtension = maybeGetFormattedExtension(number, regionCode);
+ // For countries 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();
+ }
+ return !internationalPrefixForFormatting.equals("")
+ ? internationalPrefixForFormatting + " " + countryCode + " " + formattedNationalNumber
+ + formattedExtension
+ : formatNumberByFormat(countryCode,
+ PhoneNumberFormat.INTERNATIONAL,
+ formattedNationalNumber,
+ formattedExtension);
+ }
+
+ static String getUnformattedNationalNumber(PhoneNumber number) {
+ // The leading zero in the national (significant) number of an Italian phone number has a
+ // special meaning. Unlike the rest of the world, it indicates the number is a landline
+ // number. There have been plans to migrate landline numbers to start with the digit two since
+ // December 2000, but it has not yet happened.
+ // See http://en.wikipedia.org/wiki/%2B39 for more details.
+ // Cote d'Ivoire also uses this for some of their mobile numbers.
+ StringBuffer nationalNumber = new StringBuffer(
+ ((number.getCountryCode() == 39 || number.getCountryCode() == 225) &&
+ number.hasItalianLeadingZero() &&
+ number.getItalianLeadingZero())
+ ? "0" : ""
+ );
+ nationalNumber.append(number.getNationalNumber());
+ return nationalNumber.toString();
+ }
+
+ /**
+ * A helper function that is used by format and formatByPattern.
+ */
+ private String formatNumberByFormat(int countryCode,
+ PhoneNumberFormat numberFormat,
+ String formattedNationalNumber,
+ String formattedExtension) {
+ switch (numberFormat) {
+ case E164:
+ return String.valueOf(PLUS_SIGN) + countryCode + formattedNationalNumber
+ + formattedExtension;
+ case INTERNATIONAL:
+ return String.valueOf(PLUS_SIGN) + countryCode + " " + formattedNationalNumber
+ + formattedExtension;
+ case NATIONAL:
+ default:
+ return formattedNationalNumber + formattedExtension;
+ }
+ }
+
+ // Note in some countries, 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.
+ private String formatNationalNumber(String number,
+ String regionCode,
+ PhoneNumberFormat numberFormat) {
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ List<NumberFormat> intlNumberFormats = metadata.getIntlNumberFormatList();
+ // 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.getNumberFormatList()
+ : metadata.getIntlNumberFormatList();
+ return formatAccordingToFormats(number, availableFormats, numberFormat);
+ }
+
+ private String formatAccordingToFormats(String nationalNumber,
+ List<NumberFormat> availableFormats,
+ PhoneNumberFormat numberFormat) {
+ for (NumberFormat numFormat : availableFormats) {
+ if (!numFormat.hasLeadingDigits() ||
+ Pattern.compile(numFormat.getLeadingDigits()).matcher(nationalNumber).lookingAt()) {
+ String patternToMatch = numFormat.getPattern();
+ if (nationalNumber.matches(patternToMatch)) {
+ String nationalPrefixFormattingRule = numFormat.getNationalPrefixFormattingRule();
+ if (numberFormat == PhoneNumberFormat.NATIONAL &&
+ nationalPrefixFormattingRule != null &&
+ nationalPrefixFormattingRule.length() > 0) {
+ return nationalNumber.replaceAll(
+ patternToMatch,
+ numFormat.getFormat().replaceFirst("(\\$1)", nationalPrefixFormattingRule));
+ } else {
+ return nationalNumber.replaceAll(patternToMatch, numFormat.getFormat());
+ }
+ }
+ }
+ }
+
+ // If no pattern above is matched, we format the number as a whole.
+ return nationalNumber;
+ }
+
+ /**
+ * Gets a valid number for the specified country.
+ *
+ * @param regionCode the ISO 3166-1 two-letter country code that denotes the country for which
+ * an example number is needed
+ * @return a valid fixed-line number for the specified country. 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 country and number type.
+ *
+ * @param regionCode the ISO 3166-1 two-letter country code that denotes the country for which
+ * an example number is needed
+ * @param type the type of number that is needed
+ * @return a valid number for the specified country and type. Returns null when the metadata
+ * does not contain such information.
+ */
+ public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) {
+ PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), type);
+ try {
+ if (desc.hasExampleNumber()) {
+ return parse(desc.getExampleNumber(), regionCode);
+ }
+ } catch (NumberParseException e) {
+ LOGGER.log(Level.SEVERE, e.toString());
+ }
+ return null;
+ }
+
+ /**
+ * Gets the formatted extension of a phone number, if the phone number had an extension specified.
+ * If not, it returns an empty string.
+ */
+ private String maybeGetFormattedExtension(PhoneNumber number, String regionCode) {
+ if (!number.hasExtension()) {
+ return "";
+ } else {
+ return formatExtension(number.getExtension(), regionCode);
+ }
+ }
+
+ /**
+ * 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 country.
+ */
+ private String formatExtension(String extensionDigits, String regionCode) {
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ if (metadata.hasPreferredExtnPrefix()) {
+ return metadata.getPreferredExtnPrefix() + extensionDigits;
+ } else {
+ return DEFAULT_EXTN_PREFIX + 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();
+ 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);
+ String nationalSignificantNumber = getUnformattedNationalNumber(number);
+ if (!isValidRegionCode(regionCode, number.getCountryCode(), nationalSignificantNumber)) {
+ return PhoneNumberType.UNKNOWN;
+ }
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ return getNumberTypeHelper(nationalSignificantNumber, metadata);
+ }
+
+ private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) {
+ PhoneNumberDesc generalNumberDesc = metadata.getGeneralDesc();
+ if (!generalNumberDesc.hasNationalNumberPattern() ||
+ !isNumberMatchingDesc(nationalNumber, generalNumberDesc)) {
+ LOGGER.log(Level.FINEST,
+ "Number type unknown - doesn't match general national number pattern.");
+ return PhoneNumberType.UNKNOWN;
+ }
+
+ if (isNumberMatchingDesc(nationalNumber, metadata.getPremiumRate())) {
+ LOGGER.log(Level.FINEST, "Number is a premium number.");
+ return PhoneNumberType.PREMIUM_RATE;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getTollFree())) {
+ LOGGER.log(Level.FINEST, "Number is a toll-free number.");
+ return PhoneNumberType.TOLL_FREE;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getSharedCost())) {
+ LOGGER.log(Level.FINEST, "Number is a shared cost number.");
+ return PhoneNumberType.SHARED_COST;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getVoip())) {
+ LOGGER.log(Level.FINEST, "Number is a VOIP (Voice over IP) number.");
+ return PhoneNumberType.VOIP;
+ }
+ if (isNumberMatchingDesc(nationalNumber, metadata.getPersonalNumber())) {
+ LOGGER.log(Level.FINEST, "Number is a personal number.");
+ return PhoneNumberType.PERSONAL_NUMBER;
+ }
+
+ boolean isFixedLine = isNumberMatchingDesc(nationalNumber, metadata.getFixedLine());
+ if (isFixedLine) {
+ if (metadata.getSameMobileAndFixedLinePattern()) {
+ LOGGER.log(Level.FINEST,
+ "Fixed-line and mobile patterns equal, number is fixed-line or mobile");
+ return PhoneNumberType.FIXED_LINE_OR_MOBILE;
+ } else if (isNumberMatchingDesc(nationalNumber, metadata.getMobile())) {
+ LOGGER.log(Level.FINEST,
+ "Fixed-line and mobile patterns differ, but number is " +
+ "still fixed-line or mobile");
+ return PhoneNumberType.FIXED_LINE_OR_MOBILE;
+ }
+ LOGGER.log(Level.FINEST, "Number is a fixed line number.");
+ 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.getSameMobileAndFixedLinePattern() &&
+ isNumberMatchingDesc(nationalNumber, metadata.getMobile())) {
+ LOGGER.log(Level.FINEST, "Number is a mobile number.");
+ return PhoneNumberType.MOBILE;
+ }
+ LOGGER.log(Level.FINEST,
+ "Number type unknown - doesn't match any specific number type pattern.");
+ return PhoneNumberType.UNKNOWN;
+ }
+
+ PhoneMetadata getMetadataForRegion(String regionCode) {
+ if (regionCode == null) {
+ return null;
+ }
+ return countryToMetadataMap.get(regionCode);
+ }
+
+ private boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) {
+ String possiblePattern = numberDesc.getPossibleNumberPattern();
+ if (!nationalNumber.matches(possiblePattern)) {
+ return false;
+ }
+
+ String validPattern = numberDesc.getNationalNumberPattern();
+ return nationalNumber.matches(validPattern);
+ }
+
+ /**
+ * 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, number.getCountryCode(),
+ getUnformattedNationalNumber(number))
+ && 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 code is not the same as the country 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 ISO 3166-1 two-letter country code that denotes the region/country
+ * 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 = getUnformattedNationalNumber(number);
+
+ // For countries where we don't have meta-data 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()) {
+ LOGGER.log(Level.FINER, "Validating number with incomplete metadata.");
+ int numberLength = nationalSignificantNumber.length();
+ return numberLength > MIN_LENGTH_FOR_NSN && numberLength <= MAX_LENGTH_FOR_NSN;
+ }
+ return isNumberMatchingDesc(nationalSignificantNumber, generalNumDesc)
+ && getNumberTypeHelper(nationalSignificantNumber, metadata) != PhoneNumberType.UNKNOWN;
+ }
+
+ /**
+ * Returns the country/region where a phone number is from. This could be used for geo-coding in
+ * the country/region level.
+ *
+ * @param number the phone number whose origin we want to know
+ * @return the country/region where the phone number is from
+ */
+ public String getRegionCodeForNumber(PhoneNumber number) {
+ int countryCode = number.getCountryCode();
+ String regionCode;
+ switch (countryCode) {
+ case NANPA_COUNTRY_CODE:
+ // Override this and try the US case first, since it is more likely than other countries,
+ // for performance reasons.
+ if (isValidNumberForRegion(number, "US")) {
+ return "US";
+ }
+ Set<String> nanpaExceptUS = new HashSet<String>(nanpaCountries);
+ nanpaExceptUS.remove("US");
+ regionCode = getRegionCodeForNumberFromRegionList(number, nanpaExceptUS);
+ return regionCode;
+ case RUSSIAN_FED_COUNTRY_CODE:
+ regionCode = getRegionCodeForNumberFromRegionList(number, russiaFederationCountries);
+ return regionCode;
+ case FRENCH_INDIAN_OCEAN_COUNTRY_CODE:
+ regionCode = getRegionCodeForNumberFromRegionList(number, frenchIndianOceanTerritories);
+ return regionCode;
+ default:
+ return getRegionCodeForCountryCode(countryCode);
+ }
+ }
+
+ private String getRegionCodeForNumberFromRegionList(PhoneNumber number,
+ Set<String> regionCodes) {
+ String nationalNumber = String.valueOf(number.getNationalNumber());
+ for (String regionCode : regionCodes) {
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ if (getNumberTypeHelper(nationalNumber, metadata) != PhoneNumberType.UNKNOWN) {
+ return regionCode;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the region code that matches the specific country code. In the case of no region code
+ * being found, ZZ will be returned.
+ */
+ String getRegionCodeForCountryCode(int countryCode) {
+ String regionCode = countryCodeToRegionCodeMap.get(countryCode);
+ return regionCode == null ? "ZZ" : regionCode;
+ }
+
+ /**
+ * Returns the country calling code for a specific region. For example, this would be 1 for the
+ * United States, and 64 for New Zealand.
+ *
+ * @param regionCode the ISO 3166-1 two-letter country code that denotes the country/region that
+ * we want to get the country code for
+ * @return the country calling code for the country/region denoted by regionCode
+ */
+ public int getCountryCodeForRegion(String regionCode) {
+ if (regionCode == null || regionCode.equals("ZZ")) {
+ LOGGER.log(Level.SEVERE, "Invalid or missing country code provided.");
+ return 0;
+ }
+ PhoneMetadata metadata = getMetadataForRegion(regionCode);
+ return metadata.getCountryCode();
+ }
+
+ /**
+ * Gets a set which contains all the countries under the North American Numbering Plan
+ * Administration (NANPA).
+ *
+ * @return the set that contains the countries under NANPA
+ */
+ public Set<String> getNANPACountries() {
+ return new HashSet<String>(nanpaCountries);
+ }
+
+ /**
+ * Convenience wrapper around 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;
+ }
+
+ /**
+ * Check whether a phone number is a possible number. It provides a more lenient check than
+ * isValidNumber in the following sense:
+ * 1. It only checks the length of phone numbers. In particular, it doesn't check starting
+ * digits of the number.
+ * 2. 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 country. Therefore, it is much faster than
+ * isValidNumber.
+ * 3. For fixed line numbers, many countries 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.
+ *
+ * @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 = String.valueOf(number.getNationalNumber());
+ 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 countries within those plans.
+ String regionCode = getRegionCodeForCountryCode(countryCode);
+ if (!isValidRegionCode(regionCode, countryCode, nationalNumber)) {
+ return ValidationResult.INVALID_COUNTRY_CODE;
+ }
+ PhoneNumberDesc generalNumDesc = getMetadataForRegion(regionCode).getGeneralDesc();
+ String possibleNumberPattern = generalNumDesc.getPossibleNumberPattern();
+ Matcher m = Pattern.compile(possibleNumberPattern).matcher(nationalNumber);
+ if (m.lookingAt()) {
+ return (m.end() == nationalNumber.length()) ? ValidationResult.IS_POSSIBLE
+ : ValidationResult.TOO_LONG;
+ } else {
+ return ValidationResult.TOO_SHORT;
+ }
+ }
+
+ /**
+ * Check whether a phone number is a possible number given a number in the form of a string, and
+ * the country where the number could be dialed from. It provides a more lenient check than
+ * isValidNumber. See isPossibleNumber(PhoneNumber number) for details.
+ *
+ * This method first parses the number, then invokes isPossibleNumber(PhoneNumber number) with the
+ * resultant PhoneNumber object.
+ *
+ * @param number the number that needs to be checked, in the form of a string
+ * @param countryDialingFrom the ISO 3166-1 two-letter country code that denotes
+ * the country that we are expecting the number to be dialed from.
+ * Note this is different from the country 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 could be dialed from any country.
+ * When it is written as 00 1 650 253 0000, it could be dialed from
+ * any country which has international prefix 00. When it is written as
+ * 650 253 0000, it could only be dialed from US, and when written as
+ * 253 0000, it could only be dialed from US (Mountain View, CA, to be
+ * more specific).
+ * @return true if the number is possible
+ */
+ public boolean isPossibleNumber(String number, String countryDialingFrom) {
+ try {
+ return isPossibleNumber(parse(number, countryDialingFrom));
+ } catch (NumberParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets an AsYouTypeFormatter for the specific country. Note this function doesn't attempt to
+ * figure out the types of phone number being entered on the fly due to performance reasons.
+ * Instead, it tries to apply a standard format to all types of phone numbers. For countries
+ * where different types of phone numbers follow different formats, the formatter returned
+ * will do no formatting but output exactly what is fed into the inputDigit method.
+ *
+ * If the type of the phone number being entered is known beforehand, use
+ * getAsYouTypeFormatterByType instead.
+ *
+ * @param regionCode the ISO 3166-1 two-letter country code that denotes the country/region
+ * where the phone number is being entered
+ * @return an AsYouTypeFormatter object, which could be used to format phone numbers in the
+ * specific country "as you type"
+ */
+ public AsYouTypeFormatter getAsYouTypeFormatter(String regionCode) {
+ return new AsYouTypeFormatter(regionCode);
+ }
+
+ // Extracts country 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 code, and leaves nationalNumber unmodified.
+ int extractCountryCode(StringBuffer fullNumber, StringBuffer nationalNumber) {
+ int potentialCountryCode;
+ for (int i = 1; i <= 3; i++) {
+ potentialCountryCode = Integer.parseInt(fullNumber.substring(0, i));
+ if (countryCodeToRegionCodeMap.containsKey(potentialCountryCode)) {
+ nationalNumber.append(fullNumber.substring(i));
+ return potentialCountryCode;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Tries to extract a country code from a number. This method will return zero if no country code
+ * is considered to be present. Country codes are extracted in the following ways:
+ * - by stripping the international dialing prefix of the country the person is dialing from,
+ * if this is present in the number, and looking at the next digits
+ * - by stripping the '+' sign if present and then looking at the next digits
+ * - by comparing the start of the number and the country 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 code of this region, validation will be reattempted after
+ * stripping this country code. If this number is considered a possible number, then the
+ * first digits will be considered the country code and removed as such.
+ *
+ * It will throw a NumberParseException if the number starts with a '+' but the country code
+ * supplied after this does not match that of any known country.
+ *
+ * @param number non-normalized telephone number that we wish to extract a country
+ * 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 code was extracted. The number is appended to any existing contents. If no
+ * country code was extracted, this will be left unchanged.
+ * @return the country code extracted or 0 if none could be extracted
+ */
+ @VisibleForTesting
+ int maybeExtractCountryCode(String number, PhoneMetadata defaultRegionMetadata,
+ StringBuffer nationalNumber)
+ throws NumberParseException {
+ StringBuffer fullNumber = new StringBuffer(number);
+ // Set the default prefix to be something that will never match.
+ String possibleCountryIddPrefix = "NonMatch";
+ if (defaultRegionMetadata != null) {
+ possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
+ }
+ if (maybeStripInternationalPrefixAndNormalize(fullNumber, possibleCountryIddPrefix)) {
+ 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) {
+ return potentialCountryCode;
+ }
+
+ // If this fails, they must be using a strange country code that we don't recognize, or
+ // that doesn't exist.
+ throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ "Country code supplied was not recognised.");
+ } else if (defaultRegionMetadata != null) {
+ // Check to see if the number is valid for the default region already. If not, we check to
+ // see if the country code for the default region is present at the start of the number.
+ Pattern validNumberPattern =
+ Pattern.compile(defaultRegionMetadata.getGeneralDesc().getNationalNumberPattern());
+ if (!validNumberPattern.matcher(fullNumber).matches()) {
+ int defaultCountryCode = defaultRegionMetadata.getCountryCode();
+ String defaultCountryCodeString = String.valueOf(defaultCountryCode);
+ String normalizedNumber = fullNumber.toString();
+ if (normalizedNumber.startsWith(defaultCountryCodeString)) {
+ // If so, strip this, and see if the resultant number is valid.
+ StringBuffer potentialNationalNumber =
+ new StringBuffer(normalizedNumber.substring(defaultCountryCodeString.length()));
+ maybeStripNationalPrefix(
+ potentialNationalNumber,
+ defaultRegionMetadata.getNationalPrefixForParsing(),
+ defaultRegionMetadata.getNationalPrefixTransformRule(),
+ validNumberPattern);
+ if (validNumberPattern.matcher(potentialNationalNumber).matches()) {
+ nationalNumber.append(potentialNationalNumber);
+ return defaultCountryCode;
+ }
+ }
+ }
+ }
+ // No country code present.
+ return 0;
+ }
+
+ /**
+ * Strips the IDD from the start of the number if present. Helper function used by
+ * maybeStripInternationalPrefixAndNormalize.
+ */
+ private boolean parsePrefixAsIdd(Pattern iddPattern,
+ StringBuffer 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 codes cannot
+ // begin with 0.
+ Matcher digitMatcher = CAPTURING_DIGIT_PATTERN.matcher(number.substring(matchEnd));
+ if (digitMatcher.find()) {
+ String normalizedGroup = normalize(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 country we
+ * think this number may be dialed in
+ * @return true if an international dialing prefix could be removed from the number, otherwise
+ * false if the number did not seem to be in international format
+ */
+ @VisibleForTesting
+ boolean maybeStripInternationalPrefixAndNormalize(StringBuffer number, String possibleIddPrefix) {
+ if (number.length() == 0) {
+ return false;
+ }
+ if (number.charAt(0) == PLUS_SIGN) {
+ number.deleteCharAt(0);
+ // Can now normalize the rest of the number since we've consumed the "+" sign at the start.
+ normalize(number);
+ return true;
+ }
+ // Attempt to parse the first digits as an international prefix.
+ Pattern iddPattern = Pattern.compile(possibleIddPrefix);
+ if (parsePrefixAsIdd(iddPattern, number)) {
+ normalize(number);
+ return true;
+ }
+ // If still not found, then try and normalize the number and then try again. This shouldn't be
+ // done before, since non-numeric characters (+ and ~) may legally be in the international
+ // prefix.
+ normalize(number);
+ return parsePrefixAsIdd(iddPattern, number);
+ }
+
+ /**
+ * 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 possibleNationalPrefix a regex that represents the national direct dialing prefix
+ * from the country we think this number may be dialed in
+ * @param transformRule the string that specifies how number should be transformed according
+ * to the regex specified in possibleNationalPrefix
+ * @param nationalNumberRule a regular expression that specifies what a valid phonenumber from
+ * this region should look like after any national prefix was stripped or transformed
+ */
+ @VisibleForTesting
+ void maybeStripNationalPrefix(StringBuffer number, String possibleNationalPrefix,
+ String transformRule, Pattern nationalNumberRule) {
+ int numberLength = number.length();
+ if (numberLength == 0 || possibleNationalPrefix.equals("")) {
+ // Early return for numbers of zero length.
+ return;
+ }
+ // Attempt to parse the first digits as a national prefix.
+ Matcher m = Pattern.compile(possibleNationalPrefix).matcher(number);
+ if (m.lookingAt()) {
+ // m.group(1) == null implies nothing was captured by the capturing groups in
+ // possibleNationalPrefix; therefore, no transformation is necessary, and we
+ // just remove the national prefix.
+ if (transformRule == null || transformRule.equals("") || m.group(1) == null) {
+ // Check that the resultant number is viable. If not, return.
+ Matcher nationalNumber = nationalNumberRule.matcher(number.substring(m.end()));
+ if (!nationalNumber.matches()) {
+ return;
+ }
+ number.delete(0, m.end());
+ } else {
+ // Check that the resultant number is viable. If not, return. Check this by copying the
+ // string buffer and making the transformation on the copy first.
+ StringBuffer transformedNumber = new StringBuffer(number);
+ transformedNumber.replace(0, numberLength, m.replaceFirst(transformRule));
+ Matcher nationalNumber = nationalNumberRule.matcher(transformedNumber.toString());
+ if (!nationalNumber.matches()) {
+ return;
+ }
+ number.replace(0, number.length(), transformedNumber.toString());
+ }
+ }
+ }
+
+ /**
+ * 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(StringBuffer 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; i <= m.groupCount(); 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 "";
+ }
+
+ /**
+ * Parses a string and returns it in proto buffer format. This method will throw a
+ * NumberParseException exception 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
+ * country/region is not performed. This can be done separately with 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 defaultCountry the ISO 3166-1 two-letter country code that denotes the country 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 country 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 country was supplied
+ */
+ public PhoneNumber parse(String numberToParse, String defaultCountry)
+ throws NumberParseException {
+ if (defaultCountry == null || defaultCountry.equals("ZZ")) {
+ throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ "No default country was supplied.");
+ }
+ return parseHelper(numberToParse, defaultCountry);
+ }
+
+ /**
+ * As no equals method is implemented for MessageLite, we implement our own equals method here
+ * to compare the serialized data.
+ */
+ @VisibleForTesting
+ static Boolean areSameMessages(MessageLite message1, MessageLite message2) {
+ if (message1 == null && message2 == null) {
+ return true;
+ }
+ if (message1 == null || message2 == null) {
+ return false;
+ }
+ OutputStream output1 = new ByteArrayOutputStream();
+ OutputStream output2 = new ByteArrayOutputStream();
+ try {
+ message1.writeTo(output1);
+ message2.writeTo(output2);
+ } catch (IOException e) {
+ LOGGER.log(Level.WARNING, e.toString());
+ }
+
+ return output1.toString().equals(output2.toString());
+ }
+
+
+ /**
+ * Parses a string and returns it in proto buffer format. This method is the same as the public
+ * parse() method, with the exception that it allows the default country to be null, for use by
+ * isNumberMatch().
+ */
+ private PhoneNumber parseHelper(String numberToParse, String defaultCountry)
+ throws NumberParseException {
+ // 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.");
+ }
+
+ PhoneNumber.Builder phoneNumber = PhoneNumber.newBuilder();
+ StringBuffer nationalNumber = new StringBuffer(number);
+ // Attempt to parse extension first, since it doesn't require country-specific data and we want
+ // to have the non-normalised number here.
+ String extension = maybeStripExtension(nationalNumber);
+ if (!extension.equals("")) {
+ phoneNumber.setExtension(extension);
+ }
+
+ PhoneMetadata countryMetadata = getMetadataForRegion(defaultCountry);
+ // Check to see if the number is given in international format so we know whether this number is
+ // from the default country or not.
+ StringBuffer normalizedNationalNumber = new StringBuffer();
+ // been created, and just remove the prefix, rather than taking in a string and then outputting
+ // a string buffer.
+ int countryCode = maybeExtractCountryCode(nationalNumber.toString(), countryMetadata,
+ normalizedNationalNumber);
+ if (countryCode != 0) {
+ String phoneNumberRegion = getRegionCodeForCountryCode(countryCode);
+ countryMetadata = getMetadataForRegion(phoneNumberRegion);
+ } else {
+ // If no extracted country 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 (defaultCountry != null) {
+ countryCode = countryMetadata.getCountryCode();
+ }
+ }
+ 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 (countryMetadata != null) {
+ Pattern validNumberPattern =
+ Pattern.compile(countryMetadata.getGeneralDesc().getNationalNumberPattern());
+ maybeStripNationalPrefix(normalizedNationalNumber,
+ countryMetadata.getNationalPrefixForParsing(),
+ countryMetadata.getNationalPrefixTransformRule(),
+ validNumberPattern);
+ }
+ phoneNumber.setCountryCode(countryCode);
+ // The ItalianLeadingZero is valid only for numbers from IT and CI.
+ if ((countryCode == 39 || countryCode == 225) && normalizedNationalNumber.charAt(0) == '0') {
+ phoneNumber.setItalianLeadingZero(true);
+ }
+ 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.");
+ }
+ phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString()));
+ return phoneNumber.build();
+ }
+
+ /**
+ * Takes two phone numbers and compares them for equality.
+ *
+ * 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 country specified, and the NSNs and extensions are
+ * the same.
+ * Returns SHORT_NSN_MATCH if either or both has no country specified, or the country 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.Builder firstNumber = PhoneNumber.newBuilder();
+ firstNumber.mergeFrom(firstNumberIn);
+ PhoneNumber.Builder secondNumber = PhoneNumber.newBuilder();
+ secondNumber.mergeFrom(secondNumberIn);
+ // First clear any empty-string extensions so that we can use the proto-buffer equality method.
+
+ if (firstNumber.hasExtension() &&
+ firstNumber.getExtension().equals("")) {
+ firstNumber.clearExtension();
+ }
+ if (secondNumber.hasExtension() &&
+ secondNumber.getExtension().equals("")) {
+ secondNumber.clearExtension();
+ }
+
+ PhoneNumber number1 = firstNumber.build();
+ PhoneNumber number2 = secondNumber.build();
+
+ // Early exit if both had extensions and these are different.
+ if (number1.hasExtension() && number2.hasExtension() &&
+ !number1.getExtension().equals(number2.getExtension())) {
+ return MatchType.NO_MATCH;
+ }
+ int firstNumberCountryCode = number1.getCountryCode();
+ int secondNumberCountryCode = number2.getCountryCode();
+ // Both had country code specified.
+ if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
+ if (areSameMessages(number1, number2)) {
+ return MatchType.EXACT_MATCH;
+ } else if (firstNumberCountryCode == secondNumberCountryCode) {
+ // 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.
+ String firstNumberNationalNumber = String.valueOf(number1.getNationalNumber());
+ String secondNumberNationalNumber = String.valueOf(number2.getNationalNumber());
+ // Note that endsWith returns true if the numbers are equal.
+ if (firstNumberNationalNumber.endsWith(secondNumberNationalNumber) ||
+ secondNumberNationalNumber.endsWith(firstNumberNationalNumber)) {
+ return MatchType.SHORT_NSN_MATCH;
+ }
+ }
+ // This is not a match.
+ return MatchType.NO_MATCH;
+ }
+ // Checks cases where one or both country codes were not specified. To make equality checks
+ // easier, we first set the country codes to be equal.
+ PhoneNumber newNumber =
+ PhoneNumber.newBuilder(number1).setCountryCode(secondNumberCountryCode).build();
+ // If all else was the same, then this is an NSN_MATCH.
+ if (areSameMessages(newNumber, number2)) {
+ return MatchType.NSN_MATCH;
+ }
+ String firstNumberNationalNumber = String.valueOf(newNumber.getNationalNumber());
+ String secondNumberNationalNumber = String.valueOf(number2.getNationalNumber());
+ // Note that endsWith returns true if the numbers are equal.
+ if (firstNumberNationalNumber.endsWith(secondNumberNationalNumber) ||
+ secondNumberNationalNumber.endsWith(firstNumberNationalNumber)) {
+ return MatchType.SHORT_NSN_MATCH;
+ }
+ return MatchType.NO_MATCH;
+ }
+
+ /**
+ * Takes two phone numbers as strings and compares them for equality. This is a convenience
+ * wrapper for isNumberMatch(PhoneNumber firstNumber, PhoneNumber secondNumber). No default region
+ * is known.
+ *
+ * @param firstNumber first number to compare. Can contain formatting, and can have country code
+ * specified with + at the start.
+ * @param secondNumber second number to compare. Can contain formatting, and can have country
+ * code specified with + at the start.
+ * @return NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See isNumberMatch(PhoneNumber
+ * firstNumber, PhoneNumber secondNumber) for more details.
+ * @throws NumberParseException if either number is not considered to be a viable phone
+ * number
+ */
+ public MatchType isNumberMatch(String firstNumber, String secondNumber)
+ throws NumberParseException {
+ return isNumberMatch(parseHelper(firstNumber, null), parseHelper(secondNumber, null));
+ }
+
+ /**
+ * Takes two phone numbers and compares them for equality. This is a convenience wrapper for
+ * isNumberMatch(PhoneNumber firstNumber, PhoneNumber secondNumber). 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
+ * code specified with + at the start.
+ * @return NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See isNumberMatch(PhoneNumber
+ * firstNumber, PhoneNumber secondNumber) for more details.
+ * @throws NumberParseException if the second number is not considered to be a viable phone
+ * number
+ */
+ public MatchType isNumberMatch(PhoneNumber firstNumber, String secondNumber)
+ throws NumberParseException {
+ return isNumberMatch(firstNumber, parseHelper(secondNumber, null));
+ }
+}
diff --git a/java/src/com/google/i18n/phonenumbers/Phonemetadata.java b/java/src/com/google/i18n/phonenumbers/Phonemetadata.java
new file mode 100644
index 0000000..2d5eb53
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/Phonemetadata.java
@@ -0,0 +1,2370 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: phonemetadata.proto
+
+package com.google.i18n.phonenumbers;
+
+public final class Phonemetadata {
+ private Phonemetadata() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+ public static final class NumberFormat extends
+ com.google.protobuf.GeneratedMessageLite {
+ // Use NumberFormat.newBuilder() to construct.
+ private NumberFormat() {
+ initFields();
+ }
+ private NumberFormat(boolean noInit) {}
+
+ private static final NumberFormat defaultInstance;
+ public static NumberFormat getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public NumberFormat getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ // required string pattern = 1;
+ public static final int PATTERN_FIELD_NUMBER = 1;
+ private boolean hasPattern;
+ private java.lang.String pattern_ = "";
+ public boolean hasPattern() { return hasPattern; }
+ public java.lang.String getPattern() { return pattern_; }
+
+ // required string format = 2;
+ public static final int FORMAT_FIELD_NUMBER = 2;
+ private boolean hasFormat;
+ private java.lang.String format_ = "";
+ public boolean hasFormat() { return hasFormat; }
+ public java.lang.String getFormat() { return format_; }
+
+ // optional string leading_digits = 3;
+ public static final int LEADING_DIGITS_FIELD_NUMBER = 3;
+ private boolean hasLeadingDigits;
+ private java.lang.String leadingDigits_ = "";
+ public boolean hasLeadingDigits() { return hasLeadingDigits; }
+ public java.lang.String getLeadingDigits() { return leadingDigits_; }
+
+ // optional string national_prefix_formatting_rule = 4;
+ public static final int NATIONAL_PREFIX_FORMATTING_RULE_FIELD_NUMBER = 4;
+ private boolean hasNationalPrefixFormattingRule;
+ private java.lang.String nationalPrefixFormattingRule_ = "";
+ public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; }
+ public java.lang.String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; }
+
+ private void initFields() {
+ }
+ public final boolean isInitialized() {
+ if (!hasPattern) return false;
+ if (!hasFormat) return false;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (hasPattern()) {
+ output.writeString(1, getPattern());
+ }
+ if (hasFormat()) {
+ output.writeString(2, getFormat());
+ }
+ if (hasLeadingDigits()) {
+ output.writeString(3, getLeadingDigits());
+ }
+ if (hasNationalPrefixFormattingRule()) {
+ output.writeString(4, getNationalPrefixFormattingRule());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasPattern()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(1, getPattern());
+ }
+ if (hasFormat()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(2, getFormat());
+ }
+ if (hasLeadingDigits()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(3, getLeadingDigits());
+ }
+ if (hasNationalPrefixFormattingRule()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(4, getNationalPrefixFormattingRule());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.NumberFormat parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ com.google.i18n.phonenumbers.Phonemetadata.NumberFormat, Builder> {
+ private com.google.i18n.phonenumbers.Phonemetadata.NumberFormat result;
+
+ // Construct using com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.newBuilder()
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new com.google.i18n.phonenumbers.Phonemetadata.NumberFormat();
+ return builder;
+ }
+
+ protected com.google.i18n.phonenumbers.Phonemetadata.NumberFormat internalGetResult() {
+ return result;
+ }
+
+ public Builder clear() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "Cannot call clear() after build().");
+ }
+ result = new com.google.i18n.phonenumbers.Phonemetadata.NumberFormat();
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(result);
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat getDefaultInstanceForType() {
+ return com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.getDefaultInstance();
+ }
+
+ public boolean isInitialized() {
+ return result.isInitialized();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat build() {
+ if (result != null && !isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return buildPartial();
+ }
+
+ private com.google.i18n.phonenumbers.Phonemetadata.NumberFormat buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat buildPartial() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
+ com.google.i18n.phonenumbers.Phonemetadata.NumberFormat returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ public Builder mergeFrom(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat other) {
+ if (other == com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.getDefaultInstance()) return this;
+ if (other.hasPattern()) {
+ setPattern(other.getPattern());
+ }
+ if (other.hasFormat()) {
+ setFormat(other.getFormat());
+ }
+ if (other.hasLeadingDigits()) {
+ setLeadingDigits(other.getLeadingDigits());
+ }
+ if (other.hasNationalPrefixFormattingRule()) {
+ setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule());
+ }
+ return this;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ setPattern(input.readString());
+ break;
+ }
+ case 18: {
+ setFormat(input.readString());
+ break;
+ }
+ case 26: {
+ setLeadingDigits(input.readString());
+ break;
+ }
+ case 34: {
+ setNationalPrefixFormattingRule(input.readString());
+ break;
+ }
+ }
+ }
+ }
+
+
+ // required string pattern = 1;
+ public boolean hasPattern() {
+ return result.hasPattern();
+ }
+ public java.lang.String getPattern() {
+ return result.getPattern();
+ }
+ public Builder setPattern(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPattern = true;
+ result.pattern_ = value;
+ return this;
+ }
+ public Builder clearPattern() {
+ result.hasPattern = false;
+ result.pattern_ = getDefaultInstance().getPattern();
+ return this;
+ }
+
+ // required string format = 2;
+ public boolean hasFormat() {
+ return result.hasFormat();
+ }
+ public java.lang.String getFormat() {
+ return result.getFormat();
+ }
+ public Builder setFormat(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasFormat = true;
+ result.format_ = value;
+ return this;
+ }
+ public Builder clearFormat() {
+ result.hasFormat = false;
+ result.format_ = getDefaultInstance().getFormat();
+ return this;
+ }
+
+ // optional string leading_digits = 3;
+ public boolean hasLeadingDigits() {
+ return result.hasLeadingDigits();
+ }
+ public java.lang.String getLeadingDigits() {
+ return result.getLeadingDigits();
+ }
+ public Builder setLeadingDigits(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasLeadingDigits = true;
+ result.leadingDigits_ = value;
+ return this;
+ }
+ public Builder clearLeadingDigits() {
+ result.hasLeadingDigits = false;
+ result.leadingDigits_ = getDefaultInstance().getLeadingDigits();
+ return this;
+ }
+
+ // optional string national_prefix_formatting_rule = 4;
+ public boolean hasNationalPrefixFormattingRule() {
+ return result.hasNationalPrefixFormattingRule();
+ }
+ public java.lang.String getNationalPrefixFormattingRule() {
+ return result.getNationalPrefixFormattingRule();
+ }
+ public Builder setNationalPrefixFormattingRule(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalPrefixFormattingRule = true;
+ result.nationalPrefixFormattingRule_ = value;
+ return this;
+ }
+ public Builder clearNationalPrefixFormattingRule() {
+ result.hasNationalPrefixFormattingRule = false;
+ result.nationalPrefixFormattingRule_ = getDefaultInstance().getNationalPrefixFormattingRule();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.NumberFormat)
+ }
+
+ static {
+ defaultInstance = new NumberFormat(true);
+ com.google.i18n.phonenumbers.Phonemetadata.internalForceInit();
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:i18n.phonenumbers.NumberFormat)
+ }
+
+ public static final class PhoneNumberDesc extends
+ com.google.protobuf.GeneratedMessageLite {
+ // Use PhoneNumberDesc.newBuilder() to construct.
+ private PhoneNumberDesc() {
+ initFields();
+ }
+ private PhoneNumberDesc(boolean noInit) {}
+
+ private static final PhoneNumberDesc defaultInstance;
+ public static PhoneNumberDesc getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PhoneNumberDesc getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ // optional string national_number_pattern = 2;
+ public static final int NATIONAL_NUMBER_PATTERN_FIELD_NUMBER = 2;
+ private boolean hasNationalNumberPattern;
+ private java.lang.String nationalNumberPattern_ = "";
+ public boolean hasNationalNumberPattern() { return hasNationalNumberPattern; }
+ public java.lang.String getNationalNumberPattern() { return nationalNumberPattern_; }
+
+ // optional string possible_number_pattern = 3;
+ public static final int POSSIBLE_NUMBER_PATTERN_FIELD_NUMBER = 3;
+ private boolean hasPossibleNumberPattern;
+ private java.lang.String possibleNumberPattern_ = "";
+ public boolean hasPossibleNumberPattern() { return hasPossibleNumberPattern; }
+ public java.lang.String getPossibleNumberPattern() { return possibleNumberPattern_; }
+
+ // optional string example_number = 6;
+ public static final int EXAMPLE_NUMBER_FIELD_NUMBER = 6;
+ private boolean hasExampleNumber;
+ private java.lang.String exampleNumber_ = "";
+ public boolean hasExampleNumber() { return hasExampleNumber; }
+ public java.lang.String getExampleNumber() { return exampleNumber_; }
+
+ private void initFields() {
+ }
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (hasNationalNumberPattern()) {
+ output.writeString(2, getNationalNumberPattern());
+ }
+ if (hasPossibleNumberPattern()) {
+ output.writeString(3, getPossibleNumberPattern());
+ }
+ if (hasExampleNumber()) {
+ output.writeString(6, getExampleNumber());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasNationalNumberPattern()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(2, getNationalNumberPattern());
+ }
+ if (hasPossibleNumberPattern()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(3, getPossibleNumberPattern());
+ }
+ if (hasExampleNumber()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(6, getExampleNumber());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc, Builder> {
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc result;
+
+ // Construct using com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder()
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc();
+ return builder;
+ }
+
+ protected com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc internalGetResult() {
+ return result;
+ }
+
+ public Builder clear() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "Cannot call clear() after build().");
+ }
+ result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc();
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(result);
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getDefaultInstanceForType() {
+ return com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ }
+
+ public boolean isInitialized() {
+ return result.isInitialized();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc build() {
+ if (result != null && !isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return buildPartial();
+ }
+
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc buildPartial() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ public Builder mergeFrom(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc other) {
+ if (other == com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) return this;
+ if (other.hasNationalNumberPattern()) {
+ setNationalNumberPattern(other.getNationalNumberPattern());
+ }
+ if (other.hasPossibleNumberPattern()) {
+ setPossibleNumberPattern(other.getPossibleNumberPattern());
+ }
+ if (other.hasExampleNumber()) {
+ setExampleNumber(other.getExampleNumber());
+ }
+ return this;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 18: {
+ setNationalNumberPattern(input.readString());
+ break;
+ }
+ case 26: {
+ setPossibleNumberPattern(input.readString());
+ break;
+ }
+ case 50: {
+ setExampleNumber(input.readString());
+ break;
+ }
+ }
+ }
+ }
+
+
+ // optional string national_number_pattern = 2;
+ public boolean hasNationalNumberPattern() {
+ return result.hasNationalNumberPattern();
+ }
+ public java.lang.String getNationalNumberPattern() {
+ return result.getNationalNumberPattern();
+ }
+ public Builder setNationalNumberPattern(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalNumberPattern = true;
+ result.nationalNumberPattern_ = value;
+ return this;
+ }
+ public Builder clearNationalNumberPattern() {
+ result.hasNationalNumberPattern = false;
+ result.nationalNumberPattern_ = getDefaultInstance().getNationalNumberPattern();
+ return this;
+ }
+
+ // optional string possible_number_pattern = 3;
+ public boolean hasPossibleNumberPattern() {
+ return result.hasPossibleNumberPattern();
+ }
+ public java.lang.String getPossibleNumberPattern() {
+ return result.getPossibleNumberPattern();
+ }
+ public Builder setPossibleNumberPattern(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPossibleNumberPattern = true;
+ result.possibleNumberPattern_ = value;
+ return this;
+ }
+ public Builder clearPossibleNumberPattern() {
+ result.hasPossibleNumberPattern = false;
+ result.possibleNumberPattern_ = getDefaultInstance().getPossibleNumberPattern();
+ return this;
+ }
+
+ // optional string example_number = 6;
+ public boolean hasExampleNumber() {
+ return result.hasExampleNumber();
+ }
+ public java.lang.String getExampleNumber() {
+ return result.getExampleNumber();
+ }
+ public Builder setExampleNumber(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasExampleNumber = true;
+ result.exampleNumber_ = value;
+ return this;
+ }
+ public Builder clearExampleNumber() {
+ result.hasExampleNumber = false;
+ result.exampleNumber_ = getDefaultInstance().getExampleNumber();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.PhoneNumberDesc)
+ }
+
+ static {
+ defaultInstance = new PhoneNumberDesc(true);
+ com.google.i18n.phonenumbers.Phonemetadata.internalForceInit();
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:i18n.phonenumbers.PhoneNumberDesc)
+ }
+
+ public static final class PhoneMetadata extends
+ com.google.protobuf.GeneratedMessageLite {
+ // Use PhoneMetadata.newBuilder() to construct.
+ private PhoneMetadata() {
+ initFields();
+ }
+ private PhoneMetadata(boolean noInit) {}
+
+ private static final PhoneMetadata defaultInstance;
+ public static PhoneMetadata getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PhoneMetadata getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc general_desc = 1;
+ public static final int GENERAL_DESC_FIELD_NUMBER = 1;
+ private boolean hasGeneralDesc;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc generalDesc_;
+ public boolean hasGeneralDesc() { return hasGeneralDesc; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getGeneralDesc() { return generalDesc_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc fixed_line = 2;
+ public static final int FIXED_LINE_FIELD_NUMBER = 2;
+ private boolean hasFixedLine;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc fixedLine_;
+ public boolean hasFixedLine() { return hasFixedLine; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getFixedLine() { return fixedLine_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc mobile = 3;
+ public static final int MOBILE_FIELD_NUMBER = 3;
+ private boolean hasMobile;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc mobile_;
+ public boolean hasMobile() { return hasMobile; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getMobile() { return mobile_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc toll_free = 4;
+ public static final int TOLL_FREE_FIELD_NUMBER = 4;
+ private boolean hasTollFree;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc tollFree_;
+ public boolean hasTollFree() { return hasTollFree; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getTollFree() { return tollFree_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc premium_rate = 5;
+ public static final int PREMIUM_RATE_FIELD_NUMBER = 5;
+ private boolean hasPremiumRate;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc premiumRate_;
+ public boolean hasPremiumRate() { return hasPremiumRate; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getPremiumRate() { return premiumRate_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc shared_cost = 6;
+ public static final int SHARED_COST_FIELD_NUMBER = 6;
+ private boolean hasSharedCost;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc sharedCost_;
+ public boolean hasSharedCost() { return hasSharedCost; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getSharedCost() { return sharedCost_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc personal_number = 7;
+ public static final int PERSONAL_NUMBER_FIELD_NUMBER = 7;
+ private boolean hasPersonalNumber;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc personalNumber_;
+ public boolean hasPersonalNumber() { return hasPersonalNumber; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getPersonalNumber() { return personalNumber_; }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc voip = 8;
+ public static final int VOIP_FIELD_NUMBER = 8;
+ private boolean hasVoip;
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc voip_;
+ public boolean hasVoip() { return hasVoip; }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getVoip() { return voip_; }
+
+ // required string id = 9;
+ public static final int ID_FIELD_NUMBER = 9;
+ private boolean hasId;
+ private java.lang.String id_ = "";
+ public boolean hasId() { return hasId; }
+ public java.lang.String getId() { return id_; }
+
+ // required int32 country_code = 10;
+ public static final int COUNTRY_CODE_FIELD_NUMBER = 10;
+ private boolean hasCountryCode;
+ private int countryCode_ = 0;
+ public boolean hasCountryCode() { return hasCountryCode; }
+ public int getCountryCode() { return countryCode_; }
+
+ // required string international_prefix = 11;
+ public static final int INTERNATIONAL_PREFIX_FIELD_NUMBER = 11;
+ private boolean hasInternationalPrefix;
+ private java.lang.String internationalPrefix_ = "";
+ public boolean hasInternationalPrefix() { return hasInternationalPrefix; }
+ public java.lang.String getInternationalPrefix() { return internationalPrefix_; }
+
+ // optional string preferred_international_prefix = 17;
+ public static final int PREFERRED_INTERNATIONAL_PREFIX_FIELD_NUMBER = 17;
+ private boolean hasPreferredInternationalPrefix;
+ private java.lang.String preferredInternationalPrefix_ = "";
+ public boolean hasPreferredInternationalPrefix() { return hasPreferredInternationalPrefix; }
+ public java.lang.String getPreferredInternationalPrefix() { return preferredInternationalPrefix_; }
+
+ // optional string national_prefix = 12;
+ public static final int NATIONAL_PREFIX_FIELD_NUMBER = 12;
+ private boolean hasNationalPrefix;
+ private java.lang.String nationalPrefix_ = "";
+ public boolean hasNationalPrefix() { return hasNationalPrefix; }
+ public java.lang.String getNationalPrefix() { return nationalPrefix_; }
+
+ // optional string preferred_extn_prefix = 13;
+ public static final int PREFERRED_EXTN_PREFIX_FIELD_NUMBER = 13;
+ private boolean hasPreferredExtnPrefix;
+ private java.lang.String preferredExtnPrefix_ = "";
+ public boolean hasPreferredExtnPrefix() { return hasPreferredExtnPrefix; }
+ public java.lang.String getPreferredExtnPrefix() { return preferredExtnPrefix_; }
+
+ // optional string national_prefix_for_parsing = 15;
+ public static final int NATIONAL_PREFIX_FOR_PARSING_FIELD_NUMBER = 15;
+ private boolean hasNationalPrefixForParsing;
+ private java.lang.String nationalPrefixForParsing_ = "";
+ public boolean hasNationalPrefixForParsing() { return hasNationalPrefixForParsing; }
+ public java.lang.String getNationalPrefixForParsing() { return nationalPrefixForParsing_; }
+
+ // optional string national_prefix_transform_rule = 16;
+ public static final int NATIONAL_PREFIX_TRANSFORM_RULE_FIELD_NUMBER = 16;
+ private boolean hasNationalPrefixTransformRule;
+ private java.lang.String nationalPrefixTransformRule_ = "";
+ public boolean hasNationalPrefixTransformRule() { return hasNationalPrefixTransformRule; }
+ public java.lang.String getNationalPrefixTransformRule() { return nationalPrefixTransformRule_; }
+
+ // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false];
+ public static final int SAME_MOBILE_AND_FIXED_LINE_PATTERN_FIELD_NUMBER = 18;
+ private boolean hasSameMobileAndFixedLinePattern;
+ private boolean sameMobileAndFixedLinePattern_ = false;
+ public boolean hasSameMobileAndFixedLinePattern() { return hasSameMobileAndFixedLinePattern; }
+ public boolean getSameMobileAndFixedLinePattern() { return sameMobileAndFixedLinePattern_; }
+
+ // repeated .i18n.phonenumbers.NumberFormat number_format = 19;
+ public static final int NUMBER_FORMAT_FIELD_NUMBER = 19;
+ private java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> numberFormat_ =
+ java.util.Collections.emptyList();
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> getNumberFormatList() {
+ return numberFormat_;
+ }
+ public int getNumberFormatCount() { return numberFormat_.size(); }
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat getNumberFormat(int index) {
+ return numberFormat_.get(index);
+ }
+
+ // repeated .i18n.phonenumbers.NumberFormat intl_number_format = 20;
+ public static final int INTL_NUMBER_FORMAT_FIELD_NUMBER = 20;
+ private java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> intlNumberFormat_ =
+ java.util.Collections.emptyList();
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> getIntlNumberFormatList() {
+ return intlNumberFormat_;
+ }
+ public int getIntlNumberFormatCount() { return intlNumberFormat_.size(); }
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat getIntlNumberFormat(int index) {
+ return intlNumberFormat_.get(index);
+ }
+
+ // optional string national_prefix_formatting_rule = 21;
+ public static final int NATIONAL_PREFIX_FORMATTING_RULE_FIELD_NUMBER = 21;
+ private boolean hasNationalPrefixFormattingRule;
+ private java.lang.String nationalPrefixFormattingRule_ = "";
+ public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; }
+ public java.lang.String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; }
+
+ private void initFields() {
+ generalDesc_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ fixedLine_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ mobile_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ tollFree_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ premiumRate_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ sharedCost_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ personalNumber_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ voip_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ }
+ public final boolean isInitialized() {
+ if (!hasGeneralDesc) return false;
+ if (!hasFixedLine) return false;
+ if (!hasMobile) return false;
+ if (!hasTollFree) return false;
+ if (!hasPremiumRate) return false;
+ if (!hasSharedCost) return false;
+ if (!hasPersonalNumber) return false;
+ if (!hasVoip) return false;
+ if (!hasId) return false;
+ if (!hasCountryCode) return false;
+ if (!hasInternationalPrefix) return false;
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getNumberFormatList()) {
+ if (!element.isInitialized()) return false;
+ }
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getIntlNumberFormatList()) {
+ if (!element.isInitialized()) return false;
+ }
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (hasGeneralDesc()) {
+ output.writeMessage(1, getGeneralDesc());
+ }
+ if (hasFixedLine()) {
+ output.writeMessage(2, getFixedLine());
+ }
+ if (hasMobile()) {
+ output.writeMessage(3, getMobile());
+ }
+ if (hasTollFree()) {
+ output.writeMessage(4, getTollFree());
+ }
+ if (hasPremiumRate()) {
+ output.writeMessage(5, getPremiumRate());
+ }
+ if (hasSharedCost()) {
+ output.writeMessage(6, getSharedCost());
+ }
+ if (hasPersonalNumber()) {
+ output.writeMessage(7, getPersonalNumber());
+ }
+ if (hasVoip()) {
+ output.writeMessage(8, getVoip());
+ }
+ if (hasId()) {
+ output.writeString(9, getId());
+ }
+ if (hasCountryCode()) {
+ output.writeInt32(10, getCountryCode());
+ }
+ if (hasInternationalPrefix()) {
+ output.writeString(11, getInternationalPrefix());
+ }
+ if (hasNationalPrefix()) {
+ output.writeString(12, getNationalPrefix());
+ }
+ if (hasPreferredExtnPrefix()) {
+ output.writeString(13, getPreferredExtnPrefix());
+ }
+ if (hasNationalPrefixForParsing()) {
+ output.writeString(15, getNationalPrefixForParsing());
+ }
+ if (hasNationalPrefixTransformRule()) {
+ output.writeString(16, getNationalPrefixTransformRule());
+ }
+ if (hasPreferredInternationalPrefix()) {
+ output.writeString(17, getPreferredInternationalPrefix());
+ }
+ if (hasSameMobileAndFixedLinePattern()) {
+ output.writeBool(18, getSameMobileAndFixedLinePattern());
+ }
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getNumberFormatList()) {
+ output.writeMessage(19, element);
+ }
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getIntlNumberFormatList()) {
+ output.writeMessage(20, element);
+ }
+ if (hasNationalPrefixFormattingRule()) {
+ output.writeString(21, getNationalPrefixFormattingRule());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasGeneralDesc()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, getGeneralDesc());
+ }
+ if (hasFixedLine()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, getFixedLine());
+ }
+ if (hasMobile()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, getMobile());
+ }
+ if (hasTollFree()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(4, getTollFree());
+ }
+ if (hasPremiumRate()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(5, getPremiumRate());
+ }
+ if (hasSharedCost()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(6, getSharedCost());
+ }
+ if (hasPersonalNumber()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(7, getPersonalNumber());
+ }
+ if (hasVoip()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(8, getVoip());
+ }
+ if (hasId()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(9, getId());
+ }
+ if (hasCountryCode()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(10, getCountryCode());
+ }
+ if (hasInternationalPrefix()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(11, getInternationalPrefix());
+ }
+ if (hasNationalPrefix()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(12, getNationalPrefix());
+ }
+ if (hasPreferredExtnPrefix()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(13, getPreferredExtnPrefix());
+ }
+ if (hasNationalPrefixForParsing()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(15, getNationalPrefixForParsing());
+ }
+ if (hasNationalPrefixTransformRule()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(16, getNationalPrefixTransformRule());
+ }
+ if (hasPreferredInternationalPrefix()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(17, getPreferredInternationalPrefix());
+ }
+ if (hasSameMobileAndFixedLinePattern()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(18, getSameMobileAndFixedLinePattern());
+ }
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getNumberFormatList()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(19, element);
+ }
+ for (com.google.i18n.phonenumbers.Phonemetadata.NumberFormat element : getIntlNumberFormatList()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(20, element);
+ }
+ if (hasNationalPrefixFormattingRule()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(21, getNationalPrefixFormattingRule());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata, Builder> {
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata result;
+
+ // Construct using com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.newBuilder()
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata();
+ return builder;
+ }
+
+ protected com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata internalGetResult() {
+ return result;
+ }
+
+ public Builder clear() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "Cannot call clear() after build().");
+ }
+ result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata();
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(result);
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata getDefaultInstanceForType() {
+ return com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.getDefaultInstance();
+ }
+
+ public boolean isInitialized() {
+ return result.isInitialized();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata build() {
+ if (result != null && !isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return buildPartial();
+ }
+
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata buildPartial() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
+ if (result.numberFormat_ != java.util.Collections.EMPTY_LIST) {
+ result.numberFormat_ =
+ java.util.Collections.unmodifiableList(result.numberFormat_);
+ }
+ if (result.intlNumberFormat_ != java.util.Collections.EMPTY_LIST) {
+ result.intlNumberFormat_ =
+ java.util.Collections.unmodifiableList(result.intlNumberFormat_);
+ }
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ public Builder mergeFrom(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata other) {
+ if (other == com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.getDefaultInstance()) return this;
+ if (other.hasGeneralDesc()) {
+ mergeGeneralDesc(other.getGeneralDesc());
+ }
+ if (other.hasFixedLine()) {
+ mergeFixedLine(other.getFixedLine());
+ }
+ if (other.hasMobile()) {
+ mergeMobile(other.getMobile());
+ }
+ if (other.hasTollFree()) {
+ mergeTollFree(other.getTollFree());
+ }
+ if (other.hasPremiumRate()) {
+ mergePremiumRate(other.getPremiumRate());
+ }
+ if (other.hasSharedCost()) {
+ mergeSharedCost(other.getSharedCost());
+ }
+ if (other.hasPersonalNumber()) {
+ mergePersonalNumber(other.getPersonalNumber());
+ }
+ if (other.hasVoip()) {
+ mergeVoip(other.getVoip());
+ }
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasCountryCode()) {
+ setCountryCode(other.getCountryCode());
+ }
+ if (other.hasInternationalPrefix()) {
+ setInternationalPrefix(other.getInternationalPrefix());
+ }
+ if (other.hasPreferredInternationalPrefix()) {
+ setPreferredInternationalPrefix(other.getPreferredInternationalPrefix());
+ }
+ if (other.hasNationalPrefix()) {
+ setNationalPrefix(other.getNationalPrefix());
+ }
+ if (other.hasPreferredExtnPrefix()) {
+ setPreferredExtnPrefix(other.getPreferredExtnPrefix());
+ }
+ if (other.hasNationalPrefixForParsing()) {
+ setNationalPrefixForParsing(other.getNationalPrefixForParsing());
+ }
+ if (other.hasNationalPrefixTransformRule()) {
+ setNationalPrefixTransformRule(other.getNationalPrefixTransformRule());
+ }
+ if (other.hasSameMobileAndFixedLinePattern()) {
+ setSameMobileAndFixedLinePattern(other.getSameMobileAndFixedLinePattern());
+ }
+ if (!other.numberFormat_.isEmpty()) {
+ if (result.numberFormat_.isEmpty()) {
+ result.numberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.numberFormat_.addAll(other.numberFormat_);
+ }
+ if (!other.intlNumberFormat_.isEmpty()) {
+ if (result.intlNumberFormat_.isEmpty()) {
+ result.intlNumberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.intlNumberFormat_.addAll(other.intlNumberFormat_);
+ }
+ if (other.hasNationalPrefixFormattingRule()) {
+ setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule());
+ }
+ return this;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasGeneralDesc()) {
+ subBuilder.mergeFrom(getGeneralDesc());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setGeneralDesc(subBuilder.buildPartial());
+ break;
+ }
+ case 18: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasFixedLine()) {
+ subBuilder.mergeFrom(getFixedLine());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setFixedLine(subBuilder.buildPartial());
+ break;
+ }
+ case 26: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasMobile()) {
+ subBuilder.mergeFrom(getMobile());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setMobile(subBuilder.buildPartial());
+ break;
+ }
+ case 34: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasTollFree()) {
+ subBuilder.mergeFrom(getTollFree());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setTollFree(subBuilder.buildPartial());
+ break;
+ }
+ case 42: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasPremiumRate()) {
+ subBuilder.mergeFrom(getPremiumRate());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setPremiumRate(subBuilder.buildPartial());
+ break;
+ }
+ case 50: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasSharedCost()) {
+ subBuilder.mergeFrom(getSharedCost());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setSharedCost(subBuilder.buildPartial());
+ break;
+ }
+ case 58: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasPersonalNumber()) {
+ subBuilder.mergeFrom(getPersonalNumber());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setPersonalNumber(subBuilder.buildPartial());
+ break;
+ }
+ case 66: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder();
+ if (hasVoip()) {
+ subBuilder.mergeFrom(getVoip());
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ setVoip(subBuilder.buildPartial());
+ break;
+ }
+ case 74: {
+ setId(input.readString());
+ break;
+ }
+ case 80: {
+ setCountryCode(input.readInt32());
+ break;
+ }
+ case 90: {
+ setInternationalPrefix(input.readString());
+ break;
+ }
+ case 98: {
+ setNationalPrefix(input.readString());
+ break;
+ }
+ case 106: {
+ setPreferredExtnPrefix(input.readString());
+ break;
+ }
+ case 122: {
+ setNationalPrefixForParsing(input.readString());
+ break;
+ }
+ case 130: {
+ setNationalPrefixTransformRule(input.readString());
+ break;
+ }
+ case 138: {
+ setPreferredInternationalPrefix(input.readString());
+ break;
+ }
+ case 144: {
+ setSameMobileAndFixedLinePattern(input.readBool());
+ break;
+ }
+ case 154: {
+ com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addNumberFormat(subBuilder.buildPartial());
+ break;
+ }
+ case 162: {
+ com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addIntlNumberFormat(subBuilder.buildPartial());
+ break;
+ }
+ case 170: {
+ setNationalPrefixFormattingRule(input.readString());
+ break;
+ }
+ }
+ }
+ }
+
+
+ // required .i18n.phonenumbers.PhoneNumberDesc general_desc = 1;
+ public boolean hasGeneralDesc() {
+ return result.hasGeneralDesc();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getGeneralDesc() {
+ return result.getGeneralDesc();
+ }
+ public Builder setGeneralDesc(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasGeneralDesc = true;
+ result.generalDesc_ = value;
+ return this;
+ }
+ public Builder setGeneralDesc(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasGeneralDesc = true;
+ result.generalDesc_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeGeneralDesc(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasGeneralDesc() &&
+ result.generalDesc_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.generalDesc_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.generalDesc_).mergeFrom(value).buildPartial();
+ } else {
+ result.generalDesc_ = value;
+ }
+ result.hasGeneralDesc = true;
+ return this;
+ }
+ public Builder clearGeneralDesc() {
+ result.hasGeneralDesc = false;
+ result.generalDesc_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc fixed_line = 2;
+ public boolean hasFixedLine() {
+ return result.hasFixedLine();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getFixedLine() {
+ return result.getFixedLine();
+ }
+ public Builder setFixedLine(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasFixedLine = true;
+ result.fixedLine_ = value;
+ return this;
+ }
+ public Builder setFixedLine(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasFixedLine = true;
+ result.fixedLine_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeFixedLine(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasFixedLine() &&
+ result.fixedLine_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.fixedLine_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.fixedLine_).mergeFrom(value).buildPartial();
+ } else {
+ result.fixedLine_ = value;
+ }
+ result.hasFixedLine = true;
+ return this;
+ }
+ public Builder clearFixedLine() {
+ result.hasFixedLine = false;
+ result.fixedLine_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc mobile = 3;
+ public boolean hasMobile() {
+ return result.hasMobile();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getMobile() {
+ return result.getMobile();
+ }
+ public Builder setMobile(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasMobile = true;
+ result.mobile_ = value;
+ return this;
+ }
+ public Builder setMobile(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasMobile = true;
+ result.mobile_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeMobile(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasMobile() &&
+ result.mobile_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.mobile_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.mobile_).mergeFrom(value).buildPartial();
+ } else {
+ result.mobile_ = value;
+ }
+ result.hasMobile = true;
+ return this;
+ }
+ public Builder clearMobile() {
+ result.hasMobile = false;
+ result.mobile_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc toll_free = 4;
+ public boolean hasTollFree() {
+ return result.hasTollFree();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getTollFree() {
+ return result.getTollFree();
+ }
+ public Builder setTollFree(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasTollFree = true;
+ result.tollFree_ = value;
+ return this;
+ }
+ public Builder setTollFree(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasTollFree = true;
+ result.tollFree_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeTollFree(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasTollFree() &&
+ result.tollFree_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.tollFree_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.tollFree_).mergeFrom(value).buildPartial();
+ } else {
+ result.tollFree_ = value;
+ }
+ result.hasTollFree = true;
+ return this;
+ }
+ public Builder clearTollFree() {
+ result.hasTollFree = false;
+ result.tollFree_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc premium_rate = 5;
+ public boolean hasPremiumRate() {
+ return result.hasPremiumRate();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getPremiumRate() {
+ return result.getPremiumRate();
+ }
+ public Builder setPremiumRate(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPremiumRate = true;
+ result.premiumRate_ = value;
+ return this;
+ }
+ public Builder setPremiumRate(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasPremiumRate = true;
+ result.premiumRate_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergePremiumRate(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasPremiumRate() &&
+ result.premiumRate_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.premiumRate_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.premiumRate_).mergeFrom(value).buildPartial();
+ } else {
+ result.premiumRate_ = value;
+ }
+ result.hasPremiumRate = true;
+ return this;
+ }
+ public Builder clearPremiumRate() {
+ result.hasPremiumRate = false;
+ result.premiumRate_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc shared_cost = 6;
+ public boolean hasSharedCost() {
+ return result.hasSharedCost();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getSharedCost() {
+ return result.getSharedCost();
+ }
+ public Builder setSharedCost(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasSharedCost = true;
+ result.sharedCost_ = value;
+ return this;
+ }
+ public Builder setSharedCost(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasSharedCost = true;
+ result.sharedCost_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeSharedCost(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasSharedCost() &&
+ result.sharedCost_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.sharedCost_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.sharedCost_).mergeFrom(value).buildPartial();
+ } else {
+ result.sharedCost_ = value;
+ }
+ result.hasSharedCost = true;
+ return this;
+ }
+ public Builder clearSharedCost() {
+ result.hasSharedCost = false;
+ result.sharedCost_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc personal_number = 7;
+ public boolean hasPersonalNumber() {
+ return result.hasPersonalNumber();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getPersonalNumber() {
+ return result.getPersonalNumber();
+ }
+ public Builder setPersonalNumber(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPersonalNumber = true;
+ result.personalNumber_ = value;
+ return this;
+ }
+ public Builder setPersonalNumber(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasPersonalNumber = true;
+ result.personalNumber_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergePersonalNumber(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasPersonalNumber() &&
+ result.personalNumber_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.personalNumber_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.personalNumber_).mergeFrom(value).buildPartial();
+ } else {
+ result.personalNumber_ = value;
+ }
+ result.hasPersonalNumber = true;
+ return this;
+ }
+ public Builder clearPersonalNumber() {
+ result.hasPersonalNumber = false;
+ result.personalNumber_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required .i18n.phonenumbers.PhoneNumberDesc voip = 8;
+ public boolean hasVoip() {
+ return result.hasVoip();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc getVoip() {
+ return result.getVoip();
+ }
+ public Builder setVoip(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasVoip = true;
+ result.voip_ = value;
+ return this;
+ }
+ public Builder setVoip(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.Builder builderForValue) {
+ result.hasVoip = true;
+ result.voip_ = builderForValue.build();
+ return this;
+ }
+ public Builder mergeVoip(com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc value) {
+ if (result.hasVoip() &&
+ result.voip_ != com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance()) {
+ result.voip_ =
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.newBuilder(result.voip_).mergeFrom(value).buildPartial();
+ } else {
+ result.voip_ = value;
+ }
+ result.hasVoip = true;
+ return this;
+ }
+ public Builder clearVoip() {
+ result.hasVoip = false;
+ result.voip_ = com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc.getDefaultInstance();
+ return this;
+ }
+
+ // required string id = 9;
+ public boolean hasId() {
+ return result.hasId();
+ }
+ public java.lang.String getId() {
+ return result.getId();
+ }
+ public Builder setId(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasId = true;
+ result.id_ = value;
+ return this;
+ }
+ public Builder clearId() {
+ result.hasId = false;
+ result.id_ = getDefaultInstance().getId();
+ return this;
+ }
+
+ // required int32 country_code = 10;
+ public boolean hasCountryCode() {
+ return result.hasCountryCode();
+ }
+ public int getCountryCode() {
+ return result.getCountryCode();
+ }
+ public Builder setCountryCode(int value) {
+ result.hasCountryCode = true;
+ result.countryCode_ = value;
+ return this;
+ }
+ public Builder clearCountryCode() {
+ result.hasCountryCode = false;
+ result.countryCode_ = 0;
+ return this;
+ }
+
+ // required string international_prefix = 11;
+ public boolean hasInternationalPrefix() {
+ return result.hasInternationalPrefix();
+ }
+ public java.lang.String getInternationalPrefix() {
+ return result.getInternationalPrefix();
+ }
+ public Builder setInternationalPrefix(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasInternationalPrefix = true;
+ result.internationalPrefix_ = value;
+ return this;
+ }
+ public Builder clearInternationalPrefix() {
+ result.hasInternationalPrefix = false;
+ result.internationalPrefix_ = getDefaultInstance().getInternationalPrefix();
+ return this;
+ }
+
+ // optional string preferred_international_prefix = 17;
+ public boolean hasPreferredInternationalPrefix() {
+ return result.hasPreferredInternationalPrefix();
+ }
+ public java.lang.String getPreferredInternationalPrefix() {
+ return result.getPreferredInternationalPrefix();
+ }
+ public Builder setPreferredInternationalPrefix(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPreferredInternationalPrefix = true;
+ result.preferredInternationalPrefix_ = value;
+ return this;
+ }
+ public Builder clearPreferredInternationalPrefix() {
+ result.hasPreferredInternationalPrefix = false;
+ result.preferredInternationalPrefix_ = getDefaultInstance().getPreferredInternationalPrefix();
+ return this;
+ }
+
+ // optional string national_prefix = 12;
+ public boolean hasNationalPrefix() {
+ return result.hasNationalPrefix();
+ }
+ public java.lang.String getNationalPrefix() {
+ return result.getNationalPrefix();
+ }
+ public Builder setNationalPrefix(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalPrefix = true;
+ result.nationalPrefix_ = value;
+ return this;
+ }
+ public Builder clearNationalPrefix() {
+ result.hasNationalPrefix = false;
+ result.nationalPrefix_ = getDefaultInstance().getNationalPrefix();
+ return this;
+ }
+
+ // optional string preferred_extn_prefix = 13;
+ public boolean hasPreferredExtnPrefix() {
+ return result.hasPreferredExtnPrefix();
+ }
+ public java.lang.String getPreferredExtnPrefix() {
+ return result.getPreferredExtnPrefix();
+ }
+ public Builder setPreferredExtnPrefix(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasPreferredExtnPrefix = true;
+ result.preferredExtnPrefix_ = value;
+ return this;
+ }
+ public Builder clearPreferredExtnPrefix() {
+ result.hasPreferredExtnPrefix = false;
+ result.preferredExtnPrefix_ = getDefaultInstance().getPreferredExtnPrefix();
+ return this;
+ }
+
+ // optional string national_prefix_for_parsing = 15;
+ public boolean hasNationalPrefixForParsing() {
+ return result.hasNationalPrefixForParsing();
+ }
+ public java.lang.String getNationalPrefixForParsing() {
+ return result.getNationalPrefixForParsing();
+ }
+ public Builder setNationalPrefixForParsing(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalPrefixForParsing = true;
+ result.nationalPrefixForParsing_ = value;
+ return this;
+ }
+ public Builder clearNationalPrefixForParsing() {
+ result.hasNationalPrefixForParsing = false;
+ result.nationalPrefixForParsing_ = getDefaultInstance().getNationalPrefixForParsing();
+ return this;
+ }
+
+ // optional string national_prefix_transform_rule = 16;
+ public boolean hasNationalPrefixTransformRule() {
+ return result.hasNationalPrefixTransformRule();
+ }
+ public java.lang.String getNationalPrefixTransformRule() {
+ return result.getNationalPrefixTransformRule();
+ }
+ public Builder setNationalPrefixTransformRule(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalPrefixTransformRule = true;
+ result.nationalPrefixTransformRule_ = value;
+ return this;
+ }
+ public Builder clearNationalPrefixTransformRule() {
+ result.hasNationalPrefixTransformRule = false;
+ result.nationalPrefixTransformRule_ = getDefaultInstance().getNationalPrefixTransformRule();
+ return this;
+ }
+
+ // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false];
+ public boolean hasSameMobileAndFixedLinePattern() {
+ return result.hasSameMobileAndFixedLinePattern();
+ }
+ public boolean getSameMobileAndFixedLinePattern() {
+ return result.getSameMobileAndFixedLinePattern();
+ }
+ public Builder setSameMobileAndFixedLinePattern(boolean value) {
+ result.hasSameMobileAndFixedLinePattern = true;
+ result.sameMobileAndFixedLinePattern_ = value;
+ return this;
+ }
+ public Builder clearSameMobileAndFixedLinePattern() {
+ result.hasSameMobileAndFixedLinePattern = false;
+ result.sameMobileAndFixedLinePattern_ = false;
+ return this;
+ }
+
+ // repeated .i18n.phonenumbers.NumberFormat number_format = 19;
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> getNumberFormatList() {
+ return java.util.Collections.unmodifiableList(result.numberFormat_);
+ }
+ public int getNumberFormatCount() {
+ return result.getNumberFormatCount();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat getNumberFormat(int index) {
+ return result.getNumberFormat(index);
+ }
+ public Builder setNumberFormat(int index, com.google.i18n.phonenumbers.Phonemetadata.NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.numberFormat_.set(index, value);
+ return this;
+ }
+ public Builder setNumberFormat(int index, com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder builderForValue) {
+ result.numberFormat_.set(index, builderForValue.build());
+ return this;
+ }
+ public Builder addNumberFormat(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ if (result.numberFormat_.isEmpty()) {
+ result.numberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.numberFormat_.add(value);
+ return this;
+ }
+ public Builder addNumberFormat(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder builderForValue) {
+ if (result.numberFormat_.isEmpty()) {
+ result.numberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.numberFormat_.add(builderForValue.build());
+ return this;
+ }
+ public Builder addAllNumberFormat(
+ java.lang.Iterable<? extends com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> values) {
+ if (result.numberFormat_.isEmpty()) {
+ result.numberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ super.addAll(values, result.numberFormat_);
+ return this;
+ }
+ public Builder clearNumberFormat() {
+ result.numberFormat_ = java.util.Collections.emptyList();
+ return this;
+ }
+
+ // repeated .i18n.phonenumbers.NumberFormat intl_number_format = 20;
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> getIntlNumberFormatList() {
+ return java.util.Collections.unmodifiableList(result.intlNumberFormat_);
+ }
+ public int getIntlNumberFormatCount() {
+ return result.getIntlNumberFormatCount();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.NumberFormat getIntlNumberFormat(int index) {
+ return result.getIntlNumberFormat(index);
+ }
+ public Builder setIntlNumberFormat(int index, com.google.i18n.phonenumbers.Phonemetadata.NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.intlNumberFormat_.set(index, value);
+ return this;
+ }
+ public Builder setIntlNumberFormat(int index, com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder builderForValue) {
+ result.intlNumberFormat_.set(index, builderForValue.build());
+ return this;
+ }
+ public Builder addIntlNumberFormat(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ if (result.intlNumberFormat_.isEmpty()) {
+ result.intlNumberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.intlNumberFormat_.add(value);
+ return this;
+ }
+ public Builder addIntlNumberFormat(com.google.i18n.phonenumbers.Phonemetadata.NumberFormat.Builder builderForValue) {
+ if (result.intlNumberFormat_.isEmpty()) {
+ result.intlNumberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ result.intlNumberFormat_.add(builderForValue.build());
+ return this;
+ }
+ public Builder addAllIntlNumberFormat(
+ java.lang.Iterable<? extends com.google.i18n.phonenumbers.Phonemetadata.NumberFormat> values) {
+ if (result.intlNumberFormat_.isEmpty()) {
+ result.intlNumberFormat_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.NumberFormat>();
+ }
+ super.addAll(values, result.intlNumberFormat_);
+ return this;
+ }
+ public Builder clearIntlNumberFormat() {
+ result.intlNumberFormat_ = java.util.Collections.emptyList();
+ return this;
+ }
+
+ // optional string national_prefix_formatting_rule = 21;
+ public boolean hasNationalPrefixFormattingRule() {
+ return result.hasNationalPrefixFormattingRule();
+ }
+ public java.lang.String getNationalPrefixFormattingRule() {
+ return result.getNationalPrefixFormattingRule();
+ }
+ public Builder setNationalPrefixFormattingRule(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasNationalPrefixFormattingRule = true;
+ result.nationalPrefixFormattingRule_ = value;
+ return this;
+ }
+ public Builder clearNationalPrefixFormattingRule() {
+ result.hasNationalPrefixFormattingRule = false;
+ result.nationalPrefixFormattingRule_ = getDefaultInstance().getNationalPrefixFormattingRule();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.PhoneMetadata)
+ }
+
+ static {
+ defaultInstance = new PhoneMetadata(true);
+ com.google.i18n.phonenumbers.Phonemetadata.internalForceInit();
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:i18n.phonenumbers.PhoneMetadata)
+ }
+
+ public static final class PhoneMetadataCollection extends
+ com.google.protobuf.GeneratedMessageLite {
+ // Use PhoneMetadataCollection.newBuilder() to construct.
+ private PhoneMetadataCollection() {
+ initFields();
+ }
+ private PhoneMetadataCollection(boolean noInit) {}
+
+ private static final PhoneMetadataCollection defaultInstance;
+ public static PhoneMetadataCollection getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PhoneMetadataCollection getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ // repeated .i18n.phonenumbers.PhoneMetadata metadata = 1;
+ public static final int METADATA_FIELD_NUMBER = 1;
+ private java.util.List<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata> metadata_ =
+ java.util.Collections.emptyList();
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata> getMetadataList() {
+ return metadata_;
+ }
+ public int getMetadataCount() { return metadata_.size(); }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata getMetadata(int index) {
+ return metadata_.get(index);
+ }
+
+ private void initFields() {
+ }
+ public final boolean isInitialized() {
+ for (com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata element : getMetadataList()) {
+ if (!element.isInitialized()) return false;
+ }
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ for (com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata element : getMetadataList()) {
+ output.writeMessage(1, element);
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ for (com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata element : getMetadataList()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(1, element);
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection, Builder> {
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection result;
+
+ // Construct using com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection.newBuilder()
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection();
+ return builder;
+ }
+
+ protected com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection internalGetResult() {
+ return result;
+ }
+
+ public Builder clear() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "Cannot call clear() after build().");
+ }
+ result = new com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection();
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(result);
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection getDefaultInstanceForType() {
+ return com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection.getDefaultInstance();
+ }
+
+ public boolean isInitialized() {
+ return result.isInitialized();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection build() {
+ if (result != null && !isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return buildPartial();
+ }
+
+ private com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection buildPartial() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
+ if (result.metadata_ != java.util.Collections.EMPTY_LIST) {
+ result.metadata_ =
+ java.util.Collections.unmodifiableList(result.metadata_);
+ }
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ public Builder mergeFrom(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection other) {
+ if (other == com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection.getDefaultInstance()) return this;
+ if (!other.metadata_.isEmpty()) {
+ if (result.metadata_.isEmpty()) {
+ result.metadata_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata>();
+ }
+ result.metadata_.addAll(other.metadata_);
+ }
+ return this;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 10: {
+ com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.Builder subBuilder = com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.newBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ addMetadata(subBuilder.buildPartial());
+ break;
+ }
+ }
+ }
+ }
+
+
+ // repeated .i18n.phonenumbers.PhoneMetadata metadata = 1;
+ public java.util.List<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata> getMetadataList() {
+ return java.util.Collections.unmodifiableList(result.metadata_);
+ }
+ public int getMetadataCount() {
+ return result.getMetadataCount();
+ }
+ public com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata getMetadata(int index) {
+ return result.getMetadata(index);
+ }
+ public Builder setMetadata(int index, com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.metadata_.set(index, value);
+ return this;
+ }
+ public Builder setMetadata(int index, com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.Builder builderForValue) {
+ result.metadata_.set(index, builderForValue.build());
+ return this;
+ }
+ public Builder addMetadata(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ if (result.metadata_.isEmpty()) {
+ result.metadata_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata>();
+ }
+ result.metadata_.add(value);
+ return this;
+ }
+ public Builder addMetadata(com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata.Builder builderForValue) {
+ if (result.metadata_.isEmpty()) {
+ result.metadata_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata>();
+ }
+ result.metadata_.add(builderForValue.build());
+ return this;
+ }
+ public Builder addAllMetadata(
+ java.lang.Iterable<? extends com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata> values) {
+ if (result.metadata_.isEmpty()) {
+ result.metadata_ = new java.util.ArrayList<com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata>();
+ }
+ super.addAll(values, result.metadata_);
+ return this;
+ }
+ public Builder clearMetadata() {
+ result.metadata_ = java.util.Collections.emptyList();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.PhoneMetadataCollection)
+ }
+
+ static {
+ defaultInstance = new PhoneMetadataCollection(true);
+ com.google.i18n.phonenumbers.Phonemetadata.internalForceInit();
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:i18n.phonenumbers.PhoneMetadataCollection)
+ }
+
+
+ static {
+ }
+
+ public static void internalForceInit() {}
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/java/src/com/google/i18n/phonenumbers/Phonenumber.java b/java/src/com/google/i18n/phonenumbers/Phonenumber.java
new file mode 100644
index 0000000..c3b5089
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/Phonenumber.java
@@ -0,0 +1,392 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: phonenumber.proto
+
+package com.google.i18n.phonenumbers;
+
+public final class Phonenumber {
+ private Phonenumber() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistryLite registry) {
+ }
+ public static final class PhoneNumber extends
+ com.google.protobuf.GeneratedMessageLite {
+ // Use PhoneNumber.newBuilder() to construct.
+ private PhoneNumber() {
+ initFields();
+ }
+ private PhoneNumber(boolean noInit) {}
+
+ private static final PhoneNumber defaultInstance;
+ public static PhoneNumber getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public PhoneNumber getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ // required int32 country_code = 1;
+ public static final int COUNTRY_CODE_FIELD_NUMBER = 1;
+ private boolean hasCountryCode;
+ private int countryCode_ = 0;
+ public boolean hasCountryCode() { return hasCountryCode; }
+ public int getCountryCode() { return countryCode_; }
+
+ // required uint64 national_number = 2;
+ public static final int NATIONAL_NUMBER_FIELD_NUMBER = 2;
+ private boolean hasNationalNumber;
+ private long nationalNumber_ = 0L;
+ public boolean hasNationalNumber() { return hasNationalNumber; }
+ public long getNationalNumber() { return nationalNumber_; }
+
+ // optional string extension = 3;
+ public static final int EXTENSION_FIELD_NUMBER = 3;
+ private boolean hasExtension;
+ private java.lang.String extension_ = "";
+ public boolean hasExtension() { return hasExtension; }
+ public java.lang.String getExtension() { return extension_; }
+
+ // optional bool italian_leading_zero = 4;
+ public static final int ITALIAN_LEADING_ZERO_FIELD_NUMBER = 4;
+ private boolean hasItalianLeadingZero;
+ private boolean italianLeadingZero_ = false;
+ public boolean hasItalianLeadingZero() { return hasItalianLeadingZero; }
+ public boolean getItalianLeadingZero() { return italianLeadingZero_; }
+
+ private void initFields() {
+ }
+ public final boolean isInitialized() {
+ if (!hasCountryCode) return false;
+ if (!hasNationalNumber) return false;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (hasCountryCode()) {
+ output.writeInt32(1, getCountryCode());
+ }
+ if (hasNationalNumber()) {
+ output.writeUInt64(2, getNationalNumber());
+ }
+ if (hasExtension()) {
+ output.writeString(3, getExtension());
+ }
+ if (hasItalianLeadingZero()) {
+ output.writeBool(4, getItalianLeadingZero());
+ }
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasCountryCode()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(1, getCountryCode());
+ }
+ if (hasNationalNumber()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(2, getNationalNumber());
+ }
+ if (hasExtension()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeStringSize(3, getExtension());
+ }
+ if (hasItalianLeadingZero()) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBoolSize(4, getItalianLeadingZero());
+ }
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ Builder builder = newBuilder();
+ if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+ return builder.buildParsed();
+ } else {
+ return null;
+ }
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input).buildParsed();
+ }
+ public static com.google.i18n.phonenumbers.Phonenumber.PhoneNumber parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return newBuilder().mergeFrom(input, extensionRegistry)
+ .buildParsed();
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.i18n.phonenumbers.Phonenumber.PhoneNumber prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessageLite.Builder<
+ com.google.i18n.phonenumbers.Phonenumber.PhoneNumber, Builder> {
+ private com.google.i18n.phonenumbers.Phonenumber.PhoneNumber result;
+
+ // Construct using com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.newBuilder()
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new com.google.i18n.phonenumbers.Phonenumber.PhoneNumber();
+ return builder;
+ }
+
+ protected com.google.i18n.phonenumbers.Phonenumber.PhoneNumber internalGetResult() {
+ return result;
+ }
+
+ public Builder clear() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "Cannot call clear() after build().");
+ }
+ result = new com.google.i18n.phonenumbers.Phonenumber.PhoneNumber();
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(result);
+ }
+
+ public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber getDefaultInstanceForType() {
+ return com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.getDefaultInstance();
+ }
+
+ public boolean isInitialized() {
+ return result.isInitialized();
+ }
+ public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber build() {
+ if (result != null && !isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return buildPartial();
+ }
+
+ private com.google.i18n.phonenumbers.Phonenumber.PhoneNumber buildParsed()
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ result).asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ public com.google.i18n.phonenumbers.Phonenumber.PhoneNumber buildPartial() {
+ if (result == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
+ com.google.i18n.phonenumbers.Phonenumber.PhoneNumber returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ public Builder mergeFrom(com.google.i18n.phonenumbers.Phonenumber.PhoneNumber other) {
+ if (other == com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.getDefaultInstance()) return this;
+ if (other.hasCountryCode()) {
+ setCountryCode(other.getCountryCode());
+ }
+ if (other.hasNationalNumber()) {
+ setNationalNumber(other.getNationalNumber());
+ }
+ if (other.hasExtension()) {
+ setExtension(other.getExtension());
+ }
+ if (other.hasItalianLeadingZero()) {
+ setItalianLeadingZero(other.getItalianLeadingZero());
+ }
+ return this;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ while (true) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ return this;
+ default: {
+ if (!parseUnknownField(input, extensionRegistry, tag)) {
+ return this;
+ }
+ break;
+ }
+ case 8: {
+ setCountryCode(input.readInt32());
+ break;
+ }
+ case 16: {
+ setNationalNumber(input.readUInt64());
+ break;
+ }
+ case 26: {
+ setExtension(input.readString());
+ break;
+ }
+ case 32: {
+ setItalianLeadingZero(input.readBool());
+ break;
+ }
+ }
+ }
+ }
+
+
+ // required int32 country_code = 1;
+ public boolean hasCountryCode() {
+ return result.hasCountryCode();
+ }
+ public int getCountryCode() {
+ return result.getCountryCode();
+ }
+ public Builder setCountryCode(int value) {
+ result.hasCountryCode = true;
+ result.countryCode_ = value;
+ return this;
+ }
+ public Builder clearCountryCode() {
+ result.hasCountryCode = false;
+ result.countryCode_ = 0;
+ return this;
+ }
+
+ // required uint64 national_number = 2;
+ public boolean hasNationalNumber() {
+ return result.hasNationalNumber();
+ }
+ public long getNationalNumber() {
+ return result.getNationalNumber();
+ }
+ public Builder setNationalNumber(long value) {
+ result.hasNationalNumber = true;
+ result.nationalNumber_ = value;
+ return this;
+ }
+ public Builder clearNationalNumber() {
+ result.hasNationalNumber = false;
+ result.nationalNumber_ = 0L;
+ return this;
+ }
+
+ // optional string extension = 3;
+ public boolean hasExtension() {
+ return result.hasExtension();
+ }
+ public java.lang.String getExtension() {
+ return result.getExtension();
+ }
+ public Builder setExtension(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ result.hasExtension = true;
+ result.extension_ = value;
+ return this;
+ }
+ public Builder clearExtension() {
+ result.hasExtension = false;
+ result.extension_ = getDefaultInstance().getExtension();
+ return this;
+ }
+
+ // optional bool italian_leading_zero = 4;
+ public boolean hasItalianLeadingZero() {
+ return result.hasItalianLeadingZero();
+ }
+ public boolean getItalianLeadingZero() {
+ return result.getItalianLeadingZero();
+ }
+ public Builder setItalianLeadingZero(boolean value) {
+ result.hasItalianLeadingZero = true;
+ result.italianLeadingZero_ = value;
+ return this;
+ }
+ public Builder clearItalianLeadingZero() {
+ result.hasItalianLeadingZero = false;
+ result.italianLeadingZero_ = false;
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:i18n.phonenumbers.PhoneNumber)
+ }
+
+ static {
+ defaultInstance = new PhoneNumber(true);
+ com.google.i18n.phonenumbers.Phonenumber.internalForceInit();
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:i18n.phonenumbers.PhoneNumber)
+ }
+
+
+ static {
+ }
+
+ public static void internalForceInit() {}
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/java/src/com/google/i18n/phonenumbers/phonemetadata.proto b/java/src/com/google/i18n/phonenumbers/phonemetadata.proto
new file mode 100644
index 0000000..3e744e3
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/phonemetadata.proto
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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 protocol buffer for holding metadata for international
+// telephone numbers.
+// @author Shaopeng Jia
+
+syntax = "proto2";
+
+option java_package = "com.google.i18n.phonenumbers";
+option optimize_for = LITE_RUNTIME;
+package i18n.phonenumbers;
+
+message NumberFormat {
+ // pattern is a regex that is used to match the national (significant)
+ // number. For example, the pattern "(20)(\d{4})(\d{4})" will match number
+ // "2070313000", which is the national (significant) number for Google London.
+ // Note the presence of the parentheses, which are capturing groups what
+ // specifies the grouping of numbers.
+ required string pattern = 1;
+
+ // format specifies how the national (significant) number matched by
+ // pattern should be formatted.
+ // Using the same example as above, format could contain "$1 $2 $3",
+ // meaning that the number should be formatted as "20 7031 3000".
+ // Each $x are replaced by the numbers captured by group x in the
+ // regex specified by pattern.
+ required string format = 2;
+
+ // leadingDigits is a regex that is used to match up to the first four digits
+ // of the national (significant) number. When the match is successful, the
+ // accompanying pattern and format should be used to format this number. For
+ // example, if leading_digits="[1-3]|44", then all the national numbers
+ // starting with 1, 2, 3 or 44 should be formatted using the accompanying
+ // pattern and format.
+ optional string leading_digits = 3;
+
+ // This field specifies how the national prefix ($NP) together with the first
+ // group ($FG) in the national significant number should be formatted in
+ // the NATIONAL format when a national prefix exists for a certain country.
+ // When present, it overrides the national_prefix_formatting_rule specified
+ // in PhoneNumberDesc. See the comment in PhoneNumberDesc for more information
+ // on how this rule is specified.
+ optional string national_prefix_formatting_rule = 4;
+}
+
+message PhoneNumberDesc {
+ // The national_number_pattern is the pattern that a valid national
+ // significant number would match. This specifies information such as its
+ // total length and leading digits.
+ optional string national_number_pattern = 2;
+
+ // The possible_number_pattern represents what a potentially valid phone
+ // number for this region may be written as. This is a superset of the
+ // national_number_pattern above and includes numbers that have the area code
+ // omitted. Typically the only restrictions here are in the number of digits.
+ // This could be used to highlight tokens in a text that may be a phone
+ // number, or to quickly prune numbers that could not possibly be a phone
+ // number for this locale.
+ optional string possible_number_pattern = 3;
+
+ // An example national significant number for the specific type. It should
+ // not contain any formatting information.
+ optional string example_number = 6;
+}
+
+message PhoneMetadata {
+ // The general_desc contains information which is a superset of descriptions
+ // for all types of phone numbers. If any element is missing in the
+ // description of a specific type in the XML file, the element will inherit
+ // from its counterpart in the general_desc. Every locale is assumed to have
+ // fixed line and mobile numbers - if these types are missing in the XML
+ // file, they will inherit all fields from the general_desc. For all other
+ // types, if the whole type is missing in the xml file, it will be given a
+ // national_number_pattern of "NA" and a possible_number_pattern of "NA".
+ required PhoneNumberDesc general_desc = 1;
+ required PhoneNumberDesc fixed_line = 2;
+ required PhoneNumberDesc mobile = 3;
+ required PhoneNumberDesc toll_free = 4;
+ required PhoneNumberDesc premium_rate = 5;
+ required PhoneNumberDesc shared_cost = 6;
+ required PhoneNumberDesc personal_number = 7;
+ required PhoneNumberDesc voip = 8;
+
+ // The ISO 3166-1 alpha-2 representation of a country/region
+ required string id = 9;
+
+ // The country calling code that one would dial from overseas when trying to
+ // dial a phone number in this country. For example, this would be "64" for
+ // New Zealand.
+ required int32 country_code = 10;
+
+ // The international_prefix of country A is the number that needs to be
+ // dialled from country A to another country (country B). This is followed
+ // by the country code for country B. Note that some countries may have more
+ // than one international prefix, and for those cases, a regular expression
+ // matching the international prefixes will be stored in this field.
+ required string international_prefix = 11;
+
+ // If more than one international prefix is present, a preferred prefix can
+ // be specified here for out-of-country formatting purposes. If this field is
+ // not present, and multiple international prefixes are present, then "+"
+ // will be used instead.
+ optional string preferred_international_prefix = 17;
+
+ // The national prefix of country A is the number that needs to be dialled
+ // before the national significant number when dialling internally. This
+ // would not be dialled when dialling internationally. For example, in New
+ // Zealand, the number that would be locally dialled as 09 345 3456 would be
+ // dialled from overseas as +64 9 345 3456. In this case, 0 is the national
+ // prefix.
+ optional string national_prefix = 12;
+
+ // The preferred prefix when specifying an extension in this country. This is
+ // used for formatting only, and if this is not specified, a suitable default
+ // should be used instead. For example, if you wanted extensions to be
+ // formatted in the following way:
+ // 1 (365) 345 445 ext. 2345
+ // " ext. " should be the preferred extension prefix.
+ optional string preferred_extn_prefix = 13;
+
+ // This field is used for cases where the national prefix of a country
+ // contains a carrier selection code, and is written in the form of a
+ // regular expression. For example, to dial the number 2222-2222 in
+ // Fortaleza, Brazil (area code 85) using the long distance carrier Oi
+ // (selection code 31), one would dial 0 31 85 2222 2222. Assuming the
+ // only other possible carrier selection code is 32, the field will
+ // contain "03[12]".
+ //
+ // When it is missing from the XML file, this field inherits the value of
+ // national_prefix, if that is present.
+ optional string national_prefix_for_parsing = 15;
+
+ // This field is only populated and used under very rare situations.
+ // For example, mobile numbers in Argentina are written in two completely
+ // different ways when dialed in-country and out-of-country
+ // (e.g. 0343 15 555 1212 is exactly the same number as +54 9 343 555 1212).
+ // This field is used together with national_prefix_for_parsing to transform
+ // the number into a particular representation for storing in the phonenumber
+ // proto buffer in those rare cases.
+ optional string national_prefix_transform_rule = 16;
+
+ // Specifies whether the mobile and fixed-line patterns are the same or not.
+ // This is used to speed up determining phone number type in countries where
+ // these two types of phone numbers can never be distinguished.
+ optional bool same_mobile_and_fixed_line_pattern = 18 [default=false];
+
+ // Note that the number format here is used for formatting only, not parsing.
+ // Hence all the varied ways a user *may* write a number need not be recorded
+ // - just the ideal way we would like to format it for them. When this element
+ // is absent, the national significant number will be formatted as a whole
+ // without any formatting applied.
+ //
+ // When formatting, the library goes through the list of formats from the
+ // beginning and the first successful match is used to do the formatting.
+ // A match is successful if the phone number being formatted starts with
+ // digits matching the leadingDigits and the number itself matches the
+ // corresponding pattern. However, AsYouTypeFormatter goes through the whole
+ // list and selects formats whose leadingDigits match what has been typed
+ // so far. Therefore, having more specific leadingDigits improves the
+ // performance of AsYouTypeFormatter in terms of speed.
+ repeated NumberFormat number_format = 19;
+
+ // This field is populated only when the national significant number is
+ // formatted differently when it forms part of the INTERNATIONAL format
+ // and NATIONAL format. A case in point is mobile numbers in Argentina:
+ // The number, which would be written in INTERNATIONAL format as
+ // +54 9 343 555 1212, will be written as 0343 15 555 1212 for NATIONAL
+ // format. In this case, the prefix 9 is inserted when dialling from
+ // overseas, but otherwise the prefix 0 and the carrier selection code
+ // 15 (inserted after the area code of 343) is used.
+ repeated NumberFormat intl_number_format = 20;
+
+ // This field specifies how the national prefix ($NP) together with the first
+ // group ($FG) in the national significant number should be formatted in
+ // the NATIONAL format when a national prefix exists for a certain country.
+ // For example, when this field contains "($NP$FG)", a number from Beijing,
+ // China (whose $NP = 0), which would by default be formatted without
+ // national prefix as 10 1234 5678 in NATIONAL format, will instead be
+ // formatted as (010) 1234 5678; to format it as (0)10 1234 5678, the field
+ // would contain "($NP)$FG". Note $FG should always be present in this field,
+ // but $NP can be omitted. For example, having "$FG" could indicate the
+ // number should be formatted in NATIONAL format without the national prefix.
+ // This is commonly used to override the rule from generalDesc.
+ //
+ // When this field is missing, a number will be formatted without national
+ // prefix in NATIONAL format. This field does not affect how a number
+ // is formatted in other formats, such as INTERNATIONAL.
+ //
+ // This field applies to all numberFormats unless overridden by the
+ // national_prefix_formatting_rule in a specific numberFormat.
+ optional string national_prefix_formatting_rule = 21;
+}
+
+message PhoneMetadataCollection {
+ repeated PhoneMetadata metadata = 1;
+}
diff --git a/java/src/com/google/i18n/phonenumbers/phonenumber.proto b/java/src/com/google/i18n/phonenumbers/phonenumber.proto
new file mode 100644
index 0000000..4238274
--- /dev/null
+++ b/java/src/com/google/i18n/phonenumbers/phonenumber.proto
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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 protocol buffer for representing international telephone numbers.
+// @author Shaopeng Jia
+
+syntax = "proto2";
+
+option java_package = "com.google.i18n.phonenumbers";
+option optimize_for = LITE_RUNTIME;
+package i18n.phonenumbers;
+
+message PhoneNumber {
+ required int32 country_code = 1;
+
+// National (significant) Number is defined in International Telecommunication Union Recommendation
+// E.164. It is a language/country-neutral representation of a phone number at a country level. For
+// countries which have the concept of Area Code, the National (significant) Number contains the
+// area code. It contains a maximum number of digits which equal to 15 - n, where n is the number of
+// digits of the country code. Take note that National (significant) Number does not contain
+// National(trunk) prefix. Obviously, as a uint64, it will never contain any formatting (hypens,
+// spaces, parentheses), nor any alphanumeric spellings.
+ required uint64 national_number = 2;
+
+// Extension is not standardized in ITU recommendations, except for being defined as a series of
+// numbers with a maximum length of 40 digits. It is defined as a string here to accommodate for the
+// possible use of a leading zero in the extension (organizations have complete freedom to do so,
+// as there is no standard defined). However, only ASCII digits should be stored here.
+ optional string extension = 3;
+
+// The leading zero in the national (significant) number of an Italian phone number has a special
+// meaning. Unlike the rest of the world, it indicates the number is a fixed-line number. There have
+// been plans to migrate fixed-line numbers to start with the digit two since December 2000, but it
+// has not happened yet. See http://en.wikipedia.org/wiki/%2B39 for more details.
+//
+// This field can be safely ignored (no need to set it) if you are not dealing with Italian
+// phone numbers. For an Italian phone number, if its national (significant) number starts
+// with the digit zero, set this flag to true.
+ optional bool italian_leading_zero = 4;
+}
+
+// Examples
+//
+// Google MTV, +1 650-253-0000, (650) 253-0000
+// country_code: 1
+// national_number: 6502530000
+//
+// Google Paris, +33 (0)1 42 68 53 00, 01 42 68 53 00
+// country_code: 33
+// national_number: 142685300
+//
+// Google Beijing, +86-10-62503000, (010) 62503000
+// country_code: 86
+// national_number: 1062503000
+//
+// Google Italy, +39 02-36618 300, 02-36618 300
+// country_code: 39
+// national_number: 236618300
+// italian_leading_zero: true
diff --git a/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java b/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java
new file mode 100644
index 0000000..6eb77f9
--- /dev/null
+++ b/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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 PhoneNumberUtil.java
+ *
+ * Note that these tests use the metadata contained in the file specified by TEST_META_DATA_FILE,
+ * not the normal metadata file, so should not be used for regression test purposes - these tests
+ * are illustrative only and test functionality.
+ *
+ * @author Shaopeng Jia
+ */
+public class AsYouTypeFormatterTest extends TestCase {
+ private PhoneNumberUtil phoneUtil;
+ private static final String TEST_META_DATA_FILE =
+ "/com/google/i18n/phonenumbers/test/generated_files/PhoneNumberMetadataProtoForTesting";
+
+ public AsYouTypeFormatterTest() {
+ PhoneNumberUtil.resetInstance();
+ InputStream in = PhoneNumberUtilTest.class.getResourceAsStream(TEST_META_DATA_FILE);
+ phoneUtil = PhoneNumberUtil.getInstance(in);
+ }
+
+ public void testAsYouTypeFormatterUS() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("US");
+ 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("650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("650 253 2\u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 22\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 222\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 2222", 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("650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("650 253 2\u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 22\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 222\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 2222", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("6", formatter.inputDigit('6'));
+ assertEquals("65", formatter.inputDigit('5'));
+ assertEquals("650", formatter.inputDigit('0'));
+ assertEquals("650-", formatter.inputDigit('-'));
+ assertEquals("650-2", formatter.inputDigit('2'));
+ assertEquals("650-25", formatter.inputDigit('5'));
+ assertEquals("650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('-'));
+ assertEquals("650 253 2\u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 22\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("650 253 222\u2008", 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("0114", formatter.inputDigit('4'));
+ assertEquals("01148", formatter.inputDigit('8'));
+ assertEquals("011 48 8", formatter.inputDigit('8'));
+ assertEquals("011 48 88", formatter.inputDigit('8'));
+ assertEquals("011 48 881", formatter.inputDigit('1'));
+ assertEquals("011 48 88 12\u2008 \u2008\u2008 \u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("011 48 88 123 \u2008\u2008 \u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("011 48 88 123 1\u2008 \u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("011 48 88 123 12 \u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("011 48 88 123 12 1\u2008", formatter.inputDigit('1'));
+ assertEquals("011 48 88 123 12 12", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("01", formatter.inputDigit('1'));
+ assertEquals("011", formatter.inputDigit('1'));
+ assertEquals("0114", formatter.inputDigit('4'));
+ assertEquals("01144", formatter.inputDigit('4'));
+ assertEquals("011 44 6", formatter.inputDigit('6'));
+ assertEquals("011 44 61", formatter.inputDigit('1'));
+ assertEquals("011 44 612", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123 \u2008\u2008\u2008 \u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("011 44 6 123 1\u2008\u2008 \u2008\u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("011 44 6 123 12\u2008 \u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123 123 \u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("011 44 6 123 123 1\u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("011 44 6 123 123 12\u2008", formatter.inputDigit('2'));
+ assertEquals("011 44 6 123 123 123", formatter.inputDigit('3'));
+
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+1", formatter.inputDigit('1'));
+ assertEquals("+16", formatter.inputDigit('6'));
+ assertEquals("+165", formatter.inputDigit('5'));
+ assertEquals("+1650", formatter.inputDigit('0'));
+ assertEquals("+1 650 2\u2008\u2008 \u2008\u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("+1 650 25\u2008 \u2008\u2008\u2008\u2008", formatter.inputDigit('5'));
+ assertEquals("+1 650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("+1 650 253 2\u2008\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 22\u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("+1 650 253 222\u2008", formatter.inputDigit('2'));
+
+ formatter.clear();
+ assertEquals("+", formatter.inputDigit('+'));
+ assertEquals("+4", formatter.inputDigit('4'));
+ assertEquals("+48", formatter.inputDigit('8'));
+ assertEquals("+488", formatter.inputDigit('8'));
+ assertEquals("+4888", formatter.inputDigit('8'));
+ assertEquals("+48 881", formatter.inputDigit('1'));
+ assertEquals("+48 88 12\u2008 \u2008\u2008 \u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("+48 88 123 \u2008\u2008 \u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("+48 88 123 1\u2008 \u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("+48 88 123 12 \u2008\u2008", formatter.inputDigit('2'));
+ assertEquals("+48 88 123 12 1\u2008", formatter.inputDigit('1'));
+ assertEquals("+48 88 123 12 12", formatter.inputDigit('2'));
+
+ // Test US number with full-width characters.
+ formatter.clear();
+ assertEquals("\uFF16", formatter.inputDigit('\uFF16'));
+ assertEquals("\uFF16\uFF15", formatter.inputDigit('\uFF15'));
+ assertEquals("\uFF16\uFF15\uFF10", formatter.inputDigit('\uFF10'));
+ assertEquals("\uFF16\uFF15\uFF10\uFF12", formatter.inputDigit('\uFF12'));
+ assertEquals("\uFF16\uFF15\uFF10\uFF12\uFF15", formatter.inputDigit('\uFF15'));
+ assertEquals("650 253 \u2008\u2008\u2008\u2008", formatter.inputDigit('\uFF13'));
+ assertEquals("650 253 2\u2008\u2008\u2008", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 22\u2008\u2008", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 222\u2008", formatter.inputDigit('\uFF12'));
+ assertEquals("650 253 2222", formatter.inputDigit('\uFF12'));
+
+ // Mobile short code.
+ formatter.clear();
+ assertEquals("*", formatter.inputDigit('*'));
+ assertEquals("*1", formatter.inputDigit('1'));
+ assertEquals("*12", formatter.inputDigit('2'));
+ assertEquals("*121", formatter.inputDigit('1'));
+ assertEquals("*121#", formatter.inputDigit('#'));
+ }
+
+ public void testAsYouTypeFormatterGBFixedLine() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("GB");
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("020", formatter.inputDigit('0'));
+ assertEquals("0207", formatter.inputDigit('7'));
+ assertEquals("02070", formatter.inputDigit('0'));
+ assertEquals("020 703\u2008 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("020 7031 \u2008\u2008\u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("020 7031 3\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("020 7031 30\u2008\u2008", formatter.inputDigit('0'));
+ assertEquals("020 7031 300\u2008", formatter.inputDigit('0'));
+ assertEquals("020 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAsYouTypeFormatterGBTollFree() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("GB");
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("08", formatter.inputDigit('8'));
+ assertEquals("080", formatter.inputDigit('0'));
+ assertEquals("0807", formatter.inputDigit('7'));
+ assertEquals("08070", formatter.inputDigit('0'));
+ assertEquals("080 703\u2008 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("080 7031 \u2008\u2008\u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("080 7031 3\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("080 7031 30\u2008\u2008", formatter.inputDigit('0'));
+ assertEquals("080 7031 300\u2008", formatter.inputDigit('0'));
+ assertEquals("080 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAsYouTypeFormatterGBPremiumRate() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("GB");
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("09", formatter.inputDigit('9'));
+ assertEquals("090", formatter.inputDigit('0'));
+ assertEquals("0907", formatter.inputDigit('7'));
+ assertEquals("09070", formatter.inputDigit('0'));
+ assertEquals("090 703\u2008 \u2008\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("090 7031 \u2008\u2008\u2008\u2008", formatter.inputDigit('1'));
+ assertEquals("090 7031 3\u2008\u2008\u2008", formatter.inputDigit('3'));
+ assertEquals("090 7031 30\u2008\u2008", formatter.inputDigit('0'));
+ assertEquals("090 7031 300\u2008", formatter.inputDigit('0'));
+ assertEquals("090 7031 3000", formatter.inputDigit('0'));
+ }
+
+ public void testAsYouTypeFormatterNZMobile() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("NZ");
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("02", formatter.inputDigit('2'));
+ assertEquals("021", formatter.inputDigit('1'));
+ assertEquals("0211", formatter.inputDigit('1'));
+ assertEquals("02112", formatter.inputDigit('2'));
+ assertEquals("021123", formatter.inputDigit('3'));
+ assertEquals("0211234", formatter.inputDigit('4'));
+ assertEquals("02112345", formatter.inputDigit('5'));
+ assertEquals("021123456", formatter.inputDigit('6'));
+ }
+
+ public void testAsYouTypeFormatterDE() {
+ AsYouTypeFormatter formatter = phoneUtil.getAsYouTypeFormatter("DE");
+ assertEquals("0", formatter.inputDigit('0'));
+ assertEquals("03", formatter.inputDigit('3'));
+ assertEquals("030", formatter.inputDigit('0'));
+ assertEquals("0301", formatter.inputDigit('1'));
+ assertEquals("03012", formatter.inputDigit('2'));
+ assertEquals("030123", formatter.inputDigit('3'));
+ assertEquals("0301234", formatter.inputDigit('4'));
+ }
+}
diff --git a/java/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java b/java/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
new file mode 100644
index 0000000..d3fd37c
--- /dev/null
+++ b/java/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.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.getSupportedCountries()) {
+ 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 testSharedCost() throws Exception {
+ Set<PhoneNumberType> sharedCostTypes = EnumSet.of(PhoneNumberType.SHARED_COST);
+ checkNumbersValidAndCorrectType(PhoneNumberType.SHARED_COST, sharedCostTypes);
+ assertEquals(0, invalidCases.size());
+ assertEquals(0, wrongTypeCases.size());
+ }
+}
diff --git a/java/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
new file mode 100644
index 0000000..0721fa6
--- /dev/null
+++ b/java/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
@@ -0,0 +1,1456 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.Phonenumber.PhoneNumber;
+import com.google.protobuf.MessageLite;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * Unit tests for PhoneNumberUtil.java
+ *
+ * Note that these tests use the metadata contained in the file specified by TEST_META_DATA_FILE,
+ * not the normal metadata file, so should not be used for regression test purposes - these tests
+ * are illustrative only and test functionality.
+ *
+ * @author Shaopeng Jia
+ * @author Lara Rennie
+ */
+public class PhoneNumberUtilTest extends TestCase {
+ private PhoneNumberUtil phoneUtil;
+ private static final String TEST_META_DATA_FILE =
+ "/com/google/i18n/phonenumbers/test/generated_files/PhoneNumberMetadataProtoForTesting";
+
+ public PhoneNumberUtilTest() {
+ PhoneNumberUtil.resetInstance();
+ InputStream in = PhoneNumberUtilTest.class.getResourceAsStream(TEST_META_DATA_FILE);
+ phoneUtil = PhoneNumberUtil.getInstance(in);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private Boolean assertEquals(MessageLite message1, MessageLite message2) {
+ return PhoneNumberUtil.areSameMessages(message1, message2);
+ }
+
+ public void testGetInstanceLoadUSMetadata() throws IOException {
+ PhoneMetadata metadata = phoneUtil.getPhoneMetadata("US");
+ assertEquals("US", metadata.getId());
+ assertEquals(1, metadata.getCountryCode());
+ assertEquals("011", metadata.getInternationalPrefix());
+ assertFalse(metadata.hasNationalPrefix());
+ assertEquals(2, metadata.getNumberFormatCount());
+ assertEquals("(\\d{3})(\\d{3})(\\d{4})",
+ metadata.getNumberFormat(0).getPattern());
+ assertEquals("$1 $2 $3", metadata.getNumberFormat(0).getFormat());
+ assertEquals("[13-9]\\d{9}|2[0-35-9]\\d{8}",
+ metadata.getGeneralDesc().getNationalNumberPattern());
+ assertEquals("\\d{7,10}", metadata.getGeneralDesc().getPossibleNumberPattern());
+ assertEquals(metadata.getGeneralDesc(), 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.getPhoneMetadata("DE");
+ assertEquals("DE", metadata.getId());
+ assertEquals(49, metadata.getCountryCode());
+ assertEquals("00", metadata.getInternationalPrefix());
+ assertEquals("0", metadata.getNationalPrefix());
+ assertEquals(6, metadata.getNumberFormatCount());
+ assertEquals("9009", metadata.getNumberFormat(5).getLeadingDigits());
+ assertEquals("(\\d{3})(\\d{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{3,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.getPhoneMetadata("AR");
+ assertEquals("AR", metadata.getId());
+ assertEquals(54, metadata.getCountryCode());
+ assertEquals("00", metadata.getInternationalPrefix());
+ assertEquals("0", metadata.getNationalPrefix());
+ assertEquals("0(?:(11|343|3715)15)?", metadata.getNationalPrefixForParsing());
+ assertEquals("9$1", metadata.getNationalPrefixTransformRule());
+ assertEquals("9(\\d{4})(\\d{2})(\\d{4})",
+ metadata.getNumberFormat(3).getPattern());
+ assertEquals("$1 15 $2-$3", metadata.getNumberFormat(3).getFormat());
+ assertEquals("(9)(\\d{4})(\\d{2})(\\d{4})",
+ metadata.getIntlNumberFormat(3).getPattern());
+ assertEquals("$1 $2 $3 $4", metadata.getIntlNumberFormat(3).getFormat());
+ }
+
+ public void testGetExampleNumber() throws IOException {
+ PhoneNumber deNumber =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(30123456).build();
+ assertEquals(deNumber, phoneUtil.getExampleNumber("DE"));
+
+ assertEquals(deNumber,
+ phoneUtil.getExampleNumberForType("DE",
+ PhoneNumberUtil.PhoneNumberType.FIXED_LINE));
+ assertEquals(null,
+ phoneUtil.getExampleNumberForType("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("US",
+ PhoneNumberUtil.PhoneNumberType.FIXED_LINE));
+ assertNotNull(phoneUtil.getExampleNumberForType("US",
+ PhoneNumberUtil.PhoneNumberType.MOBILE));
+ }
+
+ 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));
+ }
+
+ 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() {
+ PhoneNumber usNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ assertEquals("650 253 0000", phoneUtil.format(usNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 650 253 0000",
+ phoneUtil.format(usNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber usNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(8002530000L).build();
+ assertEquals("800 253 0000", phoneUtil.format(usNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 800 253 0000",
+ phoneUtil.format(usNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber usNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(9002530000L).build();
+ assertEquals("900 253 0000", phoneUtil.format(usNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 900 253 0000",
+ phoneUtil.format(usNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatBSNumber() {
+ PhoneNumber bsNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2421234567L).build();
+ assertEquals("242 123 4567", phoneUtil.format(bsNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 242 123 4567",
+ phoneUtil.format(bsNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber bsNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(8002530000L).build();
+ assertEquals("800 253 0000", phoneUtil.format(bsNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 800 253 0000",
+ phoneUtil.format(bsNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber bsNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(9002530000L).build();
+ assertEquals("900 253 0000", phoneUtil.format(bsNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+1 900 253 0000",
+ phoneUtil.format(bsNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatGBNumber() {
+ PhoneNumber gbNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(2087389353L).build();
+ assertEquals("(020) 8738 9353", phoneUtil.format(gbNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+44 20 8738 9353",
+ phoneUtil.format(gbNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber gbNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(7912345678L).build();
+ assertEquals("(07912) 345 678", phoneUtil.format(gbNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+44 7912 345 678",
+ phoneUtil.format(gbNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatDENumber() {
+ PhoneNumber deNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(301234L).build();
+ assertEquals("030 1234", phoneUtil.format(deNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 30 1234",
+ phoneUtil.format(deNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber deNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(291123L).build();
+ assertEquals("0291 123", phoneUtil.format(deNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 291 123",
+ phoneUtil.format(deNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber deNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(29112345678L).build();
+ assertEquals("0291 12345678", phoneUtil.format(deNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 291 12345678",
+ phoneUtil.format(deNumber3,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+
+ PhoneNumber deNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(9123123L).build();
+ assertEquals("09123 123", phoneUtil.format(deNumber4,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 9123 123",
+ phoneUtil.format(deNumber4,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ PhoneNumber deNumber5 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(1234L).build();
+ // 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(deNumber5,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+49 1234",
+ phoneUtil.format(deNumber5,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ }
+
+ public void testFormatITNumber() {
+ PhoneNumber itNumber1 =
+ PhoneNumber.newBuilder()
+ .setCountryCode(39).setNationalNumber(236618300L).setItalianLeadingZero(true).build();
+ assertEquals("02 3661 8300", phoneUtil.format(itNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+39 02 3661 8300",
+ phoneUtil.format(itNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+390236618300",
+ phoneUtil.format(itNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+
+ PhoneNumber itNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(345678901L).build();
+ assertEquals("345 678 901", phoneUtil.format(itNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+39 345 678 901",
+ phoneUtil.format(itNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+39345678901",
+ phoneUtil.format(itNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ }
+
+ public void testFormatAUNumber() {
+ PhoneNumber auNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(61).setNationalNumber(236618300L).build();
+ assertEquals("02 3661 8300", phoneUtil.format(auNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+61 2 3661 8300",
+ phoneUtil.format(auNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+61236618300",
+ phoneUtil.format(auNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+
+ PhoneNumber auNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(61).setNationalNumber(1800123456L).build();
+ assertEquals("1800 123 456", phoneUtil.format(auNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+61 1800 123 456",
+ phoneUtil.format(auNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+611800123456",
+ phoneUtil.format(auNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ }
+
+ public void testFormatARNumber() {
+ PhoneNumber arNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(1187654321L).build();
+ assertEquals("011 8765-4321", phoneUtil.format(arNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+54 11 8765-4321",
+ phoneUtil.format(arNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+541187654321",
+ phoneUtil.format(arNumber1,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+
+ PhoneNumber arNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(91187654321L).build();
+ assertEquals("011 15 8765-4321", phoneUtil.format(arNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals("+54 9 11 8765 4321",
+ phoneUtil.format(arNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+5491187654321",
+ phoneUtil.format(arNumber2,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ }
+
+ public void testFormatOutOfCountryCallingNumber() {
+ PhoneNumber usNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(9002530000L).build();
+ assertEquals("00 1 900 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(usNumber1, "DE"));
+
+ PhoneNumber usNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ assertEquals("1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(usNumber2, "BS"));
+
+ assertEquals("0~0 1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(usNumber2, "PL"));
+
+ PhoneNumber gbNumber =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(7912345678L).build();
+ assertEquals("011 44 7912 345 678",
+ phoneUtil.formatOutOfCountryCallingNumber(gbNumber, "US"));
+
+ PhoneNumber deNumber =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(1234L).build();
+ assertEquals("00 49 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(deNumber, "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(deNumber, "DE"));
+
+ PhoneNumber itNumber =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(236618300L)
+ .setItalianLeadingZero(true).build();
+ assertEquals("011 39 02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(itNumber, "US"));
+ assertEquals("02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(itNumber, "IT"));
+ assertEquals("+39 02 3661 8300",
+ phoneUtil.formatOutOfCountryCallingNumber(itNumber, "SG"));
+
+ PhoneNumber sgNumber =
+ PhoneNumber.newBuilder().setCountryCode(65).setNationalNumber(94777892L).build();
+ assertEquals("9477 7892",
+ phoneUtil.formatOutOfCountryCallingNumber(sgNumber, "SG"));
+
+ PhoneNumber arNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(91187654321L).build();
+ assertEquals("011 54 9 11 8765 4321",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumber1, "US"));
+
+ PhoneNumber arNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(91187654321L)
+ .setExtension("1234").build();
+ assertEquals("011 54 9 11 8765 4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumber2, "US"));
+ assertEquals("0011 54 9 11 8765 4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumber2, "AU"));
+ assertEquals("011 15 8765-4321 ext. 1234",
+ phoneUtil.formatOutOfCountryCallingNumber(arNumber2, "AR"));
+ }
+
+ public void testFormatOutOfCountryWithPreferredIntlPrefix() {
+ PhoneNumber.Builder itNumber = PhoneNumber.newBuilder();
+ itNumber.setCountryCode(39).setNationalNumber(236618300L).setItalianLeadingZero(true);
+ // 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(itNumber.build(), "AU"));
+ }
+
+ public void testFormatByPattern() {
+ PhoneNumber usNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ NumberFormat newNumFormat1 =
+ NumberFormat.newBuilder().setPattern("(\\d{3})(\\d{3})(\\d{4})")
+ .setFormat("($1) $2-$3").build();
+ List<NumberFormat> newNumberFormats = new ArrayList<NumberFormat>();
+ newNumberFormats.add(newNumFormat1);
+
+ assertEquals("(650) 253-0000",
+ phoneUtil.formatByPattern(usNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ assertEquals("+1 (650) 253-0000",
+ phoneUtil.formatByPattern(usNumber,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+
+ PhoneNumber itNumber =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(236618300L)
+ .setItalianLeadingZero(true).build();
+ NumberFormat newNumFormat2 =
+ NumberFormat.newBuilder().setPattern("(\\d{2})(\\d{5})(\\d{3})")
+ .setFormat("$1-$2 $3").build();
+ newNumberFormats.set(0, newNumFormat2);
+
+ assertEquals("02-36618 300",
+ phoneUtil.formatByPattern(itNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ assertEquals("+39 02-36618 300",
+ phoneUtil.formatByPattern(itNumber,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+
+ PhoneNumber gbNumber =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(2012345678L).build();
+
+ NumberFormat newNumFormat3 =
+ NumberFormat.newBuilder().setNationalPrefixFormattingRule("$NP$FG")
+ .setPattern("(\\d{2})(\\d{4})(\\d{4})").setFormat("$1 $2 $3").build();
+ newNumberFormats.set(0, newNumFormat3);
+ assertEquals("020 1234 5678",
+ phoneUtil.formatByPattern(gbNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+
+ NumberFormat newNumFormat4 =
+ NumberFormat.newBuilder(newNumFormat3).setNationalPrefixFormattingRule("($NP$FG)").build();
+ newNumberFormats.set(0, newNumFormat4);
+ assertEquals("(020) 1234 5678",
+ phoneUtil.formatByPattern(gbNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+ NumberFormat newNumFormat5 =
+ NumberFormat.newBuilder(newNumFormat4).setNationalPrefixFormattingRule("").build();
+ newNumberFormats.set(0, newNumFormat5);
+ assertEquals("20 1234 5678",
+ phoneUtil.formatByPattern(gbNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL,
+ newNumberFormats));
+
+ NumberFormat newNumFormat6 =
+ NumberFormat.newBuilder(newNumFormat5).setNationalPrefixFormattingRule("").build();
+ newNumberFormats.set(0, newNumFormat6);
+ assertEquals("+44 20 1234 5678",
+ phoneUtil.formatByPattern(gbNumber,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL,
+ newNumberFormats));
+ }
+
+ public void testFormatE164Number() {
+ PhoneNumber.Builder usNumber = PhoneNumber.newBuilder();
+ usNumber.setCountryCode(1).setNationalNumber(6502530000L);
+ assertEquals("+16502530000", phoneUtil.format(usNumber.build(),
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ PhoneNumber.Builder deNumber = PhoneNumber.newBuilder();
+ deNumber.setCountryCode(49).setNationalNumber(301234L);
+ assertEquals("+49301234", phoneUtil.format(deNumber.build(),
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ }
+
+ public void testFormatNumberWithExtension() {
+ PhoneNumber.Builder nzNumber = PhoneNumber.newBuilder();
+ nzNumber.setCountryCode(64).setNationalNumber(33316005L).setExtension("1234");
+ // Uses default extension prefix:
+ assertEquals("03-331 6005 ext. 1234",
+ phoneUtil.format(nzNumber.build(),
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ // Extension prefix overridden in the territory information for the US:
+ PhoneNumber.Builder usNumber = PhoneNumber.newBuilder();
+ usNumber.setCountryCode(1).setNationalNumber(6502530000L).setExtension("4567");
+ assertEquals("650 253 0000 extn. 4567",
+ phoneUtil.format(usNumber.build(),
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ }
+
+ public void testIsPremiumRate() {
+ PhoneNumber premiumRateNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(9004433030L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber1));
+
+ PhoneNumber premiumRateNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(892123L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber2));
+
+ PhoneNumber premiumRateNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(9187654321L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber3));
+
+ PhoneNumber premiumRateNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(9001654321L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber4));
+
+ PhoneNumber premiumRateNumber5 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(90091234567L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PREMIUM_RATE,
+ phoneUtil.getNumberType(premiumRateNumber5));
+ }
+
+ public void testIsTollFree() {
+ PhoneNumber tollFreeNumber1
+ = PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(8881234567L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber1));
+
+ PhoneNumber tollFreeNumber2
+ = PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(803123L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber2));
+
+ PhoneNumber tollFreeNumber3
+ = PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(8012345678L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber3));
+
+ PhoneNumber tollFreeNumber4
+ = PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(8001234567L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.TOLL_FREE,
+ phoneUtil.getNumberType(tollFreeNumber4));
+ }
+
+ public void testIsMobile() {
+ PhoneNumber mobileNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2423570000L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE,
+ phoneUtil.getNumberType(mobileNumber1));
+
+ PhoneNumber mobileNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(312345678L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE,
+ phoneUtil.getNumberType(mobileNumber2));
+
+ PhoneNumber mobileNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(7912345678L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE,
+ phoneUtil.getNumberType(mobileNumber3));
+
+ PhoneNumber mobileNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(15123456789L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE,
+ phoneUtil.getNumberType(mobileNumber4));
+
+ PhoneNumber mobileNumber5 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(91187654321L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.MOBILE,
+ phoneUtil.getNumberType(mobileNumber5));
+ }
+
+ public void testIsFixedLine() {
+ // A Bahama fixed-line number
+ PhoneNumber fixedLineNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2423651234L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE,
+ phoneUtil.getNumberType(fixedLineNumber1));
+
+ // An Italian fixed-line number
+ PhoneNumber fixedLineNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(236618300L)
+ .setItalianLeadingZero(true).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE,
+ phoneUtil.getNumberType(fixedLineNumber2));
+
+ PhoneNumber fixedLineNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(2012345678L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE,
+ phoneUtil.getNumberType(fixedLineNumber3));
+
+ PhoneNumber fixedLineNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(301234L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE,
+ phoneUtil.getNumberType(fixedLineNumber4));
+ }
+
+ public void testIsFixedLineAndMobile() {
+ PhoneNumber fixedLineAndMobileNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502531111L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE_OR_MOBILE,
+ phoneUtil.getNumberType(fixedLineAndMobileNumber1));
+
+ PhoneNumber fixedLineAndMobileNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(1987654321L).build();
+ assertEquals(PhoneNumberUtil.PhoneNumberType.FIXED_LINE_OR_MOBILE,
+ phoneUtil.getNumberType(fixedLineAndMobileNumber2));
+ }
+
+ public void testIsSharedCost() {
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(8431231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.SHARED_COST,
+ phoneUtil.getNumberType(gbNumber.build()));
+ }
+
+ public void testIsVoip() {
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(5631231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.VOIP, phoneUtil.getNumberType(gbNumber.build()));
+ }
+
+ public void testIsPersonalNumber() {
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(7031231234L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.PERSONAL_NUMBER,
+ phoneUtil.getNumberType(gbNumber.build()));
+ }
+
+ public void testIsUnknown() {
+ PhoneNumber.Builder unknownNumber = PhoneNumber.newBuilder();
+ unknownNumber.setCountryCode(1).setNationalNumber(65025311111L);
+ assertEquals(PhoneNumberUtil.PhoneNumberType.UNKNOWN,
+ phoneUtil.getNumberType(unknownNumber.build()));
+ }
+
+ public void testIsValidNumber() {
+ PhoneNumber.Builder usNumber = PhoneNumber.newBuilder();
+ usNumber.setCountryCode(1).setNationalNumber(6502530000L);
+ assertTrue(phoneUtil.isValidNumber(usNumber.build()));
+
+ PhoneNumber.Builder itNumber = PhoneNumber.newBuilder();
+ itNumber.setCountryCode(39).setNationalNumber(236618300L).setItalianLeadingZero(true);
+ assertTrue(phoneUtil.isValidNumber(itNumber.build()));
+
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(7912345678L);
+ assertTrue(phoneUtil.isValidNumber(gbNumber.build()));
+
+ PhoneNumber.Builder nzNumber = PhoneNumber.newBuilder();
+ nzNumber.setCountryCode(64).setNationalNumber(21387835L);
+ assertTrue(phoneUtil.isValidNumber(nzNumber.build()));
+ }
+
+ public void testIsValidForRegion() {
+ // This number is valid for the Bahamas, but is not a valid US number.
+ PhoneNumber bsNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2423232345L).build();
+ assertTrue(phoneUtil.isValidNumber(bsNumber1));
+ assertTrue(phoneUtil.isValidNumberForRegion(bsNumber1, "BS"));
+ assertFalse(phoneUtil.isValidNumberForRegion(bsNumber1, "US"));
+ PhoneNumber bsNumber2 =
+ PhoneNumber.newBuilder(bsNumber1).setNationalNumber(2421232345L).build();
+ // This number is no longer valid.
+ assertFalse(phoneUtil.isValidNumber(bsNumber2));
+ }
+
+ public void testIsNotValidNumber() {
+ PhoneNumber.Builder usNumber = PhoneNumber.newBuilder();
+ usNumber.setCountryCode(1).setNationalNumber(2530000L);
+ assertFalse(phoneUtil.isValidNumber(usNumber.build()));
+
+ PhoneNumber.Builder itNumber = PhoneNumber.newBuilder();
+ itNumber.setCountryCode(39).setNationalNumber(23661830000L).setItalianLeadingZero(true);
+ assertFalse(phoneUtil.isValidNumber(itNumber.build()));
+
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(791234567L);
+ assertFalse(phoneUtil.isValidNumber(gbNumber.build()));
+
+ PhoneNumber.Builder deNumber = PhoneNumber.newBuilder();
+ deNumber.setCountryCode(49).setNationalNumber(1234L);
+ assertFalse(phoneUtil.isValidNumber(deNumber.build()));
+
+ PhoneNumber.Builder nzNumber = PhoneNumber.newBuilder();
+ nzNumber.setCountryCode(64).setNationalNumber(3316005L);
+ assertFalse(phoneUtil.isValidNumber(nzNumber.build()));
+ }
+
+ public void testGetRegionCodeForCountryCode() {
+ assertEquals("US", phoneUtil.getRegionCodeForCountryCode(1));
+ assertEquals("GB", phoneUtil.getRegionCodeForCountryCode(44));
+ assertEquals("DE", phoneUtil.getRegionCodeForCountryCode(49));
+ }
+
+ public void testGetRegionCodeForNumber() {
+ PhoneNumber.Builder bsNumber = PhoneNumber.newBuilder();
+ bsNumber.setCountryCode(1).setNationalNumber(2423027000L);
+ assertEquals("BS", phoneUtil.getRegionCodeForNumber(bsNumber.build()));
+
+ PhoneNumber.Builder usNumber = PhoneNumber.newBuilder();
+ usNumber.setCountryCode(1).setNationalNumber(6502530000L);
+ assertEquals("US", phoneUtil.getRegionCodeForNumber(usNumber.build()));
+
+ PhoneNumber.Builder gbNumber = PhoneNumber.newBuilder();
+ gbNumber.setCountryCode(44).setNationalNumber(7912345678L);
+ assertEquals("GB", phoneUtil.getRegionCodeForNumber(gbNumber.build()));
+ }
+
+ public void testGetCountryCodeForRegion() {
+ assertEquals(1, phoneUtil.getCountryCodeForRegion("US"));
+ assertEquals(64, phoneUtil.getCountryCodeForRegion("NZ"));
+ }
+
+ public void testGetNANPACountries() {
+ Set nanpaCountries = phoneUtil.getNANPACountries();
+ assertEquals(2, nanpaCountries.size());
+ assertTrue(nanpaCountries.contains("US"));
+ assertTrue(nanpaCountries.contains("BS"));
+ }
+
+ public void testIsPossibleNumber() {
+ PhoneNumber number1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ assertTrue(phoneUtil.isPossibleNumber(number1));
+
+ PhoneNumber number2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2530000L).build();
+ assertTrue(phoneUtil.isPossibleNumber(number2));
+
+ PhoneNumber number3 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(2070313000L).build();
+ assertTrue(phoneUtil.isPossibleNumber(number3));
+ assertTrue(phoneUtil.isPossibleNumber("+1 650 253 0000", "US"));
+ assertTrue(phoneUtil.isPossibleNumber("+1 650 GOO OGLE", "US"));
+ assertTrue(phoneUtil.isPossibleNumber("(650) 253-0000", "US"));
+ assertTrue(phoneUtil.isPossibleNumber("253-0000", "US"));
+ assertTrue(phoneUtil.isPossibleNumber("+1 650 253 0000", "GB"));
+ assertTrue(phoneUtil.isPossibleNumber("+44 20 7031 3000", "GB"));
+ assertTrue(phoneUtil.isPossibleNumber("(020) 7031 3000", "GB"));
+ assertTrue(phoneUtil.isPossibleNumber("7031 3000", "GB"));
+ assertTrue(phoneUtil.isPossibleNumber("3331 6005", "NZ"));
+ }
+
+ public void testIsPossibleNumberWithReason() {
+ // FYI, national numbers for country code +1 that are within 7 to 10 digits are possible.
+ PhoneNumber number1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE,
+ phoneUtil.isPossibleNumberWithReason(number1));
+
+ PhoneNumber number2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2530000L).build();
+ assertEquals(PhoneNumberUtil.ValidationResult.IS_POSSIBLE,
+ phoneUtil.isPossibleNumberWithReason(number2));
+
+ PhoneNumber number3 =
+ PhoneNumber.newBuilder().setCountryCode(0).setNationalNumber(2530000L).build();
+ assertEquals(PhoneNumberUtil.ValidationResult.INVALID_COUNTRY_CODE,
+ phoneUtil.isPossibleNumberWithReason(number3));
+
+ PhoneNumber number4 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(253000L).build();
+ assertEquals(PhoneNumberUtil.ValidationResult.TOO_SHORT,
+ phoneUtil.isPossibleNumberWithReason(number4));
+
+ PhoneNumber number5 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(65025300000L).build();
+ assertEquals(PhoneNumberUtil.ValidationResult.TOO_LONG,
+ phoneUtil.isPossibleNumberWithReason(number5));
+ }
+
+ public void testIsNotPossibleNumber() {
+ PhoneNumber number1 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(65025300000L).build();
+ assertFalse(phoneUtil.isPossibleNumber(number1));
+
+ PhoneNumber number2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(253000L).build();
+ assertFalse(phoneUtil.isPossibleNumber(number2));
+
+ PhoneNumber number3 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(300L).build();
+ assertFalse(phoneUtil.isPossibleNumber(number3));
+
+ assertFalse(phoneUtil.isPossibleNumber("+1 650 253 00000", "US"));
+ assertFalse(phoneUtil.isPossibleNumber("(650) 253-00000", "US"));
+ assertFalse(phoneUtil.isPossibleNumber("I want a Pizza", "US"));
+ assertFalse(phoneUtil.isPossibleNumber("253-000", "US"));
+ assertFalse(phoneUtil.isPossibleNumber("1 3000", "GB"));
+ assertFalse(phoneUtil.isPossibleNumber("+44 300", "GB"));
+ }
+
+ 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"));
+ // 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"));
+ }
+
+ public void testMaybeStripNationalPrefix() {
+ String nationalPrefix = "34";
+ StringBuffer numberToStrip = new StringBuffer("34356778");
+ String strippedNumber = "356778";
+ String nationalRuleRegExp = "\\d{4,7}";
+ Pattern nationalRule = Pattern.compile(nationalRuleRegExp);
+ phoneUtil.maybeStripNationalPrefix(numberToStrip, nationalPrefix, "", nationalRule);
+ 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.
+ phoneUtil.maybeStripNationalPrefix(numberToStrip, nationalPrefix, "", nationalRule);
+ assertEquals("Should have had no change - no national prefix present.",
+ strippedNumber, numberToStrip.toString());
+ // Some countries have no national prefix. Repeat test with none specified.
+ nationalPrefix = "";
+ phoneUtil.maybeStripNationalPrefix(numberToStrip, nationalPrefix, "", nationalRule);
+ 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.
+ nationalPrefix = "3";
+ numberToStrip = new StringBuffer("3123");
+ strippedNumber = "3123";
+ phoneUtil.maybeStripNationalPrefix(numberToStrip, nationalPrefix, "", nationalRule);
+ assertEquals("Should have had no change - after stripping, it wouldn't have matched " +
+ "the national rule.",
+ strippedNumber, numberToStrip.toString());
+ }
+
+ public void testMaybeStripInternationalPrefix() {
+ String internationalPrefix = "00[39]";
+ StringBuffer numberToStrip = new StringBuffer("0034567700-3898003");
+ // Note the dash is removed as part of the normalization.
+ StringBuffer strippedNumber = new StringBuffer("45677003898003");
+ assertEquals(true, 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 false.
+ assertEquals(false, phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+
+ numberToStrip = new StringBuffer("00945677003898003");
+ assertEquals(true, 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 StringBuffer("00 9 45677003898003");
+ assertEquals(true, 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 false.
+ assertEquals(false, phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+
+ // Test the + symbol is also recognised and stripped.
+ numberToStrip = new StringBuffer("+45677003898003");
+ strippedNumber = new StringBuffer("45677003898003");
+ assertEquals(true, 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 code begins with 0.
+ numberToStrip = new StringBuffer("0090112-3123");
+ strippedNumber = new StringBuffer("00901123123");
+ assertEquals(false, 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 StringBuffer("009 0-112-3123");
+ assertEquals(false, phoneUtil.maybeStripInternationalPrefixAndNormalize(numberToStrip,
+ internationalPrefix));
+ }
+
+ public void testMaybeExtractCountryCode() {
+ PhoneMetadata metadata = phoneUtil.getPhoneMetadata("US");
+ // Note that for the US, the IDD is 011.
+ try {
+ String phoneNumber = "011112-3456789";
+ String strippedNumber = "123456789";
+ int countryCode = 1;
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Did not extract country code " + countryCode + " correctly.",
+ countryCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill));
+ // Should strip and normalize national significant number.
+ assertEquals("Did not strip off the country code correctly.",
+ strippedNumber,
+ numberToFill.toString());
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ try {
+ String phoneNumber = "+6423456789";
+ int countryCode = 64;
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Did not extract country code " + countryCode + " correctly.",
+ countryCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill));
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ try {
+ String phoneNumber = "2345-6789";
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Should not have extracted a country code - no international prefix present.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill));
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ try {
+ String phoneNumber = "0119991123456789";
+ StringBuffer numberToFill = new StringBuffer();
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata,
+ numberToFill);
+ fail("Should have thrown an exception, no valid country code present.");
+ } catch (NumberParseException e) {
+ // Expected.
+ assertEquals("Wrong error type stored in exception.",
+ NumberParseException.ErrorType.INVALID_COUNTRY_CODE,
+ e.getErrorType());
+ }
+ try {
+ String phoneNumber = "(1 610) 619 4466";
+ int countryCode = 1;
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Should have extracted the country code of the region passed in",
+ countryCode,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill));
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ try {
+ String phoneNumber = "(1 610) 619 446";
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Should not have extracted a country code - invalid number after extraction " +
+ "of uncertain country code.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill));
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ try {
+ String phoneNumber = "(1 610) 619 43 446";
+ StringBuffer numberToFill = new StringBuffer();
+ assertEquals("Should not have extracted a country code - invalid number both before and " +
+ "after extraction of uncertain country code.",
+ 0,
+ phoneUtil.maybeExtractCountryCode(phoneNumber, metadata,
+ numberToFill));
+ } catch (NumberParseException e) {
+ fail("Should not have thrown an exception: " + e.toString());
+ }
+ }
+
+ public void testParseNationalNumber() throws Exception {
+ PhoneNumber nzNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(33316005L).build();
+
+ // National prefix attached.
+ assertEquals(nzNumber, phoneUtil.parse("033316005", "NZ"));
+ assertEquals(nzNumber, phoneUtil.parse("33316005", "NZ"));
+ // National prefix attached and some formatting present.
+ assertEquals(nzNumber, phoneUtil.parse("03-331 6005", "NZ"));
+ assertEquals(nzNumber, phoneUtil.parse("03 331 6005", "NZ"));
+ // Test case with alpha characters.
+ PhoneNumber tollfreeNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(800332005L).build();
+ assertEquals(tollfreeNumber, phoneUtil.parse("0800 DDA 005", "NZ"));
+ PhoneNumber premiumNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(9003326005L).build();
+ assertEquals(premiumNumber, phoneUtil.parse("0900 DDA 6005", "NZ"));
+ // Not enough alpha characters for them to be considered intentional, so they are stripped.
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 6005a", "NZ"));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 600a5", "NZ"));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 332 600A5", "NZ"));
+ assertEquals(premiumNumber, phoneUtil.parse("0900 a332 600A5", "NZ"));
+
+ // Testing international prefixes.
+ // Should strip country code.
+ assertEquals(nzNumber, phoneUtil.parse("0064 3 331 6005", "NZ"));
+ // Try again, but this time we have an international number with Region Code US. It should
+ // recognise the country code and parse accordingly.
+ assertEquals(nzNumber, phoneUtil.parse("01164 3 331 6005", "US"));
+ assertEquals(nzNumber, phoneUtil.parse("+64 3 331 6005", "US"));
+
+ // Test for http://b/issue?id=2247493
+ PhoneNumber nzNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(64123456L).build();
+ assertEquals(nzNumber2, phoneUtil.parse("64(0)64123456", "NZ"));
+
+ PhoneNumber usNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6503336000L).build();
+ assertEquals(usNumber, phoneUtil.parse("+1 (650) 333-6000", "NZ"));
+ assertEquals(usNumber, phoneUtil.parse("1-650-333-6000", "US"));
+ // Calling the US number from Singapore by using different service providers
+ // 1st test: calling using SingTel IDD service (IDD is 001)
+ assertEquals(usNumber, phoneUtil.parse("0011-650-333-6000", "SG"));
+ // 2nd test: calling using StarHub IDD service (IDD is 008)
+ assertEquals(usNumber, phoneUtil.parse("0081-650-333-6000", "SG"));
+ // 3rd test: calling using SingTel V019 service (IDD is 019)
+ assertEquals(usNumber, phoneUtil.parse("0191-650-333-6000", "SG"));
+ // Calling the US number from Poland
+ assertEquals(usNumber, phoneUtil.parse("0~01-650-333-6000", "PL"));
+ // Check it doesn't use the '1' as a country code when parsing if the phone number was already
+ // possible.
+ PhoneNumber usNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(1234567890L).build();
+ assertEquals(usNumber2, phoneUtil.parse("123-456-7890", "US"));
+
+ PhoneNumber itNumber =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(236618300L)
+ .setItalianLeadingZero(true).build();
+ assertEquals(itNumber, phoneUtil.parse("+39 02-36618 300", "NZ"));
+ assertEquals(itNumber, phoneUtil.parse("02-36618 300", "IT"));
+
+ PhoneNumber itNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(312345678L).build();
+ assertEquals(itNumber2, phoneUtil.parse("312 345 678", "IT"));
+
+ // Check that using a "/" is fine in a phone number.
+ PhoneNumber deNumber =
+ PhoneNumber.newBuilder().setCountryCode(49).setNationalNumber(12345678L).build();
+ assertEquals(deNumber, phoneUtil.parse("123/45678", "DE"));
+
+ // Test parsing mobile numbers of Argentina.
+ PhoneNumber arNumber =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(93435551212L).build();
+ assertEquals(arNumber, phoneUtil.parse("+54 9 343 555 1212", "AR"));
+ assertEquals(arNumber, phoneUtil.parse("0343 15 555 1212", "AR"));
+
+ PhoneNumber arNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(93715654320L).build();
+ assertEquals(arNumber2, phoneUtil.parse("+54 9 3715 65 4320", "AR"));
+ assertEquals(arNumber2, phoneUtil.parse("03715 15 65 4320", "AR"));
+
+ // Test parsing fixed-line numbers of Argentina.
+ PhoneNumber arNumber3 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(1137970000L).build();
+ assertEquals(arNumber3, phoneUtil.parse("+54 11 3797 0000", "AR"));
+ assertEquals(arNumber3, phoneUtil.parse("011 3797 0000", "AR"));
+
+ PhoneNumber arNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(3715654321L).build();
+ assertEquals(arNumber4, phoneUtil.parse("+54 3715 65 4321", "AR"));
+ assertEquals(arNumber4, phoneUtil.parse("03715 65 4321", "AR"));
+
+ PhoneNumber arNumber5 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(2312340000L).build();
+ assertEquals(arNumber5, phoneUtil.parse("+54 23 1234 0000", "AR"));
+ assertEquals(arNumber5, phoneUtil.parse("023 1234 0000", "AR"));
+
+ // Test that having an 'x' in the phone number at the start is ok and that it just gets removed.
+ PhoneNumber arNumber6 =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(123456789L).build();
+ assertEquals(arNumber6, phoneUtil.parse("0123456789", "AR"));
+ assertEquals(arNumber6, phoneUtil.parse("(0) 123456789", "AR"));
+ assertEquals(arNumber6, phoneUtil.parse("0 123456789", "AR"));
+ assertEquals(arNumber6, phoneUtil.parse("(0xx) 123456789", "AR"));
+ PhoneNumber arFromUs =
+ PhoneNumber.newBuilder().setCountryCode(54).setNationalNumber(81429712L).build();
+ // 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", "US"));
+
+ // Test parsing fixed-line numbers of Mexico.
+ PhoneNumber mxNumber =
+ PhoneNumber.newBuilder().setCountryCode(52).setNationalNumber(4499780001L).build();
+ assertEquals(mxNumber, phoneUtil.parse("+52 (449)978-0001", "MX"));
+ assertEquals(mxNumber, phoneUtil.parse("01 (449)978-0001", "MX"));
+ assertEquals(mxNumber, phoneUtil.parse("(449)978-0001", "MX"));
+
+ // Test parsing mobile numbers of Mexico.
+ PhoneNumber mxNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(52).setNationalNumber(13312345678L).build();
+ assertEquals(mxNumber2, phoneUtil.parse("+52 1 33 1234-5678", "MX"));
+ assertEquals(mxNumber2, phoneUtil.parse("044 (33) 1234-5678", "MX"));
+ assertEquals(mxNumber2, phoneUtil.parse("045 33 1234-5678", "MX"));
+
+ // Test that if a number has two extensions specified, we ignore the second.
+ PhoneNumber usWithTwoExtensionsNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(2121231234L)
+ .setExtension("508").build();
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/x1234",
+ "US"));
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508/ x1234",
+ "US"));
+ assertEquals(usWithTwoExtensionsNumber, phoneUtil.parse("(212)123-1234 x508\\x1234",
+ "US"));
+
+ // Test parsing numbers in the form (645) 123-1234-910# works, where the last 3 digits before
+ // the # are an extension.
+ PhoneNumber usWithExtension =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6451231234L)
+ .setExtension("910").build();
+ assertEquals(usWithExtension, phoneUtil.parse("+1 (645) 123 1234-910#", "US"));
+ }
+
+ public void testFailedParseOnInvalidNumbers() {
+ try {
+ String sentencePhoneNumber = "This is not a phone number";
+ phoneUtil.parse(sentencePhoneNumber, "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, "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 tooShortPhoneNumber = "+49 0";
+ phoneUtil.parse(tooShortPhoneNumber, "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, "NZ");
+ fail("This is not a recognised country 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 someNumber = "123 456 7890";
+ phoneUtil.parse(someNumber, "ZZ");
+ fail("'Unknown' country 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 country 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, "GB");
+ fail("No number provided, only country 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, "GB");
+ fail("No number provided, only country 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, "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, "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());
+ }
+ }
+
+ public void testParseExtensions() throws Exception {
+ PhoneNumber nzNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(33316005L)
+ .setExtension("3456").build();
+ assertEquals(nzNumber, phoneUtil.parse("03 331 6005 ext 3456", "NZ"));
+ assertEquals(nzNumber, phoneUtil.parse("03-3316005x3456", "NZ"));
+ assertEquals(nzNumber, phoneUtil.parse("03-3316005 int.3456", "NZ"));
+ assertEquals(nzNumber, phoneUtil.parse("03 3316005 #3456", "NZ"));
+ // Test the following do not extract extensions:
+ PhoneNumber nonExtnNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(180074935247L).build();
+ assertEquals(nonExtnNumber, phoneUtil.parse("1800 six-flags", "US"));
+ assertEquals(nonExtnNumber, phoneUtil.parse("1800 SIX FLAGS", "US"));
+ assertEquals(nonExtnNumber, phoneUtil.parse("0~01 1800 7493 5247", "PL"));
+ assertEquals(nonExtnNumber, phoneUtil.parse("(1800) 7493.5247", "US"));
+ // Check that the last instance of an extension token is matched.
+ PhoneNumber extnNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(180074935247L)
+ .setExtension("1234").build();
+ assertEquals(extnNumber, phoneUtil.parse("0~01 1800 7493 5247 ~1234", "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 =
+ PhoneNumber.newBuilder().setCountryCode(44).setNationalNumber(2034567890L)
+ .setExtension("456").build();
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", "NZ"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890x456", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x456", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X456", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 x 456 ", "GB"));
+ assertEquals(ukNumber, phoneUtil.parse("+44 2034567890 X 456", "GB"));
+
+ PhoneNumber usWithExtension =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(8009013355L)
+ .setExtension("7246433").build();
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 x 7246433", "US"));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , ext 7246433", "US"));
+ assertEquals(usWithExtension,
+ phoneUtil.parse("(800) 901-3355 ,extension 7246433", "US"));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 , 7246433", "US"));
+ assertEquals(usWithExtension, phoneUtil.parse("(800) 901-3355 ext: 7246433", "US"));
+ }
+
+ public void testCountryWithNoNumberDesc() {
+ // Andorra is a country where we don't have PhoneNumberDesc info in the meta data.
+ PhoneNumber adNumber =
+ PhoneNumber.newBuilder().setCountryCode(376).setNationalNumber(12345L).build();
+ assertEquals("+376 12345", phoneUtil.format(adNumber,
+ PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
+ assertEquals("+37612345", phoneUtil.format(adNumber,
+ PhoneNumberUtil.PhoneNumberFormat.E164));
+ assertEquals("12345", phoneUtil.format(adNumber,
+ PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
+ assertEquals(PhoneNumberUtil.PhoneNumberType.UNKNOWN,
+ phoneUtil.getNumberType(adNumber));
+ assertTrue(phoneUtil.isValidNumber(adNumber));
+
+ // Test dialing a US number from within Andorra.
+ PhoneNumber usNumber =
+ PhoneNumber.newBuilder().setCountryCode(1).setNationalNumber(6502530000L).build();
+ assertEquals("00 1 650 253 0000",
+ phoneUtil.formatOutOfCountryCallingNumber(usNumber, "AD"));
+ }
+
+ public void testUnknownCountryCallingCodeForValidation() {
+ PhoneNumber.Builder invalidNumber = PhoneNumber.newBuilder();
+ invalidNumber.setCountryCode(0).setNationalNumber(1234L);
+ assertFalse(phoneUtil.isValidNumber(invalidNumber.build()));
+ }
+
+ public void testIsNumberMatchMatches() throws Exception {
+ // Test simple matches where formatting is different, or leading zeroes, or country code has
+ // been specified.
+ PhoneNumber num1 = phoneUtil.parse("+64 3 331 6005", "NZ");
+ PhoneNumber num2 = phoneUtil.parse("+64 03 331 6005", "NZ");
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(num1, num2));
+ 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.
+ PhoneNumber nzNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(33316005L)
+ .setExtension("3456").build();
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber, "+643 331 6005 ext 3456"));
+ PhoneNumber nzNumber2 = PhoneNumber.newBuilder(nzNumber).clearExtension().build();
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber2, "+6403 331 6005"));
+ // Check empty extensions are ignored.
+ PhoneNumber nzNumber3 = PhoneNumber.newBuilder(nzNumber).setExtension("").build();
+ assertEquals(PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber3, "+6403 331 6005"));
+ // Check variant with two proto buffers.
+ PhoneNumber nzNumber4 =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(33316005L).build();
+ assertEquals("Number " + nzNumber.toString() + " did not match " + nzNumber4.toString(),
+ PhoneNumberUtil.MatchType.EXACT_MATCH,
+ phoneUtil.isNumberMatch(nzNumber3, nzNumber4));
+ }
+
+ public void testIsNumberMatchNonMatches() throws Exception {
+ // Non-matches.
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch("03 331 6005", "03 331 6006"));
+ // Different country code, partial number match.
+ assertEquals(PhoneNumberUtil.MatchType.NO_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "+16433316005"));
+ // Different country 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"));
+ }
+
+ 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("3 331-6005", "03 331 6005"));
+ PhoneNumber nzNumber =
+ PhoneNumber.newBuilder().setCountryCode(64).setNationalNumber(33316005L)
+ .setExtension("").build();
+ assertEquals(PhoneNumberUtil.MatchType.NSN_MATCH,
+ phoneUtil.isNumberMatch(nzNumber, "03 331 6005"));
+ PhoneNumber unchangedNzNumber = PhoneNumber.newBuilder().setCountryCode(64)
+ .setNationalNumber(33316005L).setExtension("").build();
+ // Check the phone number proto was not edited during the method call.
+ assertEquals(unchangedNzNumber, nzNumber);
+ }
+
+ public void testIsNumberMatchShortNsnMatches() throws Exception {
+ // Short NSN matches with the country not specified for either one or both numbers.
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("+64 3 331-6005", "331 6005"));
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch("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 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 italianNumber1 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(1234L)
+ .setItalianLeadingZero(true).build();
+ PhoneNumber italianNumber2 =
+ PhoneNumber.newBuilder().setCountryCode(39).setNationalNumber(1234L).build();
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch(italianNumber1, italianNumber2));
+ // One has an extension, the other has an extension of "".
+ PhoneNumber italianNumber3 =
+ PhoneNumber.newBuilder(italianNumber1).setExtension("1234")
+ .clearItalianLeadingZero().build();
+ PhoneNumber italianNumber4 =
+ PhoneNumber.newBuilder(italianNumber2).setExtension("").build();
+ assertEquals(PhoneNumberUtil.MatchType.SHORT_NSN_MATCH,
+ phoneUtil.isNumberMatch(italianNumber3, italianNumber4));
+ }
+}