| @ -0,0 +1,78 @@ | |||
| <?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> | |||
| @ -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(); | |||
| } | |||
| } | |||
| @ -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/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')); | |||
| } | |||
| } | |||
| @ -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(); | |||
| } | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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> | |||
| @ -0,0 +1,462 @@ | |||
| // 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.ExtensionRegistry registry) { | |||
| } | |||
| public static final class PhoneNumber extends | |||
| com.google.protobuf.GeneratedMessage { | |||
| // 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; | |||
| } | |||
| public static final com.google.protobuf.Descriptors.Descriptor | |||
| getDescriptor() { | |||
| return com.google.i18n.phonenumbers.Phonenumber.internal_static_i18n_phonenumbers_PhoneNumber_descriptor; | |||
| } | |||
| protected com.google.protobuf.GeneratedMessage.FieldAccessorTable | |||
| internalGetFieldAccessorTable() { | |||
| return com.google.i18n.phonenumbers.Phonenumber.internal_static_i18n_phonenumbers_PhoneNumber_fieldAccessorTable; | |||
| } | |||
| // 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()); | |||
| } | |||
| getUnknownFields().writeTo(output); | |||
| } | |||
| 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()); | |||
| } | |||
| size += getUnknownFields().getSerializedSize(); | |||
| 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.GeneratedMessage.Builder<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.protobuf.Descriptors.Descriptor | |||
| getDescriptorForType() { | |||
| return com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.getDescriptor(); | |||
| } | |||
| 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.protobuf.Message other) { | |||
| if (other instanceof com.google.i18n.phonenumbers.Phonenumber.PhoneNumber) { | |||
| return mergeFrom((com.google.i18n.phonenumbers.Phonenumber.PhoneNumber)other); | |||
| } else { | |||
| super.mergeFrom(other); | |||
| return this; | |||
| } | |||
| } | |||
| 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()); | |||
| } | |||
| this.mergeUnknownFields(other.getUnknownFields()); | |||
| return this; | |||
| } | |||
| public Builder mergeFrom( | |||
| com.google.protobuf.CodedInputStream input, | |||
| com.google.protobuf.ExtensionRegistryLite extensionRegistry) | |||
| throws java.io.IOException { | |||
| com.google.protobuf.UnknownFieldSet.Builder unknownFields = | |||
| com.google.protobuf.UnknownFieldSet.newBuilder( | |||
| this.getUnknownFields()); | |||
| while (true) { | |||
| int tag = input.readTag(); | |||
| switch (tag) { | |||
| case 0: | |||
| this.setUnknownFields(unknownFields.build()); | |||
| return this; | |||
| default: { | |||
| if (!parseUnknownField(input, unknownFields, | |||
| extensionRegistry, tag)) { | |||
| this.setUnknownFields(unknownFields.build()); | |||
| 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) | |||
| } | |||
| private static com.google.protobuf.Descriptors.Descriptor | |||
| internal_static_i18n_phonenumbers_PhoneNumber_descriptor; | |||
| private static | |||
| com.google.protobuf.GeneratedMessage.FieldAccessorTable | |||
| internal_static_i18n_phonenumbers_PhoneNumber_fieldAccessorTable; | |||
| public static com.google.protobuf.Descriptors.FileDescriptor | |||
| getDescriptor() { | |||
| return descriptor; | |||
| } | |||
| private static com.google.protobuf.Descriptors.FileDescriptor | |||
| descriptor; | |||
| static { | |||
| java.lang.String[] descriptorData = { | |||
| "\n\021phonenumber.proto\022\021i18n.phonenumbers\"m" + | |||
| "\n\013PhoneNumber\022\024\n\014country_code\030\001 \002(\005\022\027\n\017n" + | |||
| "ational_number\030\002 \002(\004\022\021\n\textension\030\003 \001(\t\022" + | |||
| "\034\n\024italian_leading_zero\030\004 \001(\010B\036\n\034com.goo" + | |||
| "gle.i18n.phonenumbers" | |||
| }; | |||
| com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = | |||
| new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { | |||
| public com.google.protobuf.ExtensionRegistry assignDescriptors( | |||
| com.google.protobuf.Descriptors.FileDescriptor root) { | |||
| descriptor = root; | |||
| internal_static_i18n_phonenumbers_PhoneNumber_descriptor = | |||
| getDescriptor().getMessageTypes().get(0); | |||
| internal_static_i18n_phonenumbers_PhoneNumber_fieldAccessorTable = new | |||
| com.google.protobuf.GeneratedMessage.FieldAccessorTable( | |||
| internal_static_i18n_phonenumbers_PhoneNumber_descriptor, | |||
| new java.lang.String[] { "CountryCode", "NationalNumber", "Extension", "ItalianLeadingZero", }, | |||
| com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.class, | |||
| com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.Builder.class); | |||
| return null; | |||
| } | |||
| }; | |||
| com.google.protobuf.Descriptors.FileDescriptor | |||
| .internalBuildGeneratedFileFrom(descriptorData, | |||
| new com.google.protobuf.Descriptors.FileDescriptor[] { | |||
| }, assigner); | |||
| } | |||
| public static void internalForceInit() {} | |||
| // @@protoc_insertion_point(outer_class_scope) | |||
| } | |||
| @ -0,0 +1,209 @@ | |||
| /* | |||
| * 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"; | |||
| 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; | |||
| } | |||
| @ -0,0 +1,71 @@ | |||
| /* | |||
| * 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"; | |||
| 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 | |||