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));
+  }
+}