Commits

jia....@ee073f10-1060-11df-b6a4-87a95322a99c  committed 9a67ec5

Checking in first version of java libphonenumber

  • Participants
  • Branches default

Comments (0)

Files changed (18)

File java/build.xml

+<?xml version="1.0" ?>
+
+<project name="libphonenumber" default="compile"> 
+  <property name="src.dir" value="src"/>
+  <property name="build.dir" value="build"/>
+  <property name="classes.dir" value="${build.dir}/classes"/>
+  <property name="jar.dir" value="${build.dir}/jar"/>
+  <property name="lib.dir" value="lib"/>
+  <property name="report.dir" value="${build.dir}/junitreport"/>
+
+  <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"/>
+  </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="${src.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="${src.dir}">
+        <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="${src.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>
+

File java/lib/google-guava.jar

Binary file added.

File java/lib/junit-4.8.1.jar

Binary file added.

File java/lib/protobuf-java-2.3.0.jar

Binary file added.

File java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java

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

File java/src/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java

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

File java/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java

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

File java/src/com/google/i18n/phonenumbers/NumberParseException.java

+/*
+ * 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;
+  }
+}

File java/src/com/google/i18n/phonenumbers/PhoneNumberMetaData.xml

+<!-- 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>900212