diff --git a/java/demoapp/.gradle/8.9/checksums/checksums.lock b/java/demoapp/.gradle/8.9/checksums/checksums.lock new file mode 100644 index 0000000000..7df0626edf Binary files /dev/null and b/java/demoapp/.gradle/8.9/checksums/checksums.lock differ diff --git a/java/demoapp/.gradle/8.9/checksums/md5-checksums.bin b/java/demoapp/.gradle/8.9/checksums/md5-checksums.bin new file mode 100644 index 0000000000..089ec7f5c9 Binary files /dev/null and b/java/demoapp/.gradle/8.9/checksums/md5-checksums.bin differ diff --git a/java/demoapp/.gradle/8.9/checksums/sha1-checksums.bin b/java/demoapp/.gradle/8.9/checksums/sha1-checksums.bin new file mode 100644 index 0000000000..84278300c5 Binary files /dev/null and b/java/demoapp/.gradle/8.9/checksums/sha1-checksums.bin differ diff --git a/java/demoapp/.gradle/8.9/dependencies-accessors/gc.properties b/java/demoapp/.gradle/8.9/dependencies-accessors/gc.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/java/demoapp/.gradle/8.9/executionHistory/executionHistory.lock b/java/demoapp/.gradle/8.9/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..a87d2fec63 Binary files /dev/null and b/java/demoapp/.gradle/8.9/executionHistory/executionHistory.lock differ diff --git a/java/demoapp/.gradle/8.9/fileChanges/last-build.bin b/java/demoapp/.gradle/8.9/fileChanges/last-build.bin new file mode 100644 index 0000000000..f76dd238ad Binary files /dev/null and b/java/demoapp/.gradle/8.9/fileChanges/last-build.bin differ diff --git a/java/demoapp/.gradle/8.9/fileHashes/fileHashes.lock b/java/demoapp/.gradle/8.9/fileHashes/fileHashes.lock new file mode 100644 index 0000000000..7e84b7612e Binary files /dev/null and b/java/demoapp/.gradle/8.9/fileHashes/fileHashes.lock differ diff --git a/java/demoapp/.gradle/8.9/gc.properties b/java/demoapp/.gradle/8.9/gc.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/java/demoapp/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/java/demoapp/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000000..db102ef199 Binary files /dev/null and b/java/demoapp/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/java/demoapp/.gradle/buildOutputCleanup/cache.properties b/java/demoapp/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000000..cea8d84fb6 --- /dev/null +++ b/java/demoapp/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Thu Apr 02 09:44:30 CLST 2026 +gradle.version=8.9 diff --git a/java/demoapp/.gradle/vcs-1/gc.properties b/java/demoapp/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/migrator/migrator-servlet/src/main/java/com/google/phonenumbers/ServletMain.java b/migrator/migrator-servlet/src/main/java/com/google/phonenumbers/ServletMain.java index 52e75ddd19..ccf44b4c17 100644 --- a/migrator/migrator-servlet/src/main/java/com/google/phonenumbers/ServletMain.java +++ b/migrator/migrator-servlet/src/main/java/com/google/phonenumbers/ServletMain.java @@ -38,6 +38,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.StringTokenizer; +import java.util.UUID; @WebServlet(name = "Migrate", value = "/migrate") public class ServletMain extends HttpServlet { @@ -67,6 +68,8 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S String file = ""; String fileName = ""; String customRecipe = ""; + String sessionToken = (String) req.getSession().getAttribute("csrf_token"); + boolean isTokenValid = false; try { upload.setSizeMax(MAX_UPLOAD_SIZE); @@ -79,9 +82,11 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S || item.getFieldName().equals("fileCountryCode"))) { countryCode = Streams.asString(in); - } else if (item.isFormField() && item.getFieldName().equals("number")) { - number = Streams.asString(in); - + } else if (item.isFormField() && item.getFieldName().equals("csrf_token")) { + String providedToken = Streams.asString(in); + if (sessionToken != null && sessionToken.equals(providedToken)) { + isTokenValid = true; + } } else if (item.getFieldName().equals("file")) { fileName = item.getName(); try { @@ -102,6 +107,11 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S e.printStackTrace(); } + if (!isTokenValid(req)) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid or missing CSRF token."); + return; + } + if (!number.isEmpty() && !countryCode.isEmpty()) { /* number and country code are being set again to allow users to see their inputs after the http request has @@ -131,6 +141,12 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se matcher.removeFrom(req.getParameter("fileName")); String fileContent = req.getParameter("fileContent"); + if (fileContent == null) { + req.setAttribute("csrf_token", getOrGenerateCsrfToken(req)); + req.getRequestDispatcher("index.jsp").forward(req, resp); + return; + } + resp.setContentType("text/plain"); resp.setHeader("Content-Disposition", "attachment; filename=" + fileName); try { @@ -258,4 +274,36 @@ public static ImmutableList getMigrationResultOutputList(ImmutableList <%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% final String E164_NUMBERS_LINK = "https://support.twilio.com/hc/en-us/articles/223183008-Formatting-International-Phone-Numbers"; final String COUNTRY_CODE_LINK = "https://countrycode.org/"; @@ -140,62 +141,55 @@
- <% - if (request.getAttribute("numberError") == null && request.getAttribute("number") != null) { - if (request.getAttribute("validMigration") != null) { - out.print("

Valid +" + request.getAttribute("numberCountryCode") + " Phone Number Produced!

"); - out.print("

The stale number '" + request.getAttribute("number") + "' was successfully migrated into the" + - " phone number: +" + request.getAttribute("validMigration") + "

"); - } else if (request.getAttribute("invalidMigration") != null) { - out.print("

Invalid +" + request.getAttribute("numberCountryCode") + " Migration

"); - out.print("

The stale number '" + request.getAttribute("number") + "' was migrated into the phone number:" + - " +" + request.getAttribute("invalidMigration") + ". However this was not seen as valid using our internal" + - " metadata for country code +" + request.getAttribute("numberCountryCode") + ".

"); - } else if (request.getAttribute("alreadyValidNumber") != null) { - out.print("

Already Valid +" + request.getAttribute("numberCountryCode") + " Phone Number!

"); - out.print("

The entered phone number was already seen as being in a valid, dialable format based on our" + - " metadata for country code +" + request.getAttribute("numberCountryCode") + ". Here is the number in" + - " its clean E.164 format: +" + request.getAttribute("alreadyValidNumber") + "

"); - } else { - out.print("

Non-migratable +" + request.getAttribute("numberCountryCode") + " Phone Number

"); - out.print("

The phone number '" + request.getAttribute("number") + "' was not seen as a valid number and" + - " no migration recipe could be found for country code +" + request.getAttribute("numberCountryCode") + - " to migrate it. This may be because you have entered a country code which does not correctly correspond" + - " to the given phone number or the specified number has never been valid.

"); - } - out.print("

Think there's an issue? File one here following the given guidelines.

"); - } else if (request.getAttribute("fileError") == null && request.getAttribute("fileName") != null) { - out.print("

'" + request.getAttribute("fileName") + "' Migration Report for Country Code: +" + request.getAttribute("fileCountryCode") + "

"); - out.print("

Below is a chart showing the ratio of numbers from the entered file that were able to be migrated" + - " using '+" + request.getAttribute("fileCountryCode") + "' migration recipes. To understand more," + - " select a given segment from the chart below.

"); - out.print("
"); - - out.print("
"); - out.print(""); - out.print(""); - out.print(""); - out.print(""); - out.print("
"); - } - %> + + + +

Valid + Phone Number Produced!

+

The stale number '' was successfully migrated into the phone number: +

+
+ +

Invalid + Migration

+

The stale number '' was migrated into the phone number: +. However this was not seen as valid using our internal metadata for country code +.

+
+ +

Already Valid + Phone Number!

+

The entered phone number was already seen as being in a valid, dialable format based on our metadata for country code +. Here is the number in its clean E.164 format: +

+
+ +

Non-migratable + Phone Number

+

The phone number '' was not seen as a valid number and no migration recipe could be found for country code + to migrate it. This may be because you have entered a country code which does not correctly correspond to the given phone number or the specified number has never been valid.

+
+
+

Think there's an issue? File one here following the given guidelines.

+
+ +

'' Migration Report for Country Code: +

+

Below is a chart showing the ratio of numbers from the entered file that were able to be migrated using '+' migration recipes. To understand more, select a given segment from the chart below.

+
+
+ + + + +
+

Single Number Migration

-
<%=request.getAttribute("numberError") == null ? "" : request.getAttribute("numberError")%>
+
+

Enter a phone number in E.164 format. Inputted numbers can include spaces, curved brackets and hyphens

"/> + value=""/>

Enter the BCP-47 country code in which the specified E.164 phone number belongs to

"/> + value=""/>

@@ -210,8 +204,9 @@

File Migration

-
<%=request.getAttribute("fileError") == null ? "" : request.getAttribute("fileError")%>
+
+

Upload a file containing one E.164 phone number per line. Numbers can include spaces, curved brackets and hyphens

diff --git a/migrator/migrator-servlet/src/test/java/com/google/phonenumbers/ServletMainTest.java b/migrator/migrator-servlet/src/test/java/com/google/phonenumbers/ServletMainTest.java new file mode 100644 index 0000000000..dc2ea7ca9b --- /dev/null +++ b/migrator/migrator-servlet/src/test/java/com/google/phonenumbers/ServletMainTest.java @@ -0,0 +1,95 @@ +package com.google.phonenumbers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class ServletMainTest { + + private ServletMain servlet; + private Map sessionAttributes; + private Map requestAttributes; + + @Before + public void setUp() { + servlet = new ServletMain(); + sessionAttributes = new HashMap<>(); + requestAttributes = new HashMap<>(); + } + + @Test + public void testGetOrGenerateCsrfToken_NewSession() { + HttpServletRequest mockRequest = createMockRequest(); + + String token = servlet.getOrGenerateCsrfToken(mockRequest); + + assertNotNull(token); + assertEquals(token, sessionAttributes.get("csrf_token")); + } + + @Test + public void testGetOrGenerateCsrfToken_ExistingSession() { + String existingToken = UUID.randomUUID().toString(); + sessionAttributes.put("csrf_token", existingToken); + HttpServletRequest mockRequest = createMockRequest(); + + String token = servlet.getOrGenerateCsrfToken(mockRequest); + + assertEquals(existingToken, token); + } + + @Test + public void testIsTokenValid_NoSessionToken() { + HttpServletRequest mockRequest = createMockRequest(); + // No token in session + + assertFalse(servlet.isTokenValid(mockRequest)); + } + + // Note: Testing isTokenValid with a real multipart request would require + // complex mocking of ServletFileUpload and FileItemIterator. + // For the purpose of this PR, we've extracted the logic to ensure + // the core session-handling part is testable. + + private HttpServletRequest createMockRequest() { + return (HttpServletRequest) java.lang.reflect.Proxy.newProxyInstance( + HttpServletRequest.class.getClassLoader(), + new Class[] { HttpServletRequest.class }, + (proxy, method, args) -> { + if (method.getName().equals("getSession")) { + return createMockSession(); + } else if (method.getName().equals("setAttribute")) { + requestAttributes.put((String) args[0], args[1]); + return null; + } else if (method.getName().equals("getAttribute")) { + return requestAttributes.get(args[0]); + } + return null; + }); + } + + private HttpSession createMockSession() { + return (HttpSession) java.lang.reflect.Proxy.newProxyInstance( + HttpSession.class.getClassLoader(), + new Class[] { HttpSession.class }, + (proxy, method, args) -> { + if (method.getName().equals("getAttribute")) { + return sessionAttributes.get(args[0]); + } else if (method.getName().equals("setAttribute")) { + sessionAttributes.put((String) args[0], args[1]); + return null; + } + return null; + }); + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/BuildMetadataFromXml.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/BuildMetadataFromXml.java new file mode 100644 index 0000000000..c6ce40b700 --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/BuildMetadataFromXml.java @@ -0,0 +1,783 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Library to build phone number metadata from the XML format. + * + * @author Shaopeng Jia + */ +public class BuildMetadataFromXml { + private static final Logger logger = Logger.getLogger(BuildMetadataFromXml.class.getName()); + + // String constants used to fetch the XML nodes and attributes. + private static final String CARRIER_CODE_FORMATTING_RULE = "carrierCodeFormattingRule"; + private static final String CARRIER_SPECIFIC = "carrierSpecific"; + private static final String COUNTRY_CODE = "countryCode"; + private static final String EMERGENCY = "emergency"; + private static final String EXAMPLE_NUMBER = "exampleNumber"; + private static final String FIXED_LINE = "fixedLine"; + private static final String FORMAT = "format"; + private static final String GENERAL_DESC = "generalDesc"; + private static final String INTERNATIONAL_PREFIX = "internationalPrefix"; + private static final String INTL_FORMAT = "intlFormat"; + private static final String LEADING_DIGITS = "leadingDigits"; + private static final String MAIN_COUNTRY_FOR_CODE = "mainCountryForCode"; + private static final String MOBILE = "mobile"; + private static final String MOBILE_NUMBER_PORTABLE_REGION = "mobileNumberPortableRegion"; + private static final String NATIONAL_NUMBER_PATTERN = "nationalNumberPattern"; + private static final String NATIONAL_PREFIX = "nationalPrefix"; + private static final String NATIONAL_PREFIX_FORMATTING_RULE = "nationalPrefixFormattingRule"; + private static final String NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING = + "nationalPrefixOptionalWhenFormatting"; + private static final String NATIONAL_PREFIX_FOR_PARSING = "nationalPrefixForParsing"; + private static final String NATIONAL_PREFIX_TRANSFORM_RULE = "nationalPrefixTransformRule"; + private static final String NO_INTERNATIONAL_DIALLING = "noInternationalDialling"; + private static final String NUMBER_FORMAT = "numberFormat"; + private static final String PAGER = "pager"; + private static final String PATTERN = "pattern"; + private static final String PERSONAL_NUMBER = "personalNumber"; + private static final String POSSIBLE_LENGTHS = "possibleLengths"; + private static final String NATIONAL = "national"; + private static final String LOCAL_ONLY = "localOnly"; + private static final String PREFERRED_EXTN_PREFIX = "preferredExtnPrefix"; + private static final String PREFERRED_INTERNATIONAL_PREFIX = "preferredInternationalPrefix"; + private static final String PREMIUM_RATE = "premiumRate"; + private static final String SHARED_COST = "sharedCost"; + private static final String SHORT_CODE = "shortCode"; + private static final String SMS_SERVICES = "smsServices"; + private static final String STANDARD_RATE = "standardRate"; + private static final String TOLL_FREE = "tollFree"; + private static final String UAN = "uan"; + private static final String VOICEMAIL = "voicemail"; + private static final String VOIP = "voip"; + + private static final Set PHONE_NUMBER_DESCS_WITHOUT_MATCHING_TYPES = + new HashSet(Arrays.asList(new String[]{NO_INTERNATIONAL_DIALLING})); + + // Build the PhoneMetadataCollection from the input XML file. + public static PhoneMetadataCollection buildPhoneMetadataCollection(String inputXmlFile, + boolean liteBuild, boolean specialBuild) throws Exception { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + File xmlFile = new File(inputXmlFile); + Document document = builder.parse(xmlFile); + // TODO: Look for other uses of these constants and possibly pull them out into a separate + // constants file. + boolean isShortNumberMetadata = inputXmlFile.contains("ShortNumberMetadata"); + boolean isAlternateFormatsMetadata = inputXmlFile.contains("PhoneNumberAlternateFormats"); + return buildPhoneMetadataCollection(document, liteBuild, specialBuild, + isShortNumberMetadata, isAlternateFormatsMetadata); + } + + // @VisibleForTesting + static PhoneMetadataCollection buildPhoneMetadataCollection(Document document, + boolean liteBuild, boolean specialBuild, boolean isShortNumberMetadata, + boolean isAlternateFormatsMetadata) throws Exception { + document.getDocumentElement().normalize(); + Element rootElement = document.getDocumentElement(); + NodeList territory = rootElement.getElementsByTagName("territory"); + PhoneMetadataCollection.Builder metadataCollection = PhoneMetadataCollection.newBuilder(); + int numOfTerritories = territory.getLength(); + // TODO: Infer filter from a single flag. + MetadataFilter metadataFilter = getMetadataFilter(liteBuild, specialBuild); + for (int i = 0; i < numOfTerritories; i++) { + Element territoryElement = (Element) territory.item(i); + String regionCode = ""; + // For the main metadata file this should always be set, but for other supplementary data + // files the country calling code may be all that is needed. + if (territoryElement.hasAttribute("id")) { + regionCode = territoryElement.getAttribute("id"); + } + PhoneMetadata.Builder metadata = loadCountryMetadata(regionCode, territoryElement, + isShortNumberMetadata, isAlternateFormatsMetadata); + metadataFilter.filterMetadata(metadata); + metadataCollection.addMetadata(metadata.build()); + } + return metadataCollection.build(); + } + + // Build a mapping from a country calling code to the region codes which denote the country/region + // represented by that country code. In the case of multiple countries sharing a calling code, + // such as the NANPA countries, the one indicated with "isMainCountryForCode" in the metadata + // should be first. + public static Map> buildCountryCodeToRegionCodeMap( + PhoneMetadataCollection metadataCollection) { + Map> countryCodeToRegionCodeMap = new TreeMap>(); + for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { + String regionCode = metadata.getId(); + int countryCode = metadata.getCountryCode(); + if (countryCodeToRegionCodeMap.containsKey(countryCode)) { + if (metadata.getMainCountryForCode()) { + countryCodeToRegionCodeMap.get(countryCode).add(0, regionCode); + } else { + countryCodeToRegionCodeMap.get(countryCode).add(regionCode); + } + } else { + // For most countries, there will be only one region code for the country calling code. + List listWithRegionCode = new ArrayList(1); + if (!regionCode.equals("")) { // For alternate formats, there are no region codes at all. + listWithRegionCode.add(regionCode); + } + countryCodeToRegionCodeMap.put(countryCode, listWithRegionCode); + } + } + return countryCodeToRegionCodeMap; + } + + // Build a list of region codes from the metadata + public static List buildRegionCodeList( + PhoneMetadataCollection metadataCollection) { + List regionCodeList = new ArrayList(); + for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { + String regionCode = metadata.getId(); + regionCodeList.add(regionCode); + } + return regionCodeList; + } + + private static String validateRE(String regex) { + return validateRE(regex, false); + } + + // @VisibleForTesting + static String validateRE(String regex, boolean removeWhitespace) { + // Removes all the whitespace and newline from the regexp. Not using pattern compile options to + // make it work across programming languages. + String compressedRegex = removeWhitespace ? regex.replaceAll("\\s", "") : regex; + Pattern.compile(compressedRegex); + // We don't ever expect to see | followed by a ) in our metadata - this would be an indication + // of a bug. If one wants to make something optional, we prefer ? to using an empty group. + int errorIndex = compressedRegex.indexOf("|)"); + if (errorIndex >= 0) { + logger.log(Level.SEVERE, "Error with original regex: " + regex + + "\n| should not be followed directly by ) in phone number regular expressions."); + throw new PatternSyntaxException("| followed by )", compressedRegex, errorIndex); + } + // return the regex if it is of correct syntax, i.e. compile did not fail with a + // PatternSyntaxException. + return compressedRegex; + } + + /** + * Returns the national prefix of the provided country element. + */ + // @VisibleForTesting + static String getNationalPrefix(Element element) { + return element.hasAttribute(NATIONAL_PREFIX) ? element.getAttribute(NATIONAL_PREFIX) : ""; + } + + // @VisibleForTesting + static PhoneMetadata.Builder loadTerritoryTagMetadata(String regionCode, Element element, + String nationalPrefix) { + PhoneMetadata.Builder metadata = PhoneMetadata.newBuilder(); + metadata.setId(regionCode); + if (element.hasAttribute(COUNTRY_CODE)) { + metadata.setCountryCode(Integer.parseInt(element.getAttribute(COUNTRY_CODE))); + } + if (element.hasAttribute(LEADING_DIGITS)) { + metadata.setLeadingDigits(validateRE(element.getAttribute(LEADING_DIGITS))); + } + if (element.hasAttribute(INTERNATIONAL_PREFIX)) { + metadata.setInternationalPrefix(validateRE(element.getAttribute(INTERNATIONAL_PREFIX))); + } + if (element.hasAttribute(PREFERRED_INTERNATIONAL_PREFIX)) { + metadata.setPreferredInternationalPrefix( + element.getAttribute(PREFERRED_INTERNATIONAL_PREFIX)); + } + if (element.hasAttribute(NATIONAL_PREFIX_FOR_PARSING)) { + metadata.setNationalPrefixForParsing( + validateRE(element.getAttribute(NATIONAL_PREFIX_FOR_PARSING), true)); + if (element.hasAttribute(NATIONAL_PREFIX_TRANSFORM_RULE)) { + metadata.setNationalPrefixTransformRule( + validateRE(element.getAttribute(NATIONAL_PREFIX_TRANSFORM_RULE))); + } + } + if (!nationalPrefix.isEmpty()) { + metadata.setNationalPrefix(nationalPrefix); + if (!metadata.hasNationalPrefixForParsing()) { + metadata.setNationalPrefixForParsing(nationalPrefix); + } + } + if (element.hasAttribute(PREFERRED_EXTN_PREFIX)) { + metadata.setPreferredExtnPrefix(element.getAttribute(PREFERRED_EXTN_PREFIX)); + } + if (element.hasAttribute(MAIN_COUNTRY_FOR_CODE)) { + metadata.setMainCountryForCode(true); + } + if (element.hasAttribute(MOBILE_NUMBER_PORTABLE_REGION)) { + metadata.setMobileNumberPortableRegion(true); + } + return metadata; + } + + /** + * Extracts the pattern for international format. If there is no intlFormat, default to using the + * national format. If the intlFormat is set to "NA" the intlFormat should be ignored. + * + * @throws RuntimeException if multiple intlFormats have been encountered. + * @return whether an international number format is defined. + */ + // @VisibleForTesting + static boolean loadInternationalFormat(PhoneMetadata.Builder metadata, + Element numberFormatElement, + NumberFormat nationalFormat) { + NumberFormat.Builder intlFormat = NumberFormat.newBuilder(); + NodeList intlFormatPattern = numberFormatElement.getElementsByTagName(INTL_FORMAT); + boolean hasExplicitIntlFormatDefined = false; + + if (intlFormatPattern.getLength() > 1) { + logger.log(Level.SEVERE, + "A maximum of one intlFormat pattern for a numberFormat element should be defined."); + String countryId = metadata.getId().length() > 0 ? metadata.getId() + : Integer.toString(metadata.getCountryCode()); + throw new RuntimeException("Invalid number of intlFormat patterns for country: " + countryId); + } else if (intlFormatPattern.getLength() == 0) { + // Default to use the same as the national pattern if none is defined. + intlFormat.mergeFrom(nationalFormat); + } else { + intlFormat.setPattern(numberFormatElement.getAttribute(PATTERN)); + setLeadingDigitsPatterns(numberFormatElement, intlFormat); + String intlFormatPatternValue = intlFormatPattern.item(0).getFirstChild().getNodeValue(); + if (!intlFormatPatternValue.equals("NA")) { + intlFormat.setFormat(intlFormatPatternValue); + } + hasExplicitIntlFormatDefined = true; + } + + if (intlFormat.hasFormat()) { + metadata.addIntlNumberFormat(intlFormat.build()); + } + return hasExplicitIntlFormatDefined; + } + + /** + * Extracts the pattern for the national format. + * + * @throws RuntimeException if multiple or no formats have been encountered. + */ + // @VisibleForTesting + static void loadNationalFormat(PhoneMetadata.Builder metadata, Element numberFormatElement, + NumberFormat.Builder format) { + setLeadingDigitsPatterns(numberFormatElement, format); + format.setPattern(validateRE(numberFormatElement.getAttribute(PATTERN))); + + NodeList formatPattern = numberFormatElement.getElementsByTagName(FORMAT); + int numFormatPatterns = formatPattern.getLength(); + if (numFormatPatterns != 1) { + logger.log(Level.SEVERE, "One format pattern for a numberFormat element should be defined."); + String countryId = metadata.getId().length() > 0 ? metadata.getId() + : Integer.toString(metadata.getCountryCode()); + throw new RuntimeException("Invalid number of format patterns (" + numFormatPatterns + + ") for country: " + countryId); + } + format.setFormat(formatPattern.item(0).getFirstChild().getNodeValue()); + } + + /** + * Extracts the available formats from the provided DOM element. If it does not contain any + * nationalPrefixFormattingRule, the one passed-in is retained; similarly for + * nationalPrefixOptionalWhenFormatting. The nationalPrefix, nationalPrefixFormattingRule and + * nationalPrefixOptionalWhenFormatting values are provided from the parent (territory) element. + */ + // @VisibleForTesting + static void loadAvailableFormats(PhoneMetadata.Builder metadata, + Element element, String nationalPrefix, + String nationalPrefixFormattingRule, + boolean nationalPrefixOptionalWhenFormatting) { + String carrierCodeFormattingRule = ""; + if (element.hasAttribute(CARRIER_CODE_FORMATTING_RULE)) { + carrierCodeFormattingRule = validateRE( + getDomesticCarrierCodeFormattingRuleFromElement(element, nationalPrefix)); + } + NodeList numberFormatElements = element.getElementsByTagName(NUMBER_FORMAT); + boolean hasExplicitIntlFormatDefined = false; + + 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(NATIONAL_PREFIX_FORMATTING_RULE)) { + format.setNationalPrefixFormattingRule( + getNationalPrefixFormattingRuleFromElement(numberFormatElement, nationalPrefix)); + } else if (!nationalPrefixFormattingRule.equals("")) { + format.setNationalPrefixFormattingRule(nationalPrefixFormattingRule); + } + if (numberFormatElement.hasAttribute(NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING)) { + format.setNationalPrefixOptionalWhenFormatting( + Boolean.valueOf(numberFormatElement.getAttribute( + NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING))); + } else if (format.getNationalPrefixOptionalWhenFormatting() + != nationalPrefixOptionalWhenFormatting) { + // Inherit from the parent field if it is not already the same as the default. + format.setNationalPrefixOptionalWhenFormatting(nationalPrefixOptionalWhenFormatting); + } + if (numberFormatElement.hasAttribute(CARRIER_CODE_FORMATTING_RULE)) { + format.setDomesticCarrierCodeFormattingRule(validateRE( + getDomesticCarrierCodeFormattingRuleFromElement(numberFormatElement, + nationalPrefix))); + } else if (!carrierCodeFormattingRule.equals("")) { + format.setDomesticCarrierCodeFormattingRule(carrierCodeFormattingRule); + } + loadNationalFormat(metadata, numberFormatElement, format); + metadata.addNumberFormat(format); + + if (loadInternationalFormat(metadata, numberFormatElement, format.build())) { + hasExplicitIntlFormatDefined = true; + } + } + // Only a small number of regions need to specify the intlFormats in the xml. For the majority + // of countries the intlNumberFormat metadata is an exact copy of the national NumberFormat + // metadata. To minimize the size of the metadata file, we only keep intlNumberFormats that + // actually differ in some way to the national formats. + if (!hasExplicitIntlFormatDefined) { + metadata.clearIntlNumberFormat(); + } + } + } + + // @VisibleForTesting + static void setLeadingDigitsPatterns(Element numberFormatElement, NumberFormat.Builder format) { + NodeList leadingDigitsPatternNodes = numberFormatElement.getElementsByTagName(LEADING_DIGITS); + int numOfLeadingDigitsPatterns = leadingDigitsPatternNodes.getLength(); + if (numOfLeadingDigitsPatterns > 0) { + for (int i = 0; i < numOfLeadingDigitsPatterns; i++) { + format.addLeadingDigitsPattern( + validateRE((leadingDigitsPatternNodes.item(i)).getFirstChild().getNodeValue(), true)); + } + } + } + + // @VisibleForTesting + static String getNationalPrefixFormattingRuleFromElement(Element element, + String nationalPrefix) { + String nationalPrefixFormattingRule = element.getAttribute(NATIONAL_PREFIX_FORMATTING_RULE); + // Replace $NP with national prefix and $FG with the first group ($1). + nationalPrefixFormattingRule = + nationalPrefixFormattingRule.replaceFirst("\\$NP", nationalPrefix) + .replaceFirst("\\$FG", "\\$1"); + return nationalPrefixFormattingRule; + } + + // @VisibleForTesting + static String getDomesticCarrierCodeFormattingRuleFromElement(Element element, + String nationalPrefix) { + String carrierCodeFormattingRule = element.getAttribute(CARRIER_CODE_FORMATTING_RULE); + // Replace $FG with the first group ($1) and $NP with the national prefix. + carrierCodeFormattingRule = carrierCodeFormattingRule.replaceFirst("\\$FG", "\\$1") + .replaceFirst("\\$NP", nationalPrefix); + return carrierCodeFormattingRule; + } + + /** + * Checks if the possible lengths provided as a sorted set are equal to the possible lengths + * stored already in the description pattern. Note that possibleLengths may be empty but must not + * be null, and the PhoneNumberDesc passed in should also not be null. + */ + private static boolean arePossibleLengthsEqual(TreeSet possibleLengths, + PhoneNumberDesc desc) { + if (possibleLengths.size() != desc.getPossibleLengthCount()) { + return false; + } + // Note that both should be sorted already, and we know they are the same length. + int i = 0; + for (Integer length : possibleLengths) { + if (length != desc.getPossibleLength(i)) { + return false; + } + i++; + } + return true; + } + + /** + * 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 parent + * description will be used to fill in the whole element if necessary, or any components that are + * missing. For all other types, the parent 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 no national number data and [-1] for the possible lengths. Note that the parent + * description must therefore already be processed before this method is called on any child + * elements. + * + * @param parentDesc a generic phone number description that will be used to fill in missing + * parts of the description, or null if this is the root node. This must be processed before + * this is run on any child elements. + * @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 + */ + // @VisibleForTesting + static PhoneNumberDesc.Builder processPhoneNumberDescElement(PhoneNumberDesc.Builder parentDesc, + Element countryElement, + String numberType) { + NodeList phoneNumberDescList = countryElement.getElementsByTagName(numberType); + PhoneNumberDesc.Builder numberDesc = PhoneNumberDesc.newBuilder(); + if (phoneNumberDescList.getLength() == 0) { + // -1 will never match a possible phone number length, so is safe to use to ensure this never + // matches. We don't leave it empty, since for compression reasons, we use the empty list to + // mean that the generalDesc possible lengths apply. + numberDesc.addPossibleLength(-1); + return numberDesc; + } + if (phoneNumberDescList.getLength() > 0) { + if (phoneNumberDescList.getLength() > 1) { + throw new RuntimeException( + String.format("Multiple elements with type %s found.", numberType)); + } + Element element = (Element) phoneNumberDescList.item(0); + if (parentDesc != null) { + // New way of handling possible number lengths. We don't do this for the general + // description, since these tags won't be present; instead we will calculate its values + // based on the values for all the other number type descriptions (see + // setPossibleLengthsGeneralDesc). + TreeSet lengths = new TreeSet(); + TreeSet localOnlyLengths = new TreeSet(); + populatePossibleLengthSets(element, lengths, localOnlyLengths); + setPossibleLengths(lengths, localOnlyLengths, parentDesc.build(), numberDesc); + } + + NodeList validPattern = element.getElementsByTagName(NATIONAL_NUMBER_PATTERN); + if (validPattern.getLength() > 0) { + numberDesc.setNationalNumberPattern( + validateRE(validPattern.item(0).getFirstChild().getNodeValue(), true)); + } + + NodeList exampleNumber = element.getElementsByTagName(EXAMPLE_NUMBER); + if (exampleNumber.getLength() > 0) { + numberDesc.setExampleNumber(exampleNumber.item(0).getFirstChild().getNodeValue()); + } + } + return numberDesc; + } + + // @VisibleForTesting + static void setRelevantDescPatterns(PhoneMetadata.Builder metadata, Element element, + boolean isShortNumberMetadata) { + PhoneNumberDesc.Builder generalDesc = processPhoneNumberDescElement(null, element, + GENERAL_DESC); + // Calculate the possible lengths for the general description. This will be based on the + // possible lengths of the child elements. + setPossibleLengthsGeneralDesc(generalDesc, metadata.getId(), element, isShortNumberMetadata); + metadata.setGeneralDesc(generalDesc); + + if (!isShortNumberMetadata) { + // Set fields used by regular length phone numbers. + metadata.setFixedLine(processPhoneNumberDescElement(generalDesc, element, FIXED_LINE)); + metadata.setMobile(processPhoneNumberDescElement(generalDesc, element, MOBILE)); + metadata.setSharedCost(processPhoneNumberDescElement(generalDesc, element, SHARED_COST)); + metadata.setVoip(processPhoneNumberDescElement(generalDesc, element, VOIP)); + metadata.setPersonalNumber(processPhoneNumberDescElement(generalDesc, element, + PERSONAL_NUMBER)); + metadata.setPager(processPhoneNumberDescElement(generalDesc, element, PAGER)); + metadata.setUan(processPhoneNumberDescElement(generalDesc, element, UAN)); + metadata.setVoicemail(processPhoneNumberDescElement(generalDesc, element, VOICEMAIL)); + metadata.setNoInternationalDialling(processPhoneNumberDescElement(generalDesc, element, + NO_INTERNATIONAL_DIALLING)); + boolean mobileAndFixedAreSame = metadata.getMobile().getNationalNumberPattern() + .equals(metadata.getFixedLine().getNationalNumberPattern()); + if (metadata.getSameMobileAndFixedLinePattern() != mobileAndFixedAreSame) { + // Set this if it is not the same as the default. + metadata.setSameMobileAndFixedLinePattern(mobileAndFixedAreSame); + } + metadata.setTollFree(processPhoneNumberDescElement(generalDesc, element, TOLL_FREE)); + metadata.setPremiumRate(processPhoneNumberDescElement(generalDesc, element, PREMIUM_RATE)); + } else { + // Set fields used by short numbers. + metadata.setStandardRate(processPhoneNumberDescElement(generalDesc, element, STANDARD_RATE)); + metadata.setShortCode(processPhoneNumberDescElement(generalDesc, element, SHORT_CODE)); + metadata.setCarrierSpecific(processPhoneNumberDescElement(generalDesc, element, + CARRIER_SPECIFIC)); + metadata.setEmergency(processPhoneNumberDescElement(generalDesc, element, EMERGENCY)); + metadata.setTollFree(processPhoneNumberDescElement(generalDesc, element, TOLL_FREE)); + metadata.setPremiumRate(processPhoneNumberDescElement(generalDesc, element, PREMIUM_RATE)); + metadata.setSmsServices(processPhoneNumberDescElement(generalDesc, element, SMS_SERVICES)); + } + } + + /** + * Parses a possible length string into a set of the integers that are covered. + * + * @param possibleLengthString a string specifying the possible lengths of phone numbers. Follows + * this syntax: ranges or elements are separated by commas, and ranges are specified in + * [min-max] notation, inclusive. For example, [3-5],7,9,[11-14] should be parsed to + * 3,4,5,7,9,11,12,13,14. + */ + private static Set parsePossibleLengthStringToSet(String possibleLengthString) { + if (possibleLengthString.length() == 0) { + throw new RuntimeException("Empty possibleLength string found."); + } + String[] lengths = possibleLengthString.split(","); + Set lengthSet = new TreeSet(); + for (int i = 0; i < lengths.length; i++) { + String lengthSubstring = lengths[i]; + if (lengthSubstring.length() == 0) { + throw new RuntimeException(String.format("Leading, trailing or adjacent commas in possible " + + "length string %s, these should only separate numbers or ranges.", + possibleLengthString)); + } else if (lengthSubstring.charAt(0) == '[') { + if (lengthSubstring.charAt(lengthSubstring.length() - 1) != ']') { + throw new RuntimeException(String.format("Missing end of range character in possible " + + "length string %s.", possibleLengthString)); + } + // Strip the leading and trailing [], and split on the -. + String[] minMax = lengthSubstring.substring(1, lengthSubstring.length() - 1).split("-"); + if (minMax.length != 2) { + throw new RuntimeException(String.format("Ranges must have exactly one - character: " + + "missing for %s.", possibleLengthString)); + } + int min = Integer.parseInt(minMax[0]); + int max = Integer.parseInt(minMax[1]); + // We don't even accept [6-7] since we prefer the shorter 6,7 variant; for a range to be in + // use the hyphen needs to replace at least one digit. + if (max - min < 2) { + throw new RuntimeException(String.format("The first number in a range should be two or " + + "more digits lower than the second. Culprit possibleLength string: %s", + possibleLengthString)); + } + for (int j = min; j <= max; j++) { + if (!lengthSet.add(j)) { + throw new RuntimeException(String.format("Duplicate length element found (%d) in " + + "possibleLength string %s", j, possibleLengthString)); + } + } + } else { + int length = Integer.parseInt(lengthSubstring); + if (!lengthSet.add(length)) { + throw new RuntimeException(String.format("Duplicate length element found (%d) in " + + "possibleLength string %s", length, possibleLengthString)); + } + } + } + return lengthSet; + } + + /** + * Reads the possible lengths present in the metadata and splits them into two sets: one for + * full-length numbers, one for local numbers. + * + * @param data one or more phone number descriptions, represented as XML nodes + * @param lengths a set to which to add possible lengths of full phone numbers + * @param localOnlyLengths a set to which to add possible lengths of phone numbers only diallable + * locally (e.g. within a province) + */ + private static void populatePossibleLengthSets(Element data, TreeSet lengths, + TreeSet localOnlyLengths) { + NodeList possibleLengths = data.getElementsByTagName(POSSIBLE_LENGTHS); + for (int i = 0; i < possibleLengths.getLength(); i++) { + Element element = (Element) possibleLengths.item(i); + String nationalLengths = element.getAttribute(NATIONAL); + // We don't add to the phone metadata yet, since we want to sort length elements found under + // different nodes first, make sure there are no duplicates between them and that the + // localOnly lengths don't overlap with the others. + Set thisElementLengths = parsePossibleLengthStringToSet(nationalLengths); + if (element.hasAttribute(LOCAL_ONLY)) { + String localLengths = element.getAttribute(LOCAL_ONLY); + Set thisElementLocalOnlyLengths = parsePossibleLengthStringToSet(localLengths); + Set intersection = new HashSet(thisElementLengths); + intersection.retainAll(thisElementLocalOnlyLengths); + if (!intersection.isEmpty()) { + throw new RuntimeException(String.format( + "Possible length(s) found specified as a normal and local-only length: %s", + intersection)); + } + // We check again when we set these lengths on the metadata itself in setPossibleLengths + // that the elements in localOnly are not also in lengths. For e.g. the generalDesc, it + // might have a local-only length for one type that is a normal length for another type. We + // don't consider this an error, but we do want to remove the local-only lengths. + localOnlyLengths.addAll(thisElementLocalOnlyLengths); + } + // It is okay if at this time we have duplicates, because the same length might be possible + // for e.g. fixed-line and for mobile numbers, and this method operates potentially on + // multiple phoneNumberDesc XML elements. + lengths.addAll(thisElementLengths); + } + } + + /** + * Sets possible lengths in the general description, derived from certain child elements. + */ + // @VisibleForTesting + static void setPossibleLengthsGeneralDesc(PhoneNumberDesc.Builder generalDesc, String metadataId, + Element data, boolean isShortNumberMetadata) { + TreeSet lengths = new TreeSet(); + TreeSet localOnlyLengths = new TreeSet(); + // The general description node should *always* be present if metadata for other types is + // present, aside from in some unit tests. + // (However, for e.g. formatting metadata in PhoneNumberAlternateFormats, no PhoneNumberDesc + // elements are present). + NodeList generalDescNodes = data.getElementsByTagName(GENERAL_DESC); + if (generalDescNodes.getLength() > 0) { + Element generalDescNode = (Element) generalDescNodes.item(0); + populatePossibleLengthSets(generalDescNode, lengths, localOnlyLengths); + if (!lengths.isEmpty() || !localOnlyLengths.isEmpty()) { + // We shouldn't have anything specified at the "general desc" level: we are going to + // calculate this ourselves from child elements. + throw new RuntimeException(String.format("Found possible lengths specified at general " + + "desc: this should be derived from child elements. Affected country: %s", + metadataId)); + } + } + if (!isShortNumberMetadata) { + // Make a copy here since we want to remove some nodes, but we don't want to do that on our + // actual data. + Element allDescData = (Element) data.cloneNode(true /* deep copy */); + for (String tag : PHONE_NUMBER_DESCS_WITHOUT_MATCHING_TYPES) { + NodeList nodesToRemove = allDescData.getElementsByTagName(tag); + if (nodesToRemove.getLength() > 0) { + // We check when we process phone number descriptions that there are only one of each + // type, so this is safe to do. + allDescData.removeChild(nodesToRemove.item(0)); + } + } + populatePossibleLengthSets(allDescData, lengths, localOnlyLengths); + } else { + // For short number metadata, we want to copy the lengths from the "short code" section only. + // This is because it's the more detailed validation pattern, it's not a sub-type of short + // codes. The other lengths will be checked later to see that they are a sub-set of these + // possible lengths. + NodeList shortCodeDescList = data.getElementsByTagName(SHORT_CODE); + if (shortCodeDescList.getLength() > 0) { + Element shortCodeDesc = (Element) shortCodeDescList.item(0); + populatePossibleLengthSets(shortCodeDesc, lengths, localOnlyLengths); + } + if (localOnlyLengths.size() > 0) { + throw new RuntimeException("Found local-only lengths in short-number metadata"); + } + } + setPossibleLengths(lengths, localOnlyLengths, null, generalDesc); + } + + /** + * Sets the possible length fields in the metadata from the sets of data passed in. Checks that + * the length is covered by the "parent" phone number description element if one is present, and + * if the lengths are exactly the same as this, they are not filled in for efficiency reasons. + * + * @param parentDesc the "general description" element or null if desc is the generalDesc itself + * @param desc the PhoneNumberDesc object that we are going to set lengths for + */ + private static void setPossibleLengths(TreeSet lengths, + TreeSet localOnlyLengths, PhoneNumberDesc parentDesc, PhoneNumberDesc.Builder desc) { + // We clear these fields since the metadata tends to inherit from the parent element for other + // fields (via a mergeFrom). + desc.clearPossibleLength(); + desc.clearPossibleLengthLocalOnly(); + // Only add the lengths to this sub-type if they aren't exactly the same as the possible + // lengths in the general desc (for metadata size reasons). + if (parentDesc == null || !arePossibleLengthsEqual(lengths, parentDesc)) { + for (Integer length : lengths) { + if (parentDesc == null || parentDesc.getPossibleLengthList().contains(length)) { + desc.addPossibleLength(length); + } else { + // We shouldn't have possible lengths defined in a child element that are not covered by + // the general description. We check this here even though the general description is + // derived from child elements because it is only derived from a subset, and we need to + // ensure *all* child elements have a valid possible length. + throw new RuntimeException(String.format( + "Out-of-range possible length found (%d), parent lengths %s.", + length, parentDesc.getPossibleLengthList())); + } + } + } + // We check that the local-only length isn't also a normal possible length (only relevant for + // the general-desc, since within elements such as fixed-line we would throw an exception if we + // saw this) before adding it to the collection of possible local-only lengths. + for (Integer length : localOnlyLengths) { + if (!lengths.contains(length)) { + // We check it is covered by either of the possible length sets of the parent + // PhoneNumberDesc, because for example 7 might be a valid localOnly length for mobile, but + // a valid national length for fixedLine, so the generalDesc would have the 7 removed from + // localOnly. + if (parentDesc == null || parentDesc.getPossibleLengthLocalOnlyList().contains(length) + || parentDesc.getPossibleLengthList().contains(length)) { + desc.addPossibleLengthLocalOnly(length); + } else { + throw new RuntimeException(String.format( + "Out-of-range local-only possible length found (%d), parent length %s.", + length, parentDesc.getPossibleLengthLocalOnlyList())); + } + } + } + } + + // @VisibleForTesting + static PhoneMetadata.Builder loadCountryMetadata(String regionCode, + Element element, + boolean isShortNumberMetadata, + boolean isAlternateFormatsMetadata) { + String nationalPrefix = getNationalPrefix(element); + PhoneMetadata.Builder metadata = loadTerritoryTagMetadata(regionCode, element, nationalPrefix); + String nationalPrefixFormattingRule = + getNationalPrefixFormattingRuleFromElement(element, nationalPrefix); + loadAvailableFormats(metadata, element, nationalPrefix, + nationalPrefixFormattingRule, + element.hasAttribute(NATIONAL_PREFIX_OPTIONAL_WHEN_FORMATTING)); + if (!isAlternateFormatsMetadata) { + // The alternate formats metadata does not need most of the patterns to be set. + setRelevantDescPatterns(metadata, element, isShortNumberMetadata); + } + return metadata; + } + + /** + * Processes the custom build flags and gets a {@code MetadataFilter} which may be used to + * filter {@code PhoneMetadata} objects. Incompatible flag combinations throw RuntimeException. + * + * @param liteBuild The liteBuild flag value as given by the command-line + * @param specialBuild The specialBuild flag value as given by the command-line + */ + // @VisibleForTesting + static MetadataFilter getMetadataFilter(boolean liteBuild, boolean specialBuild) { + if (specialBuild) { + if (liteBuild) { + throw new RuntimeException("liteBuild and specialBuild may not both be set"); + } + return MetadataFilter.forSpecialBuild(); + } + if (liteBuild) { + return MetadataFilter.forLiteBuild(); + } + return MetadataFilter.emptyFilter(); + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/Command.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/Command.java new file mode 100644 index 0000000000..b54ef73398 --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/Command.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +/** + * Abstract class defining a common interface for commands provided by build tools (e.g: commands to + * generate code or to download source files). + * + *

Subclass it to create a new command (e.g: code generation step). + * + * @author Philippe Liard + */ +public abstract class Command { + // The arguments provided to this command. The first one is the name of the command. + private String[] args; + + /** + * Entry point of the command called by the CommandDispatcher when requested. This method must be + * implemented by subclasses. + */ + public abstract boolean start(); + + /** + * The name of the command is used by the CommandDispatcher to execute the requested command. The + * Dispatcher will pass along all command-line arguments to this command, so args[0] will be + * always the command name. + */ + public abstract String getCommandName(); + + public String[] getArgs() { + return args; + } + + public void setArgs(String[] args) { + this.args = args; + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CommandDispatcher.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CommandDispatcher.java new file mode 100644 index 0000000000..2806ba3ea5 --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CommandDispatcher.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +/** + * This class is designed to execute a requested command among a set of provided commands. + * The dispatching is performed according to the requested command name, which is provided as the + * first string of the 'args' array. The 'args' array also contains the command arguments available + * from position 1 to end. The verification of the arguments' consistency is under the + * responsibility of the command since the dispatcher can't be aware of its underlying goals. + * + * @see Command + * @author Philippe Liard + */ +public class CommandDispatcher { + // Command line arguments passed to the command which will be executed. Note that the first one is + // the name of the command. + private final String[] args; + // Supported commands by this dispatcher. + private final Command[] commands; + + public CommandDispatcher(String[] args, Command[] commands) { + this.args = args; + this.commands = commands; + } + + /** + * Executes the command named `args[0]` if any. If the requested command (in args[0]) is not + * supported, display a help message. + * + *

Note that the command name comparison is case sensitive. + */ + public boolean start() { + if (args.length != 0) { + String requestedCommand = args[0]; + + for (Command command : commands) { + if (command.getCommandName().equals(requestedCommand)) { + command.setArgs(args); + return command.start(); + } + } + } + displayUsage(); + return false; + } + + /** + * Displays a message containing the list of the supported commands by this dispatcher. + */ + private void displayUsage() { + StringBuilder msg = new StringBuilder("Usage: java -jar /path/to/jar [ "); + int i = 0; + + for (Command command : commands) { + msg.append(command.getCommandName()); + if (i++ != commands.length - 1) { + msg.append(" | "); + } + } + msg.append(" ] args"); + System.err.println(msg.toString()); + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CopyrightNotice.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CopyrightNotice.java new file mode 100644 index 0000000000..d8cd9e2f1a --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/CopyrightNotice.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import java.io.IOException; +import java.io.Writer; +import java.util.Formatter; + +/** + * Class containing the Apache copyright notice used by code generators. + * + * @author Philippe Liard + */ +public class CopyrightNotice { + + private static final String TEXT_OPENING = + "/*\n"; + + private static final String TEXT_OPENING_FOR_JAVASCRIPT = + "/**\n" + + " * @license\n"; + + private static final String TEXT = + " * Copyright (C) %d The Libphonenumber Authors\n" + + " *\n" + + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" + + " * you may not use this file except in compliance with the License.\n" + + " * You may obtain a copy of the License at\n" + + " *\n" + + " * http://www.apache.org/licenses/LICENSE-2.0\n" + + " *\n" + + " * Unless required by applicable law or agreed to in writing, software\n" + + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + " * See the License for the specific language governing permissions and\n" + + " * limitations under the License.\n" + + " */\n\n"; + + static final void writeTo(Writer writer, int year) throws IOException { + writeTo(writer, year, false); + } + + static final void writeTo(Writer writer, int year, boolean isJavascript) throws IOException { + if (isJavascript) { + writer.write(TEXT_OPENING_FOR_JAVASCRIPT); + } else { + writer.write(TEXT_OPENING); + } + Formatter formatter = new Formatter(writer); + formatter.format(TEXT, year); + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/FileUtils.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/FileUtils.java new file mode 100644 index 0000000000..41a11eedd1 --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/FileUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * under the License. + */ + +package com.google.i18n.phonenumbers; + +import java.io.Closeable; +import java.io.IOException; + +/** + * Helper class containing methods designed to ease file manipulation and generation. + * + * @author Philippe Liard + */ +public class FileUtils { + /** + * Silently closes a resource (i.e: don't throw any exception). + */ + private static void close(Closeable closeable) { + if (closeable == null) { + return; + } + try { + closeable.close(); + } catch (IOException e) { + System.err.println(e.getMessage()); + } + } + + /** + * Silently closes multiple resources. This method doesn't throw any exception when an error + * occurs when a resource is being closed. + */ + public static void closeFiles(Closeable ... closeables) { + for (Closeable closeable : closeables) { + close(closeable); + } + } +} diff --git a/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/MetadataFilter.java b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/MetadataFilter.java new file mode 100644 index 0000000000..a783025f33 --- /dev/null +++ b/tools/java/common/target/test-classes/com/google/i18n/phonenumbers/MetadataFilter.java @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2016 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import java.util.Arrays; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * Class to encapsulate the metadata filtering logic and restrict visibility into raw data + * structures. + * + *

+ * WARNING: This is an internal API which is under development and subject to backwards-incompatible + * changes without notice. Any changes are not guaranteed to be reflected in the versioning scheme + * of the public API, nor in release notes. + */ +final class MetadataFilter { + // The following 3 sets comprise all the PhoneMetadata fields as defined at phonemetadata.proto + // which may be excluded from customized serializations of the binary metadata. Fields that are + // core to the library functionality may not be listed here. + // excludableParentFields are PhoneMetadata fields of type PhoneNumberDesc. + // excludableChildFields are PhoneNumberDesc fields of primitive type. + // excludableChildlessFields are PhoneMetadata fields of primitive type. + // Currently we support only one non-primitive type and the depth of the "family tree" is 2, + // meaning a field may have only direct descendants, who may not have descendants of their own. If + // this changes, the blacklist handling in this class should also change. + // @VisibleForTesting + static final TreeSet excludableParentFields = new TreeSet(Arrays.asList( + "fixedLine", + "mobile", + "tollFree", + "premiumRate", + "sharedCost", + "personalNumber", + "voip", + "pager", + "uan", + "emergency", + "voicemail", + "shortCode", + "standardRate", + "carrierSpecific", + "smsServices", + "noInternationalDialling")); + + // Note: If this set changes, the descHasData implementation must change in PhoneNumberUtil. + // The current implementation assumes that all PhoneNumberDesc fields are present here, since it + // "clears" a PhoneNumberDesc field by simply clearing all of the fields under it. See the comment + // above, about all 3 sets, for more about these fields. + // @VisibleForTesting + static final TreeSet excludableChildFields = new TreeSet(Arrays.asList( + "nationalNumberPattern", + "possibleLength", + "possibleLengthLocalOnly", + "exampleNumber")); + + // @VisibleForTesting + static final TreeSet excludableChildlessFields = new TreeSet(Arrays.asList( + "preferredInternationalPrefix", + "nationalPrefix", + "preferredExtnPrefix", + "nationalPrefixTransformRule", + "sameMobileAndFixedLinePattern", + "mainCountryForCode", + "mobileNumberPortableRegion")); + + private final TreeMap> blacklist; + + // Note: If changing the blacklist here or the name of the method, update documentation about + // affected methods at the same time: + // https://github.com/google/libphonenumber/blob/master/FAQ.md#what-is-the-metadatalitejsmetadata_lite-option + static MetadataFilter forLiteBuild() { + // "exampleNumber" is a blacklist. + return new MetadataFilter(parseFieldMapFromString("exampleNumber")); + } + + static MetadataFilter forSpecialBuild() { + // "mobile" is a whitelist. + return new MetadataFilter(computeComplement(parseFieldMapFromString("mobile"))); + } + + static MetadataFilter emptyFilter() { + // Empty blacklist, meaning we filter nothing. + return new MetadataFilter(new TreeMap>()); + } + + // @VisibleForTesting + MetadataFilter(TreeMap> blacklist) { + this.blacklist = blacklist; + } + + @Override + public boolean equals(Object obj) { + return blacklist.equals(((MetadataFilter) obj).blacklist); + } + + @Override + public int hashCode() { + return blacklist.hashCode(); + } + + /** + * Clears certain fields in {@code metadata} as defined by the {@code MetadataFilter} instance. + * Note that this changes the mutable {@code metadata} object, and is not thread-safe. If this + * method does not return successfully, do not assume {@code metadata} has not changed. + * + * @param metadata The {@code PhoneMetadata} object to be filtered + */ + void filterMetadata(PhoneMetadata.Builder metadata) { + // TODO: Consider clearing if the filtered PhoneNumberDesc is empty. + if (metadata.hasFixedLine()) { + metadata.setFixedLine(getFiltered("fixedLine", metadata.getFixedLine())); + } + if (metadata.hasMobile()) { + metadata.setMobile(getFiltered("mobile", metadata.getMobile())); + } + if (metadata.hasTollFree()) { + metadata.setTollFree(getFiltered("tollFree", metadata.getTollFree())); + } + if (metadata.hasPremiumRate()) { + metadata.setPremiumRate(getFiltered("premiumRate", metadata.getPremiumRate())); + } + if (metadata.hasSharedCost()) { + metadata.setSharedCost(getFiltered("sharedCost", metadata.getSharedCost())); + } + if (metadata.hasPersonalNumber()) { + metadata.setPersonalNumber(getFiltered("personalNumber", metadata.getPersonalNumber())); + } + if (metadata.hasVoip()) { + metadata.setVoip(getFiltered("voip", metadata.getVoip())); + } + if (metadata.hasPager()) { + metadata.setPager(getFiltered("pager", metadata.getPager())); + } + if (metadata.hasUan()) { + metadata.setUan(getFiltered("uan", metadata.getUan())); + } + if (metadata.hasEmergency()) { + metadata.setEmergency(getFiltered("emergency", metadata.getEmergency())); + } + if (metadata.hasVoicemail()) { + metadata.setVoicemail(getFiltered("voicemail", metadata.getVoicemail())); + } + if (metadata.hasShortCode()) { + metadata.setShortCode(getFiltered("shortCode", metadata.getShortCode())); + } + if (metadata.hasStandardRate()) { + metadata.setStandardRate(getFiltered("standardRate", metadata.getStandardRate())); + } + if (metadata.hasCarrierSpecific()) { + metadata.setCarrierSpecific(getFiltered("carrierSpecific", metadata.getCarrierSpecific())); + } + if (metadata.hasSmsServices()) { + metadata.setSmsServices(getFiltered("smsServices", metadata.getSmsServices())); + } + if (metadata.hasNoInternationalDialling()) { + metadata.setNoInternationalDialling(getFiltered("noInternationalDialling", + metadata.getNoInternationalDialling())); + } + + if (shouldDrop("preferredInternationalPrefix")) { + metadata.clearPreferredInternationalPrefix(); + } + if (shouldDrop("nationalPrefix")) { + metadata.clearNationalPrefix(); + } + if (shouldDrop("preferredExtnPrefix")) { + metadata.clearPreferredExtnPrefix(); + } + if (shouldDrop("nationalPrefixTransformRule")) { + metadata.clearNationalPrefixTransformRule(); + } + if (shouldDrop("sameMobileAndFixedLinePattern")) { + metadata.clearSameMobileAndFixedLinePattern(); + } + if (shouldDrop("mainCountryForCode")) { + metadata.clearMainCountryForCode(); + } + if (shouldDrop("mobileNumberPortableRegion")) { + metadata.clearMobileNumberPortableRegion(); + } + } + + /** + * The input blacklist or whitelist string is expected to be of the form "a(b,c):d(e):f", where + * b and c are children of a, e is a child of d, and f is either a parent field, a child field, or + * a childless field. Order and whitespace don't matter. We throw RuntimeException for any + * duplicates, malformed strings, or strings where field tokens do not correspond to strings in + * the sets of excludable fields. We also throw RuntimeException for empty strings since such + * strings should be treated as a special case by the flag checking code and not passed here. + */ + // @VisibleForTesting + static TreeMap> parseFieldMapFromString(String string) { + if (string == null) { + throw new RuntimeException("Null string should not be passed to parseFieldMapFromString"); + } + // Remove whitespace. + string = string.replaceAll("\\s", ""); + if (string.isEmpty()) { + throw new RuntimeException("Empty string should not be passed to parseFieldMapFromString"); + } + + TreeMap> fieldMap = new TreeMap>(); + TreeSet wildcardChildren = new TreeSet(); + for (String group : string.split(":", -1)) { + int leftParenIndex = group.indexOf('('); + int rightParenIndex = group.indexOf(')'); + if (leftParenIndex < 0 && rightParenIndex < 0) { + if (excludableParentFields.contains(group)) { + if (fieldMap.containsKey(group)) { + throw new RuntimeException(group + " given more than once in " + string); + } + fieldMap.put(group, new TreeSet(excludableChildFields)); + } else if (excludableChildlessFields.contains(group)) { + if (fieldMap.containsKey(group)) { + throw new RuntimeException(group + " given more than once in " + string); + } + fieldMap.put(group, new TreeSet()); + } else if (excludableChildFields.contains(group)) { + if (wildcardChildren.contains(group)) { + throw new RuntimeException(group + " given more than once in " + string); + } + wildcardChildren.add(group); + } else { + throw new RuntimeException(group + " is not a valid token"); + } + } else if (leftParenIndex > 0 && rightParenIndex == group.length() - 1) { + // We don't check for duplicate parentheses or illegal characters since these will be caught + // as not being part of valid field tokens. + String parent = group.substring(0, leftParenIndex); + if (!excludableParentFields.contains(parent)) { + throw new RuntimeException(parent + " is not a valid parent token"); + } + if (fieldMap.containsKey(parent)) { + throw new RuntimeException(parent + " given more than once in " + string); + } + TreeSet children = new TreeSet(); + for (String child : group.substring(leftParenIndex + 1, rightParenIndex).split(",", -1)) { + if (!excludableChildFields.contains(child)) { + throw new RuntimeException(child + " is not a valid child token"); + } + if (!children.add(child)) { + throw new RuntimeException(child + " given more than once in " + group); + } + } + fieldMap.put(parent, children); + } else { + throw new RuntimeException("Incorrect location of parantheses in " + group); + } + } + for (String wildcardChild : wildcardChildren) { + for (String parent : excludableParentFields) { + TreeSet children = fieldMap.get(parent); + if (children == null) { + children = new TreeSet(); + fieldMap.put(parent, children); + } + if (!children.add(wildcardChild) + && fieldMap.get(parent).size() != excludableChildFields.size()) { + // The map already contains parent -> wildcardChild but not all possible children. + // So wildcardChild was given explicitly as a child of parent, which is a duplication + // since it's also given as a wildcard child. + throw new RuntimeException( + wildcardChild + " is present by itself so remove it from " + parent + "'s group"); + } + } + } + return fieldMap; + } + + // Does not check that legal tokens are used, assuming that fieldMap is constructed using + // parseFieldMapFromString(String) which does check. If fieldMap contains illegal tokens or parent + // fields with no children or other unexpected state, the behavior of this function is undefined. + // @VisibleForTesting + static TreeMap> computeComplement( + TreeMap> fieldMap) { + TreeMap> complement = new TreeMap>(); + for (String parent : excludableParentFields) { + if (!fieldMap.containsKey(parent)) { + complement.put(parent, new TreeSet(excludableChildFields)); + } else { + TreeSet otherChildren = fieldMap.get(parent); + // If the other map has all the children for this parent then we don't want to include the + // parent as a key. + if (otherChildren.size() != excludableChildFields.size()) { + TreeSet children = new TreeSet(); + for (String child : excludableChildFields) { + if (!otherChildren.contains(child)) { + children.add(child); + } + } + complement.put(parent, children); + } + } + } + for (String childlessField : excludableChildlessFields) { + if (!fieldMap.containsKey(childlessField)) { + complement.put(childlessField, new TreeSet()); + } + } + return complement; + } + + // @VisibleForTesting + boolean shouldDrop(String parent, String child) { + if (!excludableParentFields.contains(parent)) { + throw new RuntimeException(parent + " is not an excludable parent field"); + } + if (!excludableChildFields.contains(child)) { + throw new RuntimeException(child + " is not an excludable child field"); + } + return blacklist.containsKey(parent) && blacklist.get(parent).contains(child); + } + + // @VisibleForTesting + boolean shouldDrop(String childlessField) { + if (!excludableChildlessFields.contains(childlessField)) { + throw new RuntimeException(childlessField + " is not an excludable childless field"); + } + return blacklist.containsKey(childlessField); + } + + private PhoneNumberDesc getFiltered(String type, PhoneNumberDesc desc) { + PhoneNumberDesc.Builder builder = PhoneNumberDesc.newBuilder().mergeFrom(desc); + if (shouldDrop(type, "nationalNumberPattern")) { + builder.clearNationalNumberPattern(); + } + if (shouldDrop(type, "possibleLength")) { + builder.clearPossibleLength(); + } + if (shouldDrop(type, "possibleLengthLocalOnly")) { + builder.clearPossibleLengthLocalOnly(); + } + if (shouldDrop(type, "exampleNumber")) { + builder.clearExampleNumber(); + } + return builder.build(); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java new file mode 100644 index 0000000000..3975c2d3a0 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.HashSet; +import java.util.Set; + +public class AlternateFormatsCountryCodeSet { + // A set of all country codes for which data is available. + public static Set getCountryCodeSet() { + // The capacity is set to 61 as there are 46 different entries, + // and this offers a load factor of roughly 0.75. + Set countryCodeSet = new HashSet(61); + + countryCodeSet.add(7); + countryCodeSet.add(27); + countryCodeSet.add(30); + countryCodeSet.add(31); + countryCodeSet.add(34); + countryCodeSet.add(36); + countryCodeSet.add(39); + countryCodeSet.add(43); + countryCodeSet.add(44); + countryCodeSet.add(49); + countryCodeSet.add(52); + countryCodeSet.add(54); + countryCodeSet.add(55); + countryCodeSet.add(58); + countryCodeSet.add(61); + countryCodeSet.add(62); + countryCodeSet.add(64); + countryCodeSet.add(66); + countryCodeSet.add(81); + countryCodeSet.add(84); + countryCodeSet.add(90); + countryCodeSet.add(91); + countryCodeSet.add(94); + countryCodeSet.add(95); + countryCodeSet.add(255); + countryCodeSet.add(350); + countryCodeSet.add(351); + countryCodeSet.add(352); + countryCodeSet.add(358); + countryCodeSet.add(359); + countryCodeSet.add(372); + countryCodeSet.add(373); + countryCodeSet.add(380); + countryCodeSet.add(381); + countryCodeSet.add(385); + countryCodeSet.add(505); + countryCodeSet.add(506); + countryCodeSet.add(595); + countryCodeSet.add(675); + countryCodeSet.add(676); + countryCodeSet.add(679); + countryCodeSet.add(855); + countryCodeSet.add(856); + countryCodeSet.add(971); + countryCodeSet.add(972); + countryCodeSet.add(995); + + return countryCodeSet; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java new file mode 100644 index 0000000000..be11be57ea --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.RegexCache; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A formatter which formats phone numbers as they are entered. + * + *

An AsYouTypeFormatter can be created by invoking + * {@link PhoneNumberUtil#getAsYouTypeFormatter}. After that, digits can be added by invoking + * {@link #inputDigit} on the formatter instance, and the partially formatted phone number will be + * returned each time a digit is added. {@link #clear} can be invoked before formatting a new + * number. + * + *

See the unittests for more details on how the formatter is to be used. + * + * @author Shaopeng Jia + */ +public class AsYouTypeFormatter { + private String currentOutput = ""; + private StringBuilder formattingTemplate = new StringBuilder(); + // The pattern from numberFormat that is currently used to create formattingTemplate. + private String currentFormattingPattern = ""; + private StringBuilder accruedInput = new StringBuilder(); + private StringBuilder accruedInputWithoutFormatting = new StringBuilder(); + // This indicates whether AsYouTypeFormatter is currently doing the formatting. + private boolean ableToFormat = true; + // Set to true when users enter their own formatting. AsYouTypeFormatter will do no formatting at + // all when this is set to true. + private boolean inputHasFormatting = false; + // This is set to true when we know the user is entering a full national significant number, since + // we have either detected a national prefix or an international dialing prefix. When this is + // true, we will no longer use local number formatting patterns. + private boolean isCompleteNumber = false; + private boolean isExpectingCountryCallingCode = false; + private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + private String defaultCountry; + + // Character used when appropriate to separate a prefix, such as a long NDD or a country calling + // code, from the national number. + private static final char SEPARATOR_BEFORE_NATIONAL_NUMBER = ' '; + private static final PhoneMetadata EMPTY_METADATA = + PhoneMetadata.newBuilder().setId("").setInternationalPrefix("NA").build(); + private PhoneMetadata defaultMetadata; + private PhoneMetadata currentMetadata; + + // A pattern that is used to determine if a numberFormat under availableFormats is eligible to be + // used by the AYTF. It is eligible when the format element under numberFormat contains groups of + // the dollar sign followed by a single digit, separated by valid phone number punctuation. This + // prevents invalid punctuation (such as the star sign in Israeli star numbers) getting into the + // output of the AYTF. We require that the first group is present in the output pattern to ensure + // no data is lost while formatting; when we format as you type, this should always be the case. + private static final Pattern ELIGIBLE_FORMAT_PATTERN = + Pattern.compile("[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*" + + "\\$1" + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*(\\$\\d" + + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*)*"); + // A set of characters that, if found in a national prefix formatting rules, are an indicator to + // us that we should separate the national prefix from the number when formatting. + private static final Pattern NATIONAL_PREFIX_SEPARATORS_PATTERN = Pattern.compile("[- ]"); + + // This is the minimum length of national number accrued that is required to trigger the + // formatter. The first element of the leadingDigitsPattern of each numberFormat contains a + // regular expression that matches up to this number of digits. + private static final int MIN_LEADING_DIGITS_LENGTH = 3; + + // The digits that have not been entered yet will be represented by a \u2008, the punctuation + // space. + private static final String DIGIT_PLACEHOLDER = "\u2008"; + private static final Pattern DIGIT_PATTERN = Pattern.compile(DIGIT_PLACEHOLDER); + private int lastMatchPosition = 0; + // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as + // found in the original sequence of characters the user entered. + private int originalPosition = 0; + // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as + // found in accruedInputWithoutFormatting. + private int positionToRemember = 0; + // This contains anything that has been entered so far preceding the national significant number, + // and it is formatted (e.g. with space inserted). For example, this can contain IDD, country + // code, and/or NDD, etc. + private StringBuilder prefixBeforeNationalNumber = new StringBuilder(); + private boolean shouldAddSpaceAfterNationalPrefix = false; + // This contains the national prefix that has been extracted. It contains only digits without + // formatting. + private String extractedNationalPrefix = ""; + private StringBuilder nationalNumber = new StringBuilder(); + private List possibleFormats = new ArrayList(); + + // A cache for frequently used country-specific regular expressions. + private RegexCache regexCache = new RegexCache(64); + + /** + * Constructs an as-you-type formatter. Should be obtained from {@link + * PhoneNumberUtil#getAsYouTypeFormatter}. + * + * @param regionCode the country/region where the phone number is being entered + */ + AsYouTypeFormatter(String regionCode) { + defaultCountry = regionCode; + currentMetadata = getMetadataForRegion(defaultCountry); + defaultMetadata = currentMetadata; + } + + // The metadata needed by this class is the same for all regions sharing the same country calling + // code. Therefore, we return the metadata for "main" region for this country calling code. + private PhoneMetadata getMetadataForRegion(String regionCode) { + int countryCallingCode = phoneUtil.getCountryCodeForRegion(regionCode); + String mainCountry = phoneUtil.getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadata = phoneUtil.getMetadataForRegion(mainCountry); + if (metadata != null) { + return metadata; + } + // Set to a default instance of the metadata. This allows us to function with an incorrect + // region code, even if formatting only works for numbers specified with "+". + return EMPTY_METADATA; + } + + // Returns true if a new template is created as opposed to reusing the existing template. + private boolean maybeCreateNewTemplate() { + // When there are multiple available formats, the formatter uses the first format where a + // formatting template could be created. + Iterator it = possibleFormats.iterator(); + while (it.hasNext()) { + NumberFormat numberFormat = it.next(); + String pattern = numberFormat.getPattern(); + if (currentFormattingPattern.equals(pattern)) { + return false; + } + if (createFormattingTemplate(numberFormat)) { + currentFormattingPattern = pattern; + shouldAddSpaceAfterNationalPrefix = + NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher( + numberFormat.getNationalPrefixFormattingRule()).find(); + // With a new formatting template, the matched position using the old template needs to be + // reset. + lastMatchPosition = 0; + return true; + } else { // Remove the current number format from possibleFormats. + it.remove(); + } + } + ableToFormat = false; + return false; + } + + private void getAvailableFormats(String leadingDigits) { + // First decide whether we should use international or national number rules. + boolean isInternationalNumber = isCompleteNumber && extractedNationalPrefix.length() == 0; + List formatList = + (isInternationalNumber && currentMetadata.getIntlNumberFormatCount() > 0) + ? currentMetadata.getIntlNumberFormatList() + : currentMetadata.getNumberFormatList(); + for (NumberFormat format : formatList) { + // Discard a few formats that we know are not relevant based on the presence of the national + // prefix. + if (extractedNationalPrefix.length() > 0 + && PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + format.getNationalPrefixFormattingRule()) + && !format.getNationalPrefixOptionalWhenFormatting() + && !format.hasDomesticCarrierCodeFormattingRule()) { + // If it is a national number that had a national prefix, any rules that aren't valid with a + // national prefix should be excluded. A rule that has a carrier-code formatting rule is + // kept since the national prefix might actually be an extracted carrier code - we don't + // distinguish between these when extracting it in the AYTF. + continue; + } else if (extractedNationalPrefix.length() == 0 + && !isCompleteNumber + && !PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + format.getNationalPrefixFormattingRule()) + && !format.getNationalPrefixOptionalWhenFormatting()) { + // This number was entered without a national prefix, and this formatting rule requires one, + // so we discard it. + continue; + } + if (ELIGIBLE_FORMAT_PATTERN.matcher(format.getFormat()).matches()) { + possibleFormats.add(format); + } + } + narrowDownPossibleFormats(leadingDigits); + } + + private void narrowDownPossibleFormats(String leadingDigits) { + int indexOfLeadingDigitsPattern = leadingDigits.length() - MIN_LEADING_DIGITS_LENGTH; + Iterator it = possibleFormats.iterator(); + while (it.hasNext()) { + NumberFormat format = it.next(); + if (format.getLeadingDigitsPatternCount() == 0) { + // Keep everything that isn't restricted by leading digits. + continue; + } + int lastLeadingDigitsPattern = + Math.min(indexOfLeadingDigitsPattern, format.getLeadingDigitsPatternCount() - 1); + Pattern leadingDigitsPattern = regexCache.getPatternForRegex( + format.getLeadingDigitsPattern(lastLeadingDigitsPattern)); + Matcher m = leadingDigitsPattern.matcher(leadingDigits); + if (!m.lookingAt()) { + it.remove(); + } + } + } + + private boolean createFormattingTemplate(NumberFormat format) { + String numberPattern = format.getPattern(); + formattingTemplate.setLength(0); + String tempTemplate = getFormattingTemplate(numberPattern, format.getFormat()); + if (tempTemplate.length() > 0) { + formattingTemplate.append(tempTemplate); + return true; + } + return false; + } + + // Gets a formatting template which can be used to efficiently format a partial number where + // digits are added one by one. + private String getFormattingTemplate(String numberPattern, String numberFormat) { + // Creates a phone number consisting only of the digit 9 that matches the + // numberPattern by applying the pattern to the longestPhoneNumber string. + String longestPhoneNumber = "999999999999999"; + Matcher m = regexCache.getPatternForRegex(numberPattern).matcher(longestPhoneNumber); + m.find(); // this will always succeed + String aPhoneNumber = m.group(); + // No formatting template can be created if the number of digits entered so far is longer than + // the maximum the current formatting rule can accommodate. + if (aPhoneNumber.length() < nationalNumber.length()) { + return ""; + } + // Formats the number according to numberFormat + String template = aPhoneNumber.replaceAll(numberPattern, numberFormat); + // Replaces each digit with character DIGIT_PLACEHOLDER + template = template.replaceAll("9", DIGIT_PLACEHOLDER); + return template; + } + + /** + * Clears the internal state of the formatter, so it can be reused. + */ + public void clear() { + currentOutput = ""; + accruedInput.setLength(0); + accruedInputWithoutFormatting.setLength(0); + formattingTemplate.setLength(0); + lastMatchPosition = 0; + currentFormattingPattern = ""; + prefixBeforeNationalNumber.setLength(0); + extractedNationalPrefix = ""; + nationalNumber.setLength(0); + ableToFormat = true; + inputHasFormatting = false; + positionToRemember = 0; + originalPosition = 0; + isCompleteNumber = false; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + shouldAddSpaceAfterNationalPrefix = false; + if (!currentMetadata.equals(defaultMetadata)) { + currentMetadata = getMetadataForRegion(defaultCountry); + } + } + + /** + * Formats a phone number on-the-fly as each digit is entered. + * + * @param nextChar the most recently entered digit of a phone number. Formatting characters are + * allowed, but as soon as they are encountered this method formats the number as entered and + * not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will + * be shown as they are. + * @return the partially formatted phone number. + */ + public String inputDigit(char nextChar) { + currentOutput = inputDigitWithOptionToRememberPosition(nextChar, false); + return currentOutput; + } + + /** + * Same as {@link #inputDigit}, but remembers the position where {@code nextChar} is inserted, so + * that it can be retrieved later by using {@link #getRememberedPosition}. The remembered + * position will be automatically adjusted if additional formatting characters are later + * inserted/removed in front of {@code nextChar}. + */ + public String inputDigitAndRememberPosition(char nextChar) { + currentOutput = inputDigitWithOptionToRememberPosition(nextChar, true); + return currentOutput; + } + + @SuppressWarnings("fallthrough") + private String inputDigitWithOptionToRememberPosition(char nextChar, boolean rememberPosition) { + accruedInput.append(nextChar); + if (rememberPosition) { + originalPosition = accruedInput.length(); + } + // We do formatting on-the-fly only when each character entered is either a digit, or a plus + // sign (accepted at the start of the number only). + if (!isDigitOrLeadingPlusSign(nextChar)) { + ableToFormat = false; + inputHasFormatting = true; + } else { + nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar, rememberPosition); + } + if (!ableToFormat) { + // When we are unable to format because of reasons other than that formatting chars have been + // entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able + // to do formatting again after extracting them. + if (inputHasFormatting) { + return accruedInput.toString(); + } else if (attemptToExtractIdd()) { + if (attemptToExtractCountryCallingCode()) { + return attemptToChoosePatternWithPrefixExtracted(); + } + } else if (ableToExtractLongerNdd()) { + // Add an additional space to separate long NDD and national significant number for + // readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want + // this to change later when we choose formatting templates. + prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + return attemptToChoosePatternWithPrefixExtracted(); + } + return accruedInput.toString(); + } + + // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus + // sign is counted as a digit as well for this purpose) have been entered. + switch (accruedInputWithoutFormatting.length()) { + case 0: + case 1: + case 2: + return accruedInput.toString(); + case 3: + if (attemptToExtractIdd()) { + isExpectingCountryCallingCode = true; + } else { // No IDD or plus sign is found, might be entering in national format. + extractedNationalPrefix = removeNationalPrefixFromNationalNumber(); + return attemptToChooseFormattingPattern(); + } + // fall through + default: + if (isExpectingCountryCallingCode) { + if (attemptToExtractCountryCallingCode()) { + isExpectingCountryCallingCode = false; + } + return prefixBeforeNationalNumber + nationalNumber.toString(); + } + if (possibleFormats.size() > 0) { // The formatting patterns are already chosen. + String tempNationalNumber = inputDigitHelper(nextChar); + // See if the accrued digits can be formatted properly already. If not, use the results + // from inputDigitHelper, which does formatting based on the formatting pattern chosen. + String formattedNumber = attemptToFormatAccruedDigits(); + if (formattedNumber.length() > 0) { + return formattedNumber; + } + narrowDownPossibleFormats(nationalNumber.toString()); + if (maybeCreateNewTemplate()) { + return inputAccruedNationalNumber(); + } + return ableToFormat + ? appendNationalNumber(tempNationalNumber) + : accruedInput.toString(); + } else { + return attemptToChooseFormattingPattern(); + } + } + } + + private String attemptToChoosePatternWithPrefixExtracted() { + ableToFormat = true; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + lastMatchPosition = 0; + formattingTemplate.setLength(0); + currentFormattingPattern = ""; + return attemptToChooseFormattingPattern(); + } + + // @VisibleForTesting + String getExtractedNationalPrefix() { + return extractedNationalPrefix; + } + + // Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result + // in a number we can format, we try to see if we can extract a longer version here. + private boolean ableToExtractLongerNdd() { + if (extractedNationalPrefix.length() > 0) { + // Put the extracted NDD back to the national number before attempting to extract a new NDD. + nationalNumber.insert(0, extractedNationalPrefix); + // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set + // it to empty string because people sometimes incorrectly enter national prefix after the + // country code, e.g. +44 (0)20-1234-5678. + int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(extractedNationalPrefix); + prefixBeforeNationalNumber.setLength(indexOfPreviousNdd); + } + return !extractedNationalPrefix.equals(removeNationalPrefixFromNationalNumber()); + } + + private boolean isDigitOrLeadingPlusSign(char nextChar) { + return Character.isDigit(nextChar) + || (accruedInput.length() == 1 + && PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches()); + } + + /** + * Checks to see if there is an exact pattern match for these digits. If so, we should use this + * instead of any other formatting template whose leadingDigitsPattern also matches the input. + */ + String attemptToFormatAccruedDigits() { + for (NumberFormat numberFormat : possibleFormats) { + Matcher m = regexCache.getPatternForRegex(numberFormat.getPattern()).matcher(nationalNumber); + if (m.matches()) { + shouldAddSpaceAfterNationalPrefix = + NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher( + numberFormat.getNationalPrefixFormattingRule()).find(); + String formattedNumber = m.replaceAll(numberFormat.getFormat()); + // Check that we did not remove nor add any extra digits when we matched + // this formatting pattern. This usually happens after we entered the last + // digit during AYTF. Eg: In case of MX, we swallow mobile token (1) when + // formatted but AYTF should retain all the number entered and not change + // in order to match a format (of same leading digits and length) display + // in that way. + String fullOutput = appendNationalNumber(formattedNumber); + String formattedNumberDigitsOnly = PhoneNumberUtil.normalizeDiallableCharsOnly(fullOutput); + if (formattedNumberDigitsOnly.contentEquals(accruedInputWithoutFormatting)) { + // If it's the same (i.e entered number and format is same), then it's + // safe to return this in formatted number as nothing is lost / added. + return fullOutput; + } + } + } + return ""; + } + + /** + * Returns the current position in the partially formatted phone number of the character which was + * previously passed in as the parameter of {@link #inputDigitAndRememberPosition}. + */ + public int getRememberedPosition() { + if (!ableToFormat) { + return originalPosition; + } + int accruedInputIndex = 0; + int currentOutputIndex = 0; + while (accruedInputIndex < positionToRemember && currentOutputIndex < currentOutput.length()) { + if (accruedInputWithoutFormatting.charAt(accruedInputIndex) + == currentOutput.charAt(currentOutputIndex)) { + accruedInputIndex++; + } + currentOutputIndex++; + } + return currentOutputIndex; + } + + /** + * Combines the national number with any prefix (IDD/+ and country code or national prefix) that + * was collected. A space will be inserted between them if the current formatting template + * indicates this to be suitable. + */ + private String appendNationalNumber(String nationalNumber) { + int prefixBeforeNationalNumberLength = prefixBeforeNationalNumber.length(); + if (shouldAddSpaceAfterNationalPrefix && prefixBeforeNationalNumberLength > 0 + && prefixBeforeNationalNumber.charAt(prefixBeforeNationalNumberLength - 1) + != SEPARATOR_BEFORE_NATIONAL_NUMBER) { + // We want to add a space after the national prefix if the national prefix formatting rule + // indicates that this would normally be done, with the exception of the case where we already + // appended a space because the NDD was surprisingly long. + return new String(prefixBeforeNationalNumber) + SEPARATOR_BEFORE_NATIONAL_NUMBER + + nationalNumber; + } else { + return prefixBeforeNationalNumber + nationalNumber; + } + } + + /** + * 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 at least MIN_LEADING_DIGITS_LENGTH digits of national + // number (excluding national prefix) have been entered. + if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) { + + getAvailableFormats(nationalNumber.toString()); + // See if the accrued digits can be formatted properly already. + String formattedNumber = attemptToFormatAccruedDigits(); + if (formattedNumber.length() > 0) { + return formattedNumber; + } + return maybeCreateNewTemplate() ? inputAccruedNationalNumber() : accruedInput.toString(); + } else { + return appendNationalNumber(nationalNumber.toString()); + } + } + + /** + * Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted + * string in the end. + */ + private String inputAccruedNationalNumber() { + int lengthOfNationalNumber = nationalNumber.length(); + if (lengthOfNationalNumber > 0) { + String tempNationalNumber = ""; + for (int i = 0; i < lengthOfNationalNumber; i++) { + tempNationalNumber = inputDigitHelper(nationalNumber.charAt(i)); + } + return ableToFormat ? appendNationalNumber(tempNationalNumber) : accruedInput.toString(); + } else { + return prefixBeforeNationalNumber.toString(); + } + } + + /** + * Returns true if the current country is a NANPA country and the national number begins with + * the national prefix. + */ + private boolean isNanpaNumberWithNationalPrefix() { + // For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is + // that national significant numbers in NANPA always start with [2-9] after the national prefix. + // Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the + // national prefix. + return (currentMetadata.getCountryCode() == 1) && (nationalNumber.charAt(0) == '1') + && (nationalNumber.charAt(1) != '0') && (nationalNumber.charAt(1) != '1'); + } + + // Returns the national prefix extracted, or an empty string if it is not present. + private String removeNationalPrefixFromNationalNumber() { + int startOfNationalNumber = 0; + if (isNanpaNumberWithNationalPrefix()) { + startOfNationalNumber = 1; + prefixBeforeNationalNumber.append('1').append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + isCompleteNumber = true; + } else if (currentMetadata.hasNationalPrefixForParsing()) { + Pattern nationalPrefixForParsing = + regexCache.getPatternForRegex(currentMetadata.getNationalPrefixForParsing()); + Matcher m = nationalPrefixForParsing.matcher(nationalNumber); + // Since some national prefix patterns are entirely optional, check that a national prefix + // could actually be extracted. + if (m.lookingAt() && m.end() > 0) { + // When the national prefix is detected, we use international formatting rules instead of + // national ones, because national formatting rules could contain local formatting rules + // for numbers entered without area code. + isCompleteNumber = true; + startOfNationalNumber = m.end(); + prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber)); + } + } + String nationalPrefix = nationalNumber.substring(0, startOfNationalNumber); + nationalNumber.delete(0, startOfNationalNumber); + return nationalPrefix; + } + + /** + * Extracts IDD and plus sign to prefixBeforeNationalNumber when they are available, and places + * the remaining input into nationalNumber. + * + * @return true when accruedInputWithoutFormatting begins with the plus sign or valid IDD for + * defaultCountry. + */ + private boolean attemptToExtractIdd() { + Pattern internationalPrefix = + regexCache.getPatternForRegex("\\" + PhoneNumberUtil.PLUS_SIGN + "|" + + currentMetadata.getInternationalPrefix()); + Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting); + if (iddMatcher.lookingAt()) { + isCompleteNumber = true; + int startOfCountryCallingCode = iddMatcher.end(); + nationalNumber.setLength(0); + nationalNumber.append(accruedInputWithoutFormatting.substring(startOfCountryCallingCode)); + prefixBeforeNationalNumber.setLength(0); + prefixBeforeNationalNumber.append( + accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode)); + if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN) { + prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + } + return true; + } + return false; + } + + /** + * Extracts the country calling code from the beginning of nationalNumber to + * prefixBeforeNationalNumber when they are available, and places the remaining input into + * nationalNumber. + * + * @return true when a valid country calling code can be found. + */ + private boolean attemptToExtractCountryCallingCode() { + if (nationalNumber.length() == 0) { + return false; + } + StringBuilder numberWithoutCountryCallingCode = new StringBuilder(); + int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode); + if (countryCode == 0) { + return false; + } + nationalNumber.setLength(0); + nationalNumber.append(numberWithoutCountryCallingCode); + String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode); + if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(newRegionCode)) { + currentMetadata = phoneUtil.getMetadataForNonGeographicalRegion(countryCode); + } else if (!newRegionCode.equals(defaultCountry)) { + currentMetadata = getMetadataForRegion(newRegionCode); + } + String countryCodeString = Integer.toString(countryCode); + prefixBeforeNationalNumber.append(countryCodeString).append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + // When we have successfully extracted the IDD, the previously extracted NDD should be cleared + // because it is no longer valid. + extractedNationalPrefix = ""; + return true; + } + + // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar + // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first + // normalized to the ASCII version. The return value is nextChar itself, or its normalized + // version, if nextChar is a digit in non-ASCII format. This method assumes its input is either a + // digit or the plus sign. + private char normalizeAndAccrueDigitsAndPlusSign(char nextChar, boolean rememberPosition) { + char normalizedChar; + if (nextChar == PhoneNumberUtil.PLUS_SIGN) { + normalizedChar = nextChar; + accruedInputWithoutFormatting.append(nextChar); + } else { + int radix = 10; + normalizedChar = Character.forDigit(Character.digit(nextChar, radix), radix); + accruedInputWithoutFormatting.append(normalizedChar); + nationalNumber.append(normalizedChar); + } + if (rememberPosition) { + positionToRemember = accruedInputWithoutFormatting.length(); + } + return normalizedChar; + } + + private String inputDigitHelper(char nextChar) { + // Note that formattingTemplate is not guaranteed to have a value, it could be empty, e.g. + // when the next digit is entered after extracting an IDD or NDD. + Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate); + if (digitMatcher.find(lastMatchPosition)) { + String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar)); + formattingTemplate.replace(0, tempTemplate.length(), tempTemplate); + lastMatchPosition = digitMatcher.start(); + return formattingTemplate.substring(0, lastMatchPosition + 1); + } else { + if (possibleFormats.size() == 1) { + // More digits are entered than we could handle, and there are no other valid patterns to + // try. + ableToFormat = false; + } // else, we just reset the formatting pattern. + currentFormattingPattern = ""; + return accruedInput.toString(); + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java new file mode 100644 index 0000000000..06571d15f0 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java @@ -0,0 +1,942 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CountryCodeToRegionCodeMap { + // A mapping from a country code to the region codes which denote the + // country/region represented by that country code. In the case of multiple + // countries sharing a calling code, such as the NANPA countries, the one + // indicated with "isMainCountryForCode" in the metadata should be first. + public static Map> getCountryCodeToRegionCodeMap() { + // The capacity is set to 286 as there are 215 different entries, + // and this offers a load factor of roughly 0.75. + Map> countryCodeToRegionCodeMap = + new HashMap>(286); + + ArrayList listWithRegionCode; + + listWithRegionCode = new ArrayList(25); + listWithRegionCode.add("US"); + listWithRegionCode.add("AG"); + listWithRegionCode.add("AI"); + listWithRegionCode.add("AS"); + listWithRegionCode.add("BB"); + listWithRegionCode.add("BM"); + listWithRegionCode.add("BS"); + listWithRegionCode.add("CA"); + listWithRegionCode.add("DM"); + listWithRegionCode.add("DO"); + listWithRegionCode.add("GD"); + listWithRegionCode.add("GU"); + listWithRegionCode.add("JM"); + listWithRegionCode.add("KN"); + listWithRegionCode.add("KY"); + listWithRegionCode.add("LC"); + listWithRegionCode.add("MP"); + listWithRegionCode.add("MS"); + listWithRegionCode.add("PR"); + listWithRegionCode.add("SX"); + listWithRegionCode.add("TC"); + listWithRegionCode.add("TT"); + listWithRegionCode.add("VC"); + listWithRegionCode.add("VG"); + listWithRegionCode.add("VI"); + countryCodeToRegionCodeMap.put(1, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("RU"); + listWithRegionCode.add("KZ"); + countryCodeToRegionCodeMap.put(7, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EG"); + countryCodeToRegionCodeMap.put(20, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZA"); + countryCodeToRegionCodeMap.put(27, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GR"); + countryCodeToRegionCodeMap.put(30, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NL"); + countryCodeToRegionCodeMap.put(31, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BE"); + countryCodeToRegionCodeMap.put(32, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FR"); + countryCodeToRegionCodeMap.put(33, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ES"); + countryCodeToRegionCodeMap.put(34, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HU"); + countryCodeToRegionCodeMap.put(36, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("IT"); + listWithRegionCode.add("VA"); + countryCodeToRegionCodeMap.put(39, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RO"); + countryCodeToRegionCodeMap.put(40, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CH"); + countryCodeToRegionCodeMap.put(41, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AT"); + countryCodeToRegionCodeMap.put(43, listWithRegionCode); + + listWithRegionCode = new ArrayList(4); + listWithRegionCode.add("GB"); + listWithRegionCode.add("GG"); + listWithRegionCode.add("IM"); + listWithRegionCode.add("JE"); + countryCodeToRegionCodeMap.put(44, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DK"); + countryCodeToRegionCodeMap.put(45, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SE"); + countryCodeToRegionCodeMap.put(46, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("NO"); + listWithRegionCode.add("SJ"); + countryCodeToRegionCodeMap.put(47, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PL"); + countryCodeToRegionCodeMap.put(48, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DE"); + countryCodeToRegionCodeMap.put(49, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PE"); + countryCodeToRegionCodeMap.put(51, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MX"); + countryCodeToRegionCodeMap.put(52, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CU"); + countryCodeToRegionCodeMap.put(53, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AR"); + countryCodeToRegionCodeMap.put(54, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BR"); + countryCodeToRegionCodeMap.put(55, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CL"); + countryCodeToRegionCodeMap.put(56, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CO"); + countryCodeToRegionCodeMap.put(57, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VE"); + countryCodeToRegionCodeMap.put(58, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MY"); + countryCodeToRegionCodeMap.put(60, listWithRegionCode); + + listWithRegionCode = new ArrayList(3); + listWithRegionCode.add("AU"); + listWithRegionCode.add("CC"); + listWithRegionCode.add("CX"); + countryCodeToRegionCodeMap.put(61, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ID"); + countryCodeToRegionCodeMap.put(62, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PH"); + countryCodeToRegionCodeMap.put(63, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NZ"); + countryCodeToRegionCodeMap.put(64, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SG"); + countryCodeToRegionCodeMap.put(65, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TH"); + countryCodeToRegionCodeMap.put(66, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("JP"); + countryCodeToRegionCodeMap.put(81, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KR"); + countryCodeToRegionCodeMap.put(82, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VN"); + countryCodeToRegionCodeMap.put(84, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CN"); + countryCodeToRegionCodeMap.put(86, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TR"); + countryCodeToRegionCodeMap.put(90, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IN"); + countryCodeToRegionCodeMap.put(91, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PK"); + countryCodeToRegionCodeMap.put(92, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AF"); + countryCodeToRegionCodeMap.put(93, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LK"); + countryCodeToRegionCodeMap.put(94, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MM"); + countryCodeToRegionCodeMap.put(95, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IR"); + countryCodeToRegionCodeMap.put(98, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SS"); + countryCodeToRegionCodeMap.put(211, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("MA"); + listWithRegionCode.add("EH"); + countryCodeToRegionCodeMap.put(212, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DZ"); + countryCodeToRegionCodeMap.put(213, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TN"); + countryCodeToRegionCodeMap.put(216, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LY"); + countryCodeToRegionCodeMap.put(218, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GM"); + countryCodeToRegionCodeMap.put(220, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SN"); + countryCodeToRegionCodeMap.put(221, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MR"); + countryCodeToRegionCodeMap.put(222, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ML"); + countryCodeToRegionCodeMap.put(223, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GN"); + countryCodeToRegionCodeMap.put(224, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CI"); + countryCodeToRegionCodeMap.put(225, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BF"); + countryCodeToRegionCodeMap.put(226, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NE"); + countryCodeToRegionCodeMap.put(227, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TG"); + countryCodeToRegionCodeMap.put(228, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BJ"); + countryCodeToRegionCodeMap.put(229, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MU"); + countryCodeToRegionCodeMap.put(230, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LR"); + countryCodeToRegionCodeMap.put(231, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SL"); + countryCodeToRegionCodeMap.put(232, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GH"); + countryCodeToRegionCodeMap.put(233, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NG"); + countryCodeToRegionCodeMap.put(234, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TD"); + countryCodeToRegionCodeMap.put(235, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CF"); + countryCodeToRegionCodeMap.put(236, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CM"); + countryCodeToRegionCodeMap.put(237, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CV"); + countryCodeToRegionCodeMap.put(238, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ST"); + countryCodeToRegionCodeMap.put(239, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GQ"); + countryCodeToRegionCodeMap.put(240, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GA"); + countryCodeToRegionCodeMap.put(241, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CG"); + countryCodeToRegionCodeMap.put(242, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CD"); + countryCodeToRegionCodeMap.put(243, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AO"); + countryCodeToRegionCodeMap.put(244, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GW"); + countryCodeToRegionCodeMap.put(245, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IO"); + countryCodeToRegionCodeMap.put(246, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AC"); + countryCodeToRegionCodeMap.put(247, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SC"); + countryCodeToRegionCodeMap.put(248, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SD"); + countryCodeToRegionCodeMap.put(249, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RW"); + countryCodeToRegionCodeMap.put(250, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ET"); + countryCodeToRegionCodeMap.put(251, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SO"); + countryCodeToRegionCodeMap.put(252, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DJ"); + countryCodeToRegionCodeMap.put(253, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KE"); + countryCodeToRegionCodeMap.put(254, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TZ"); + countryCodeToRegionCodeMap.put(255, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UG"); + countryCodeToRegionCodeMap.put(256, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BI"); + countryCodeToRegionCodeMap.put(257, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MZ"); + countryCodeToRegionCodeMap.put(258, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZM"); + countryCodeToRegionCodeMap.put(260, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MG"); + countryCodeToRegionCodeMap.put(261, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("RE"); + listWithRegionCode.add("YT"); + countryCodeToRegionCodeMap.put(262, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZW"); + countryCodeToRegionCodeMap.put(263, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NA"); + countryCodeToRegionCodeMap.put(264, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MW"); + countryCodeToRegionCodeMap.put(265, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LS"); + countryCodeToRegionCodeMap.put(266, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BW"); + countryCodeToRegionCodeMap.put(267, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SZ"); + countryCodeToRegionCodeMap.put(268, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KM"); + countryCodeToRegionCodeMap.put(269, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("SH"); + listWithRegionCode.add("TA"); + countryCodeToRegionCodeMap.put(290, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ER"); + countryCodeToRegionCodeMap.put(291, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AW"); + countryCodeToRegionCodeMap.put(297, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FO"); + countryCodeToRegionCodeMap.put(298, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GL"); + countryCodeToRegionCodeMap.put(299, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GI"); + countryCodeToRegionCodeMap.put(350, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PT"); + countryCodeToRegionCodeMap.put(351, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LU"); + countryCodeToRegionCodeMap.put(352, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IE"); + countryCodeToRegionCodeMap.put(353, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IS"); + countryCodeToRegionCodeMap.put(354, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AL"); + countryCodeToRegionCodeMap.put(355, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MT"); + countryCodeToRegionCodeMap.put(356, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CY"); + countryCodeToRegionCodeMap.put(357, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("FI"); + listWithRegionCode.add("AX"); + countryCodeToRegionCodeMap.put(358, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BG"); + countryCodeToRegionCodeMap.put(359, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LT"); + countryCodeToRegionCodeMap.put(370, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LV"); + countryCodeToRegionCodeMap.put(371, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EE"); + countryCodeToRegionCodeMap.put(372, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MD"); + countryCodeToRegionCodeMap.put(373, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AM"); + countryCodeToRegionCodeMap.put(374, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BY"); + countryCodeToRegionCodeMap.put(375, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AD"); + countryCodeToRegionCodeMap.put(376, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MC"); + countryCodeToRegionCodeMap.put(377, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SM"); + countryCodeToRegionCodeMap.put(378, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UA"); + countryCodeToRegionCodeMap.put(380, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RS"); + countryCodeToRegionCodeMap.put(381, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ME"); + countryCodeToRegionCodeMap.put(382, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("XK"); + countryCodeToRegionCodeMap.put(383, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HR"); + countryCodeToRegionCodeMap.put(385, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SI"); + countryCodeToRegionCodeMap.put(386, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BA"); + countryCodeToRegionCodeMap.put(387, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MK"); + countryCodeToRegionCodeMap.put(389, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CZ"); + countryCodeToRegionCodeMap.put(420, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SK"); + countryCodeToRegionCodeMap.put(421, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LI"); + countryCodeToRegionCodeMap.put(423, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FK"); + countryCodeToRegionCodeMap.put(500, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BZ"); + countryCodeToRegionCodeMap.put(501, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GT"); + countryCodeToRegionCodeMap.put(502, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SV"); + countryCodeToRegionCodeMap.put(503, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HN"); + countryCodeToRegionCodeMap.put(504, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NI"); + countryCodeToRegionCodeMap.put(505, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CR"); + countryCodeToRegionCodeMap.put(506, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PA"); + countryCodeToRegionCodeMap.put(507, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PM"); + countryCodeToRegionCodeMap.put(508, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HT"); + countryCodeToRegionCodeMap.put(509, listWithRegionCode); + + listWithRegionCode = new ArrayList(3); + listWithRegionCode.add("GP"); + listWithRegionCode.add("BL"); + listWithRegionCode.add("MF"); + countryCodeToRegionCodeMap.put(590, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BO"); + countryCodeToRegionCodeMap.put(591, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GY"); + countryCodeToRegionCodeMap.put(592, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EC"); + countryCodeToRegionCodeMap.put(593, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GF"); + countryCodeToRegionCodeMap.put(594, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PY"); + countryCodeToRegionCodeMap.put(595, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MQ"); + countryCodeToRegionCodeMap.put(596, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SR"); + countryCodeToRegionCodeMap.put(597, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UY"); + countryCodeToRegionCodeMap.put(598, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("CW"); + listWithRegionCode.add("BQ"); + countryCodeToRegionCodeMap.put(599, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TL"); + countryCodeToRegionCodeMap.put(670, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NF"); + countryCodeToRegionCodeMap.put(672, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BN"); + countryCodeToRegionCodeMap.put(673, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NR"); + countryCodeToRegionCodeMap.put(674, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PG"); + countryCodeToRegionCodeMap.put(675, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TO"); + countryCodeToRegionCodeMap.put(676, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SB"); + countryCodeToRegionCodeMap.put(677, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VU"); + countryCodeToRegionCodeMap.put(678, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FJ"); + countryCodeToRegionCodeMap.put(679, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PW"); + countryCodeToRegionCodeMap.put(680, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("WF"); + countryCodeToRegionCodeMap.put(681, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CK"); + countryCodeToRegionCodeMap.put(682, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NU"); + countryCodeToRegionCodeMap.put(683, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("WS"); + countryCodeToRegionCodeMap.put(685, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KI"); + countryCodeToRegionCodeMap.put(686, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NC"); + countryCodeToRegionCodeMap.put(687, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TV"); + countryCodeToRegionCodeMap.put(688, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PF"); + countryCodeToRegionCodeMap.put(689, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TK"); + countryCodeToRegionCodeMap.put(690, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FM"); + countryCodeToRegionCodeMap.put(691, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MH"); + countryCodeToRegionCodeMap.put(692, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(800, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(808, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KP"); + countryCodeToRegionCodeMap.put(850, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HK"); + countryCodeToRegionCodeMap.put(852, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MO"); + countryCodeToRegionCodeMap.put(853, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KH"); + countryCodeToRegionCodeMap.put(855, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LA"); + countryCodeToRegionCodeMap.put(856, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(870, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(878, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BD"); + countryCodeToRegionCodeMap.put(880, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(881, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(882, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(883, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TW"); + countryCodeToRegionCodeMap.put(886, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(888, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MV"); + countryCodeToRegionCodeMap.put(960, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LB"); + countryCodeToRegionCodeMap.put(961, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("JO"); + countryCodeToRegionCodeMap.put(962, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SY"); + countryCodeToRegionCodeMap.put(963, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IQ"); + countryCodeToRegionCodeMap.put(964, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KW"); + countryCodeToRegionCodeMap.put(965, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SA"); + countryCodeToRegionCodeMap.put(966, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("YE"); + countryCodeToRegionCodeMap.put(967, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("OM"); + countryCodeToRegionCodeMap.put(968, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PS"); + countryCodeToRegionCodeMap.put(970, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AE"); + countryCodeToRegionCodeMap.put(971, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IL"); + countryCodeToRegionCodeMap.put(972, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BH"); + countryCodeToRegionCodeMap.put(973, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("QA"); + countryCodeToRegionCodeMap.put(974, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BT"); + countryCodeToRegionCodeMap.put(975, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MN"); + countryCodeToRegionCodeMap.put(976, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NP"); + countryCodeToRegionCodeMap.put(977, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(979, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TJ"); + countryCodeToRegionCodeMap.put(992, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TM"); + countryCodeToRegionCodeMap.put(993, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AZ"); + countryCodeToRegionCodeMap.put(994, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GE"); + countryCodeToRegionCodeMap.put(995, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KG"); + countryCodeToRegionCodeMap.put(996, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UZ"); + countryCodeToRegionCodeMap.put(998, listWithRegionCode); + + return countryCodeToRegionCodeMap; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MetadataLoader.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MetadataLoader.java new file mode 100644 index 0000000000..44fa0dc445 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MetadataLoader.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import java.io.InputStream; + +/** + * Interface for clients to specify a customized phone metadata loader, useful for Android apps to + * load Android resources since the library loads Java resources by default, e.g. with + * + * AssetManager. Note that implementation owners have the responsibility to ensure this is + * thread-safe. + */ +public interface MetadataLoader { + /** + * Returns an input stream corresponding to the metadata to load. This method may be called + * concurrently so implementations must be thread-safe. + * + * @param metadataFileName file name (including path) of metadata to load. File path is an + * absolute class path like /com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto + * @return the input stream for the metadata file. The library will close this stream + * after it is done. Return null in case the metadata file could not be found + */ + public InputStream loadMetadata(String metadataFileName); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MissingMetadataException.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MissingMetadataException.java new file mode 100644 index 0000000000..c2a8544ca3 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/MissingMetadataException.java @@ -0,0 +1,9 @@ +package com.google.i18n.phonenumbers; + +/** Exception class for cases when expected metadata cannot be found. */ +public final class MissingMetadataException extends IllegalStateException { + + public MissingMetadataException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/NumberParseException.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/NumberParseException.java new file mode 100644 index 0000000000..ef3dfa11b8 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/NumberParseException.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +/** + * Generic exception class for errors encountered when parsing phone numbers. + */ +@SuppressWarnings("serial") +public class NumberParseException extends Exception { + + /** + * The reason that a string could not be interpreted as a phone number. + */ + public enum ErrorType { + /** + * The country code supplied did not belong to a supported country or non-geographical entity. + */ + INVALID_COUNTRY_CODE, + /** + * This indicates the string passed is not a valid number. Either the string had less than 3 + * digits in it or had an invalid phone-context parameter. More specifically, the number failed + * to match the regular expression VALID_PHONE_NUMBER, RFC3966_GLOBAL_NUMBER_DIGITS, or + * RFC3966_DOMAINNAME in PhoneNumberUtil.java. + */ + NOT_A_NUMBER, + /** + * This indicates the string started with an international dialing prefix, but after this was + * stripped from the number, had less digits than any valid phone number (including country + * code) could have. + */ + TOO_SHORT_AFTER_IDD, + /** + * This indicates the string, after any country code has been stripped, had less digits than any + * valid phone number could have. + */ + TOO_SHORT_NSN, + /** + * This indicates the string had more digits than any valid phone number could have. + */ + TOO_LONG, + } + + private ErrorType errorType; + private String message; + + public NumberParseException(ErrorType errorType, String message) { + super(message); + this.message = message; + this.errorType = errorType; + } + + /** + * Returns the error type of the exception that has been thrown. + */ + public ErrorType getErrorType() { + return errorType; + } + + @Override + public String toString() { + return "Error type: " + errorType + ". " + message; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java new file mode 100644 index 0000000000..de95eac96d --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import java.util.Arrays; + +/** + * The immutable match of a phone number within a piece of text. Matches may be found using + * {@link PhoneNumberUtil#findNumbers}. + * + *

A match consists of the {@linkplain #number() phone number} as well as the + * {@linkplain #start() start} and {@linkplain #end() end} offsets of the corresponding subsequence + * of the searched text. Use {@link #rawString()} to obtain a copy of the matched subsequence. + * + *

The following annotated example clarifies the relationship between the searched text, the + * match offsets, and the parsed number: + + *

+ * CharSequence text = "Call me at +1 425 882-8080 for details.";
+ * String country = "US";
+ * PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ *
+ * // Find the first phone number match:
+ * PhoneNumberMatch m = util.findNumbers(text, country).iterator().next();
+ *
+ * // rawString() contains the phone number as it appears in the text.
+ * "+1 425 882-8080".equals(m.rawString());
+ *
+ * // start() and end() define the range of the matched subsequence.
+ * CharSequence subsequence = text.subSequence(m.start(), m.end());
+ * "+1 425 882-8080".contentEquals(subsequence);
+ *
+ * // number() returns the the same result as PhoneNumberUtil.{@link PhoneNumberUtil#parse parse()}
+ * // invoked on rawString().
+ * util.parse(m.rawString(), country).equals(m.number());
+ * 
+ */ +public final class PhoneNumberMatch { + /** The start index into the text. */ + private final int start; + /** The raw substring matched. */ + private final String rawString; + /** The matched phone number. */ + private final PhoneNumber number; + + /** + * Creates a new match. + * + * @param start the start index into the target text + * @param rawString the matched substring of the target text + * @param number the matched phone number + */ + PhoneNumberMatch(int start, String rawString, PhoneNumber number) { + if (start < 0) { + throw new IllegalArgumentException("Start index must be >= 0."); + } + if (rawString == null || number == null) { + throw new NullPointerException(); + } + this.start = start; + this.rawString = rawString; + this.number = number; + } + + /** Returns the phone number matched by the receiver. */ + public PhoneNumber number() { + return number; + } + + /** Returns the start index of the matched phone number within the searched text. */ + public int start() { + return start; + } + + /** Returns the exclusive end index of the matched phone number within the searched text. */ + public int end() { + return start + rawString.length(); + } + + /** Returns the raw string matched as a phone number in the searched text. */ + public String rawString() { + return rawString; + } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[]{start, rawString, number}); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PhoneNumberMatch)) { + return false; + } + PhoneNumberMatch other = (PhoneNumberMatch) obj; + return rawString.equals(other.rawString) && (start == other.start) + && number.equals(other.number); + } + + @Override + public String toString() { + return "PhoneNumberMatch [" + start() + "," + end() + ") " + rawString; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java new file mode 100644 index 0000000000..b812551db0 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.PhoneNumberUtil.Leniency; +import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType; +import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.internal.RegexCache; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import java.lang.Character.UnicodeBlock; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A stateful class that finds and extracts telephone numbers from {@linkplain CharSequence text}. + * Instances can be created using the {@linkplain PhoneNumberUtil#findNumbers factory methods} in + * {@link PhoneNumberUtil}. + * + *

Vanity numbers (phone numbers using alphabetic digits such as 1-800-SIX-FLAGS are + * not found. + * + *

This class is not thread-safe. + */ +final class PhoneNumberMatcher implements Iterator { + /** + * The phone number pattern used by {@link #find}, similar to + * {@code PhoneNumberUtil.VALID_PHONE_NUMBER}, but with the following differences: + *

    + *
  • All captures are limited in order to place an upper bound to the text matched by the + * pattern. + *
      + *
    • Leading punctuation / plus signs are limited. + *
    • Consecutive occurrences of punctuation are limited. + *
    • Number of digits is limited. + *
    + *
  • No whitespace is allowed at the start or end. + *
  • No alpha digits (vanity numbers such as 1-800-SIX-FLAGS) are currently supported. + *
+ */ + private static final Pattern PATTERN; + /** + * Matches strings that look like publication pages. Example: + *
Computing Complete Answers to Queries in the Presence of Limited Access Patterns.
+   * Chen Li. VLDB J. 12(3): 211-227 (2003).
+ * + * The string "211-227 (2003)" is not a telephone number. + */ + private static final Pattern PUB_PAGES = Pattern.compile("\\d{1,5}-+\\d{1,5}\\s{0,4}\\(\\d{1,4}"); + + /** + * Matches strings that look like dates using "/" as a separator. Examples: 3/10/2011, 31/10/96 or + * 08/31/95. + */ + private static final Pattern SLASH_SEPARATED_DATES = + Pattern.compile("(?:(?:[0-3]?\\d/[01]?\\d)|(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}"); + + /** + * Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does not include the + * trailing ":\d\d" -- that is covered by TIME_STAMPS_SUFFIX. + */ + private static final Pattern TIME_STAMPS = + Pattern.compile("[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d +[0-2]\\d$"); + private static final Pattern TIME_STAMPS_SUFFIX = Pattern.compile(":[0-5]\\d"); + + /** + * Pattern to check that brackets match. Opening brackets should be closed within a phone number. + * This also checks that there is something inside the brackets. Having no brackets at all is also + * fine. + */ + private static final Pattern MATCHING_BRACKETS; + + /** + * Patterns used to extract phone numbers from a larger phone-number-like pattern. These are + * ordered according to specificity. For example, white-space is last since that is frequently + * used in numbers, not just to separate two numbers. We have separate patterns since we don't + * want to break up the phone-number-like text on more than one different kind of symbol at one + * time, although symbols of the same type (e.g. space) can be safely grouped together. + * + * Note that if there is a match, we will always check any text found up to the first match as + * well. + */ + private static final Pattern[] INNER_MATCHES = { + // Breaks on the slash - e.g. "651-234-2345/332-445-1234" + Pattern.compile("/+(.*)"), + // Note that the bracket here is inside the capturing group, since we consider it part of the + // phone number. Will match a pattern like "(650) 223 3345 (754) 223 3321". + Pattern.compile("(\\([^(]*)"), + // Breaks on a hyphen - e.g. "12345 - 332-445-1234 is my number." + // We require a space on either side of the hyphen for it to be considered a separator. + Pattern.compile("(?:\\p{Z}-|-\\p{Z})\\p{Z}*(.+)"), + // Various types of wide hyphens. Note we have decided not to enforce a space here, since it's + // possible that it's supposed to be used to break two numbers without spaces, and we haven't + // seen many instances of it used within a number. + Pattern.compile("[\u2012-\u2015\uFF0D]\\p{Z}*(.+)"), + // Breaks on a full stop - e.g. "12345. 332-445-1234 is my number." + Pattern.compile("\\.+\\p{Z}*([^.]+)"), + // Breaks on space - e.g. "3324451234 8002341234" + Pattern.compile("\\p{Z}+(\\P{Z}+)") + }; + + /** + * Punctuation that may be at the start of a phone number - brackets and plus signs. + */ + private static final Pattern LEAD_CLASS; + + static { + /* Builds the MATCHING_BRACKETS and PATTERN regular expressions. The building blocks below exist + * to make the pattern more easily understood. */ + + String openingParens = "(\\[\uFF08\uFF3B"; + String closingParens = ")\\]\uFF09\uFF3D"; + String nonParens = "[^" + openingParens + closingParens + "]"; + + /* Limit on the number of pairs of brackets in a phone number. */ + String bracketPairLimit = limit(0, 3); + /* + * An opening bracket at the beginning may not be closed, but subsequent ones should be. It's + * also possible that the leading bracket was dropped, so we shouldn't be surprised if we see a + * closing bracket first. We limit the sets of brackets in a phone number to four. + */ + MATCHING_BRACKETS = Pattern.compile( + "(?:[" + openingParens + "])?" + "(?:" + nonParens + "+" + "[" + closingParens + "])?" + + nonParens + "+" + + "(?:[" + openingParens + "]" + nonParens + "+[" + closingParens + "])" + bracketPairLimit + + nonParens + "*"); + + /* Limit on the number of leading (plus) characters. */ + String leadLimit = limit(0, 2); + /* Limit on the number of consecutive punctuation characters. */ + String punctuationLimit = limit(0, 4); + /* The maximum number of digits allowed in a digit-separated block. As we allow all digits in a + * single block, set high enough to accommodate the entire national number and the international + * country code. */ + int digitBlockLimit = + PhoneNumberUtil.MAX_LENGTH_FOR_NSN + PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE; + /* Limit on the number of blocks separated by punctuation. Uses digitBlockLimit since some + * formats use spaces to separate each digit. */ + String blockLimit = limit(0, digitBlockLimit); + + /* A punctuation sequence allowing white space. */ + String punctuation = "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]" + punctuationLimit; + /* A digits block without punctuation. */ + String digitSequence = "\\p{Nd}" + limit(1, digitBlockLimit); + + String leadClassChars = openingParens + PhoneNumberUtil.PLUS_CHARS; + String leadClass = "[" + leadClassChars + "]"; + LEAD_CLASS = Pattern.compile(leadClass); + + /* Phone number pattern allowing optional punctuation. */ + PATTERN = Pattern.compile( + "(?:" + leadClass + punctuation + ")" + leadLimit + + digitSequence + "(?:" + punctuation + digitSequence + ")" + blockLimit + + "(?:" + PhoneNumberUtil.EXTN_PATTERNS_FOR_MATCHING + ")?", + PhoneNumberUtil.REGEX_FLAGS); + } + + /** Returns a regular expression quantifier with an upper and lower limit. */ + private static String limit(int lower, int upper) { + if ((lower < 0) || (upper <= 0) || (upper < lower)) { + throw new IllegalArgumentException(); + } + return "{" + lower + "," + upper + "}"; + } + + /** The potential states of a PhoneNumberMatcher. */ + private enum State { + NOT_READY, READY, DONE + } + + /** The phone number utility. */ + private final PhoneNumberUtil phoneUtil; + /** The text searched for phone numbers. */ + private final CharSequence text; + /** + * The region (country) to assume for phone numbers without an international prefix, possibly + * null. + */ + private final String preferredRegion; + /** The degree of validation requested. */ + private final Leniency leniency; + /** The maximum number of retries after matching an invalid number. */ + private long maxTries; + + /** The iteration tristate. */ + private State state = State.NOT_READY; + /** The last successful match, null unless in {@link State#READY}. */ + private PhoneNumberMatch lastMatch = null; + /** The next index to start searching at. Undefined in {@link State#DONE}. */ + private int searchIndex = 0; + + // A cache for frequently used country-specific regular expressions. Set to 32 to cover ~2-3 + // countries being used for the same doc with ~10 patterns for each country. Some pages will have + // a lot more countries in use, but typically fewer numbers for each so expanding the cache for + // that use-case won't have a lot of benefit. + private final RegexCache regexCache = new RegexCache(32); + + /** + * Creates a new instance. See the factory methods in {@link PhoneNumberUtil} on how to obtain a + * new instance. + * + * @param util the phone number util to use + * @param text the character sequence that we will search, null for no text + * @param country the country to assume for phone numbers not written in international format + * (with a leading plus, or with the international dialing prefix of the specified region). + * May be null or "ZZ" if only numbers with a leading plus should be + * considered. + * @param leniency the leniency to use when evaluating candidate phone numbers + * @param maxTries the maximum number of invalid numbers to try before giving up on the text. + * This is to cover degenerate cases where the text has a lot of false positives in it. Must + * be {@code >= 0}. + */ + PhoneNumberMatcher(PhoneNumberUtil util, CharSequence text, String country, Leniency leniency, + long maxTries) { + + if ((util == null) || (leniency == null)) { + throw new NullPointerException(); + } + if (maxTries < 0) { + throw new IllegalArgumentException(); + } + this.phoneUtil = util; + this.text = (text != null) ? text : ""; + this.preferredRegion = country; + this.leniency = leniency; + this.maxTries = maxTries; + } + + /** + * Attempts to find the next subsequence in the searched sequence on or after {@code searchIndex} + * that represents a phone number. Returns the next match, null if none was found. + * + * @param index the search index to start searching at + * @return the phone number match found, null if none can be found + */ + private PhoneNumberMatch find(int index) { + Matcher matcher = PATTERN.matcher(text); + while ((maxTries > 0) && matcher.find(index)) { + int start = matcher.start(); + CharSequence candidate = text.subSequence(start, matcher.end()); + + // Check for extra numbers at the end. + // TODO: This is the place to start when trying to support extraction of multiple phone number + // from split notations (+41 79 123 45 67 / 68). + candidate = trimAfterFirstMatch(PhoneNumberUtil.SECOND_NUMBER_START_PATTERN, candidate); + + PhoneNumberMatch match = extractMatch(candidate, start); + if (match != null) { + return match; + } + + index = start + candidate.length(); + maxTries--; + } + + return null; + } + + /** + * Trims away any characters after the first match of {@code pattern} in {@code candidate}, + * returning the trimmed version. + */ + private static CharSequence trimAfterFirstMatch(Pattern pattern, CharSequence candidate) { + Matcher trailingCharsMatcher = pattern.matcher(candidate); + if (trailingCharsMatcher.find()) { + candidate = candidate.subSequence(0, trailingCharsMatcher.start()); + } + return candidate; + } + + /** + * Helper method to determine if a character is a Latin-script letter or not. For our purposes, + * combining marks should also return true since we assume they have been added to a preceding + * Latin character. + */ + // @VisibleForTesting + static boolean isLatinLetter(char letter) { + // Combining marks are a subset of non-spacing-mark. + if (!Character.isLetter(letter) && Character.getType(letter) != Character.NON_SPACING_MARK) { + return false; + } + UnicodeBlock block = UnicodeBlock.of(letter); + return block.equals(UnicodeBlock.BASIC_LATIN) + || block.equals(UnicodeBlock.LATIN_1_SUPPLEMENT) + || block.equals(UnicodeBlock.LATIN_EXTENDED_A) + || block.equals(UnicodeBlock.LATIN_EXTENDED_ADDITIONAL) + || block.equals(UnicodeBlock.LATIN_EXTENDED_B) + || block.equals(UnicodeBlock.COMBINING_DIACRITICAL_MARKS); + } + + private static boolean isInvalidPunctuationSymbol(char character) { + return character == '%' || Character.getType(character) == Character.CURRENCY_SYMBOL; + } + + /** + * Attempts to extract a match from a {@code candidate} character sequence. + * + * @param candidate the candidate text that might contain a phone number + * @param offset the offset of {@code candidate} within {@link #text} + * @return the match found, null if none can be found + */ + private PhoneNumberMatch extractMatch(CharSequence candidate, int offset) { + // Skip a match that is more likely to be a date. + if (SLASH_SEPARATED_DATES.matcher(candidate).find()) { + return null; + } + + // Skip potential time-stamps. + if (TIME_STAMPS.matcher(candidate).find()) { + String followingText = text.toString().substring(offset + candidate.length()); + if (TIME_STAMPS_SUFFIX.matcher(followingText).lookingAt()) { + return null; + } + } + + // Try to come up with a valid match given the entire candidate. + PhoneNumberMatch match = parseAndVerify(candidate, offset); + if (match != null) { + return match; + } + + // If that failed, try to find an "inner match" - there might be a phone number within this + // candidate. + return extractInnerMatch(candidate, offset); + } + + /** + * Attempts to extract a match from {@code candidate} if the whole candidate does not qualify as a + * match. + * + * @param candidate the candidate text that might contain a phone number + * @param offset the current offset of {@code candidate} within {@link #text} + * @return the match found, null if none can be found + */ + private PhoneNumberMatch extractInnerMatch(CharSequence candidate, int offset) { + for (Pattern possibleInnerMatch : INNER_MATCHES) { + Matcher groupMatcher = possibleInnerMatch.matcher(candidate); + boolean isFirstMatch = true; + while (groupMatcher.find() && maxTries > 0) { + if (isFirstMatch) { + // We should handle any group before this one too. + CharSequence group = trimAfterFirstMatch( + PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, + candidate.subSequence(0, groupMatcher.start())); + PhoneNumberMatch match = parseAndVerify(group, offset); + if (match != null) { + return match; + } + maxTries--; + isFirstMatch = false; + } + CharSequence group = trimAfterFirstMatch( + PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, groupMatcher.group(1)); + PhoneNumberMatch match = parseAndVerify(group, offset + groupMatcher.start(1)); + if (match != null) { + return match; + } + maxTries--; + } + } + return null; + } + + /** + * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and + * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a + * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null. + * + * @param candidate the candidate match + * @param offset the offset of {@code candidate} within {@link #text} + * @return the parsed and validated phone number match, or null + */ + private PhoneNumberMatch parseAndVerify(CharSequence candidate, int offset) { + try { + // Check the candidate doesn't contain any formatting which would indicate that it really + // isn't a phone number. + if (!MATCHING_BRACKETS.matcher(candidate).matches() || PUB_PAGES.matcher(candidate).find()) { + return null; + } + + // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded + // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def. + if (leniency.compareTo(Leniency.VALID) >= 0) { + // If the candidate is not at the start of the text, and does not start with phone-number + // punctuation, check the previous character. + if (offset > 0 && !LEAD_CLASS.matcher(candidate).lookingAt()) { + char previousChar = text.charAt(offset - 1); + // We return null if it is a latin letter or an invalid punctuation symbol. + if (isInvalidPunctuationSymbol(previousChar) || isLatinLetter(previousChar)) { + return null; + } + } + int lastCharIndex = offset + candidate.length(); + if (lastCharIndex < text.length()) { + char nextChar = text.charAt(lastCharIndex); + if (isInvalidPunctuationSymbol(nextChar) || isLatinLetter(nextChar)) { + return null; + } + } + } + + PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion); + + if (leniency.verify(number, candidate, phoneUtil, this)) { + // We used parseAndKeepRawInput to create this number, but for now we don't return the extra + // values parsed. TODO: stop clearing all values here and switch all users over + // to using rawInput() rather than the rawString() of PhoneNumberMatch. + number.clearCountryCodeSource(); + number.clearRawInput(); + number.clearPreferredDomesticCarrierCode(); + return new PhoneNumberMatch(offset, candidate.toString(), number); + } + } catch (NumberParseException e) { + // ignore and continue + } + return null; + } + + /** + * Small helper interface such that the number groups can be checked according to different + * criteria, both for our default way of performing formatting and for any alternate formats we + * may want to check. + */ + interface NumberGroupingChecker { + /** + * Returns true if the groups of digits found in our candidate phone number match our + * expectations. + * + * @param number the original number we found when parsing + * @param normalizedCandidate the candidate number, normalized to only contain ASCII digits, + * but with non-digits (spaces etc) retained + * @param expectedNumberGroups the groups of digits that we would expect to see if we + * formatted this number + */ + boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, String[] expectedNumberGroups); + } + + static boolean allNumberGroupsRemainGrouped(PhoneNumberUtil util, + PhoneNumber number, + StringBuilder normalizedCandidate, + String[] formattedNumberGroups) { + int fromIndex = 0; + if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + // First skip the country code if the normalized candidate contained it. + String countryCode = Integer.toString(number.getCountryCode()); + fromIndex = normalizedCandidate.indexOf(countryCode) + countryCode.length(); + } + // Check each group of consecutive digits are not broken into separate groupings in the + // {@code normalizedCandidate} string. + for (int i = 0; i < formattedNumberGroups.length; i++) { + // Fails if the substring of {@code normalizedCandidate} starting from {@code fromIndex} + // doesn't contain the consecutive digits in formattedNumberGroups[i]. + fromIndex = normalizedCandidate.indexOf(formattedNumberGroups[i], fromIndex); + if (fromIndex < 0) { + return false; + } + // Moves {@code fromIndex} forward. + fromIndex += formattedNumberGroups[i].length(); + if (i == 0 && fromIndex < normalizedCandidate.length()) { + // We are at the position right after the NDC. We get the region used for formatting + // information based on the country code in the phone number, rather than the number itself, + // as we do not need to distinguish between different countries with the same country + // calling code and this is faster. + String region = util.getRegionCodeForCountryCode(number.getCountryCode()); + if (util.getNddPrefixForRegion(region, true) != null + && Character.isDigit(normalizedCandidate.charAt(fromIndex))) { + // This means there is no formatting symbol after the NDC. In this case, we only + // accept the number if there is no formatting symbol at all in the number, except + // for extensions. This is only important for countries with national prefixes. + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + return normalizedCandidate.substring(fromIndex - formattedNumberGroups[i].length()) + .startsWith(nationalSignificantNumber); + } + } + } + // The check here makes sure that we haven't mistakenly already used the extension to + // match the last group of the subscriber number. Note the extension cannot have + // formatting in-between digits. + return normalizedCandidate.substring(fromIndex).contains(number.getExtension()); + } + + static boolean allNumberGroupsAreExactlyPresent(PhoneNumberUtil util, + PhoneNumber number, + StringBuilder normalizedCandidate, + String[] formattedNumberGroups) { + String[] candidateGroups = + PhoneNumberUtil.NON_DIGITS_PATTERN.split(normalizedCandidate.toString()); + // Set this to the last group, skipping it if the number has an extension. + int candidateNumberGroupIndex = + number.hasExtension() ? candidateGroups.length - 2 : candidateGroups.length - 1; + // First we check if the national significant number is formatted as a block. + // We use contains and not equals, since the national significant number may be present with + // a prefix such as a national number prefix, or the country code itself. + if (candidateGroups.length == 1 + || candidateGroups[candidateNumberGroupIndex].contains( + util.getNationalSignificantNumber(number))) { + return true; + } + // Starting from the end, go through in reverse, excluding the first group, and check the + // candidate and number groups are the same. + for (int formattedNumberGroupIndex = (formattedNumberGroups.length - 1); + formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0; + formattedNumberGroupIndex--, candidateNumberGroupIndex--) { + if (!candidateGroups[candidateNumberGroupIndex].equals( + formattedNumberGroups[formattedNumberGroupIndex])) { + return false; + } + } + // Now check the first group. There may be a national prefix at the start, so we only check + // that the candidate group ends with the formatted number group. + return (candidateNumberGroupIndex >= 0 + && candidateGroups[candidateNumberGroupIndex].endsWith(formattedNumberGroups[0])); + } + + /** + * Helper method to get the national-number part of a number, formatted without any national + * prefix, and return it as a set of digit blocks that would be formatted together following + * standard formatting rules. + */ + private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number) { + // This will be in the format +CC-DG1-DG2-DGX;ext=EXT where DG1..DGX represents groups of + // digits. + String rfc3966Format = util.format(number, PhoneNumberFormat.RFC3966); + // We remove the extension part from the formatted string before splitting it into different + // groups. + int endIndex = rfc3966Format.indexOf(';'); + if (endIndex < 0) { + endIndex = rfc3966Format.length(); + } + // The country-code will have a '-' following it. + int startIndex = rfc3966Format.indexOf('-') + 1; + return rfc3966Format.substring(startIndex, endIndex).split("-"); + } + + /** + * Helper method to get the national-number part of a number, formatted without any national + * prefix, and return it as a set of digit blocks that should be formatted together according to + * the formatting pattern passed in. + */ + private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number, + NumberFormat formattingPattern) { + // If a format is provided, we format the NSN only, and split that according to the separator. + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + return util.formatNsnUsingPattern(nationalSignificantNumber, + formattingPattern, PhoneNumberFormat.RFC3966).split("-"); + } + + boolean checkNumberGroupingIsValid( + PhoneNumber number, CharSequence candidate, PhoneNumberUtil util, + NumberGroupingChecker checker) { + StringBuilder normalizedCandidate = + PhoneNumberUtil.normalizeDigits(candidate, true /* keep non-digits */); + String[] formattedNumberGroups = getNationalNumberGroups(util, number); + if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { + return true; + } + // If this didn't pass, see if there are any alternate formats that match, and try them instead. + PhoneMetadata alternateFormats = + DefaultMetadataDependenciesProvider.getInstance() + .getAlternateFormatsMetadataSource() + .getFormattingMetadataForCountryCallingCode(number.getCountryCode()); + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + if (alternateFormats != null) { + for (NumberFormat alternateFormat : alternateFormats.getNumberFormatList()) { + if (alternateFormat.getLeadingDigitsPatternCount() > 0) { + // There is only one leading digits pattern for alternate formats. + Pattern pattern = + regexCache.getPatternForRegex(alternateFormat.getLeadingDigitsPattern(0)); + if (!pattern.matcher(nationalSignificantNumber).lookingAt()) { + // Leading digits don't match; try another one. + continue; + } + } + formattedNumberGroups = getNationalNumberGroups(util, number, alternateFormat); + if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { + return true; + } + } + } + return false; + } + + static boolean containsMoreThanOneSlashInNationalNumber(PhoneNumber number, String candidate) { + int firstSlashInBodyIndex = candidate.indexOf('/'); + if (firstSlashInBodyIndex < 0) { + // No slashes, this is okay. + return false; + } + // Now look for a second one. + int secondSlashInBodyIndex = candidate.indexOf('/', firstSlashInBodyIndex + 1); + if (secondSlashInBodyIndex < 0) { + // Only one slash, this is okay. + return false; + } + + // If the first slash is after the country calling code, this is permitted. + boolean candidateHasCountryCode = + (number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN + || number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); + if (candidateHasCountryCode + && PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(0, firstSlashInBodyIndex)) + .equals(Integer.toString(number.getCountryCode()))) { + // Any more slashes and this is illegal. + return candidate.substring(secondSlashInBodyIndex + 1).contains("/"); + } + return true; + } + + static boolean containsOnlyValidXChars( + PhoneNumber number, String candidate, PhoneNumberUtil util) { + // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the + // national significant number or (2) an extension sign, in which case they always precede the + // extension number. We assume a carrier code is more than 1 digit, so the first case has to + // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x' + // or 'X'. We ignore the character if it appears as the last character of the string. + for (int index = 0; index < candidate.length() - 1; index++) { + char charAtIndex = candidate.charAt(index); + if (charAtIndex == 'x' || charAtIndex == 'X') { + char charAtNextIndex = candidate.charAt(index + 1); + if (charAtNextIndex == 'x' || charAtNextIndex == 'X') { + // This is the carrier code case, in which the 'X's always precede the national + // significant number. + index++; + if (util.isNumberMatch(number, candidate.substring(index)) != MatchType.NSN_MATCH) { + return false; + } + // This is the extension sign case, in which the 'x' or 'X' should always precede the + // extension number. + } else if (!PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(index)).equals( + number.getExtension())) { + return false; + } + } + } + return true; + } + + static boolean isNationalPrefixPresentIfRequired(PhoneNumber number, PhoneNumberUtil util) { + // First, check how we deduced the country code. If it was written in international format, then + // the national prefix is not required. + if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + return true; + } + String phoneNumberRegion = + util.getRegionCodeForCountryCode(number.getCountryCode()); + PhoneMetadata metadata = util.getMetadataForRegion(phoneNumberRegion); + if (metadata == null) { + return true; + } + // Check if a national prefix should be present when formatting this number. + String nationalNumber = util.getNationalSignificantNumber(number); + NumberFormat formatRule = + util.chooseFormattingPatternForNumber(metadata.getNumberFormatList(), nationalNumber); + // To do this, we check that a national prefix formatting rule was present and that it wasn't + // just the first-group symbol ($1) with punctuation. + if ((formatRule != null) && formatRule.getNationalPrefixFormattingRule().length() > 0) { + if (formatRule.getNationalPrefixOptionalWhenFormatting()) { + // The national-prefix is optional in these cases, so we don't need to check if it was + // present. + return true; + } + if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + formatRule.getNationalPrefixFormattingRule())) { + // National Prefix not needed for this number. + return true; + } + // Normalize the remainder. + String rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput()); + StringBuilder rawInput = new StringBuilder(rawInputCopy); + // Check if we found a national prefix and/or carrier code at the start of the raw input, and + // return the result. + return util.maybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null); + } + return true; + } + + @Override + public boolean hasNext() { + if (state == State.NOT_READY) { + lastMatch = find(searchIndex); + if (lastMatch == null) { + state = State.DONE; + } else { + searchIndex = lastMatch.end(); + state = State.READY; + } + } + return state == State.READY; + } + + @Override + public PhoneNumberMatch next() { + // Check the state and find the next match as a side-effect if necessary. + if (!hasNext()) { + throw new NoSuchElementException(); + } + + // Don't retain that memory any longer than necessary. + PhoneNumberMatch result = lastMatch; + lastMatch = null; + state = State.NOT_READY; + return result; + } + + /** + * Always throws {@link UnsupportedOperationException} as removal is not supported. + */ + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java new file mode 100644 index 0000000000..fd8f1a3067 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -0,0 +1,3683 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; +import com.google.i18n.phonenumbers.internal.MatcherApi; +import com.google.i18n.phonenumbers.internal.RegexBasedMatcher; +import com.google.i18n.phonenumbers.internal.RegexCache; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.MetadataSource; +import com.google.i18n.phonenumbers.metadata.source.MetadataSourceImpl; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility for international phone numbers. Functionality includes formatting, parsing and + * validation. + * + *

If you use this library, and want to be notified about important changes, please sign up to + * our mailing list. + * + * NOTE: A lot of methods in this class require Region Code strings. These must be provided using + * CLDR two-letter region-code format. These should be in upper-case. The list of the codes + * can be found here: + * http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html + */ +public class PhoneNumberUtil { + private static final Logger logger = Logger.getLogger(PhoneNumberUtil.class.getName()); + + /** Flags to use when compiling regular expressions for phone numbers. */ + static final int REGEX_FLAGS = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; + // The minimum and maximum length of the national significant number. + private static final int MIN_LENGTH_FOR_NSN = 2; + // The ITU says the maximum length should be 15, but we have found longer numbers in Germany. + static final int MAX_LENGTH_FOR_NSN = 17; + // The maximum length of the country calling code. + static final int MAX_LENGTH_COUNTRY_CODE = 3; + // We don't allow input strings for parsing to be longer than 250 chars. This prevents malicious + // input from overflowing the regular-expression engine. + private static final int MAX_INPUT_STRING_LENGTH = 250; + + // Region-code for the unknown region. + private static final String UNKNOWN_REGION = "ZZ"; + + private static final int NANPA_COUNTRY_CODE = 1; + + // Map of country calling codes that use a mobile token before the area code. One example of when + // this is relevant is when determining the length of the national destination code, which should + // be the length of the area code plus the length of the mobile token. + private static final Map MOBILE_TOKEN_MAPPINGS; + + // Set of country codes that have geographically assigned mobile numbers (see GEO_MOBILE_COUNTRIES + // below) which are not based on *area codes*. For example, in China mobile numbers start with a + // carrier indicator, and beyond that are geographically assigned: this carrier indicator is not + // considered to be an area code. + private static final Set GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES; + + // Set of country codes that doesn't have national prefix, but it has area codes. + private static final Set COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES; + + // Set of country calling codes that have geographically assigned mobile numbers. This may not be + // complete; we add calling codes case by case, as we find geographical mobile numbers or hear + // from user reports. Note that countries like the US, where we can't distinguish between + // fixed-line or mobile numbers, are not listed here, since we consider FIXED_LINE_OR_MOBILE to be + // a possibly geographically-related type anyway (like FIXED_LINE). + private static final Set GEO_MOBILE_COUNTRIES; + + // The PLUS_SIGN signifies the international prefix. + static final char PLUS_SIGN = '+'; + + private static final char STAR_SIGN = '*'; + + private static final String RFC3966_EXTN_PREFIX = ";ext="; + private static final String RFC3966_PREFIX = "tel:"; + private static final String RFC3966_PHONE_CONTEXT = ";phone-context="; + private static final String RFC3966_ISDN_SUBADDRESS = ";isub="; + + // A map that contains characters that are essential when dialling. That means any of the + // characters in this map must not be removed from a number when dialling, otherwise the call + // will not reach the intended destination. + private static final Map DIALLABLE_CHAR_MAPPINGS; + + // Only upper-case variants of alpha characters are stored. + private static final Map ALPHA_MAPPINGS; + + // For performance reasons, amalgamate both into one map. + private static final Map ALPHA_PHONE_MAPPINGS; + + // Separate map of all symbols that we wish to retain when formatting alpha numbers. This + // includes digits, ASCII letters and number grouping symbols such as "-" and " ". + private static final Map ALL_PLUS_NUMBER_GROUPING_SYMBOLS; + + static { + HashMap mobileTokenMap = new HashMap<>(); + mobileTokenMap.put(54, "9"); + MOBILE_TOKEN_MAPPINGS = Collections.unmodifiableMap(mobileTokenMap); + + HashSet geoMobileCountriesWithoutMobileAreaCodes = new HashSet<>(); + geoMobileCountriesWithoutMobileAreaCodes.add(86); // China + GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES = + Collections.unmodifiableSet(geoMobileCountriesWithoutMobileAreaCodes); + + HashSet countriesWithoutNationalPrefixWithAreaCodes = new HashSet<>(); + countriesWithoutNationalPrefixWithAreaCodes.add(52); // Mexico + COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES = + Collections.unmodifiableSet(countriesWithoutNationalPrefixWithAreaCodes); + + HashSet geoMobileCountries = new HashSet<>(); + geoMobileCountries.add(52); // Mexico + geoMobileCountries.add(54); // Argentina + geoMobileCountries.add(55); // Brazil + geoMobileCountries.add(62); // Indonesia: some prefixes only (fixed CMDA wireless) + geoMobileCountries.addAll(geoMobileCountriesWithoutMobileAreaCodes); + GEO_MOBILE_COUNTRIES = Collections.unmodifiableSet(geoMobileCountries); + + // Simple ASCII digits map used to populate ALPHA_PHONE_MAPPINGS and + // ALL_PLUS_NUMBER_GROUPING_SYMBOLS. + HashMap asciiDigitMappings = new HashMap<>(); + asciiDigitMappings.put('0', '0'); + asciiDigitMappings.put('1', '1'); + asciiDigitMappings.put('2', '2'); + asciiDigitMappings.put('3', '3'); + asciiDigitMappings.put('4', '4'); + asciiDigitMappings.put('5', '5'); + asciiDigitMappings.put('6', '6'); + asciiDigitMappings.put('7', '7'); + asciiDigitMappings.put('8', '8'); + asciiDigitMappings.put('9', '9'); + + HashMap alphaMap = new HashMap<>(40); + alphaMap.put('A', '2'); + alphaMap.put('B', '2'); + alphaMap.put('C', '2'); + alphaMap.put('D', '3'); + alphaMap.put('E', '3'); + alphaMap.put('F', '3'); + alphaMap.put('G', '4'); + alphaMap.put('H', '4'); + alphaMap.put('I', '4'); + alphaMap.put('J', '5'); + alphaMap.put('K', '5'); + alphaMap.put('L', '5'); + alphaMap.put('M', '6'); + alphaMap.put('N', '6'); + alphaMap.put('O', '6'); + alphaMap.put('P', '7'); + alphaMap.put('Q', '7'); + alphaMap.put('R', '7'); + alphaMap.put('S', '7'); + alphaMap.put('T', '8'); + alphaMap.put('U', '8'); + alphaMap.put('V', '8'); + alphaMap.put('W', '9'); + alphaMap.put('X', '9'); + alphaMap.put('Y', '9'); + alphaMap.put('Z', '9'); + ALPHA_MAPPINGS = Collections.unmodifiableMap(alphaMap); + + HashMap combinedMap = new HashMap<>(100); + combinedMap.putAll(ALPHA_MAPPINGS); + combinedMap.putAll(asciiDigitMappings); + ALPHA_PHONE_MAPPINGS = Collections.unmodifiableMap(combinedMap); + + HashMap diallableCharMap = new HashMap<>(); + diallableCharMap.putAll(asciiDigitMappings); + diallableCharMap.put(PLUS_SIGN, PLUS_SIGN); + diallableCharMap.put('*', '*'); + diallableCharMap.put('#', '#'); + DIALLABLE_CHAR_MAPPINGS = Collections.unmodifiableMap(diallableCharMap); + + HashMap allPlusNumberGroupings = new HashMap<>(); + // Put (lower letter -> upper letter) and (upper letter -> upper letter) mappings. + for (char c : ALPHA_MAPPINGS.keySet()) { + allPlusNumberGroupings.put(Character.toLowerCase(c), c); + allPlusNumberGroupings.put(c, c); + } + allPlusNumberGroupings.putAll(asciiDigitMappings); + // Put grouping symbols. + allPlusNumberGroupings.put('-', '-'); + allPlusNumberGroupings.put('\uFF0D', '-'); + allPlusNumberGroupings.put('\u2010', '-'); + allPlusNumberGroupings.put('\u2011', '-'); + allPlusNumberGroupings.put('\u2012', '-'); + allPlusNumberGroupings.put('\u2013', '-'); + allPlusNumberGroupings.put('\u2014', '-'); + allPlusNumberGroupings.put('\u2015', '-'); + allPlusNumberGroupings.put('\u2212', '-'); + allPlusNumberGroupings.put('/', '/'); + allPlusNumberGroupings.put('\uFF0F', '/'); + allPlusNumberGroupings.put(' ', ' '); + allPlusNumberGroupings.put('\u3000', ' '); + allPlusNumberGroupings.put('\u2060', ' '); + allPlusNumberGroupings.put('.', '.'); + allPlusNumberGroupings.put('\uFF0E', '.'); + ALL_PLUS_NUMBER_GROUPING_SYMBOLS = Collections.unmodifiableMap(allPlusNumberGroupings); + } + + // Pattern that makes it easy to distinguish whether a region has a single international dialing + // prefix or not. If a region has a single international prefix (e.g. 011 in USA), it will be + // represented as a string that contains a sequence of ASCII digits, and possibly a tilde, which + // signals waiting for the tone. If there are multiple available international prefixes in a + // region, they will be represented as a regex string that always contains one or more characters + // that are not ASCII digits or a tilde. + private static final Pattern SINGLE_INTERNATIONAL_PREFIX = + Pattern.compile("[\\d]+(?:[~\u2053\u223C\uFF5E][\\d]+)?"); + + // Regular expression of acceptable punctuation found in phone numbers, used to find numbers in + // text and to decide what is a viable phone number. This excludes diallable characters. + // This consists of dash characters, white space characters, full stops, slashes, + // square brackets, parentheses and tildes. It also includes the letter 'x' as that is found as a + // placeholder for carrier information in some phone numbers. Full-width variants are also + // present. + static final String VALID_PUNCTUATION = "-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F " + + "\u00A0\u00AD\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E"; + + private static final String DIGITS = "\\p{Nd}"; + // We accept alpha characters in phone numbers, ASCII only, upper and lower case. + private static final String VALID_ALPHA = + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).replaceAll("[, \\[\\]]", "") + + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()) + .toLowerCase().replaceAll("[, \\[\\]]", ""); + static final String PLUS_CHARS = "+\uFF0B"; + static final Pattern PLUS_CHARS_PATTERN = Pattern.compile("[" + PLUS_CHARS + "]+"); + private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[" + VALID_PUNCTUATION + "]+"); + private static final Pattern CAPTURING_DIGIT_PATTERN = Pattern.compile("(" + DIGITS + ")"); + + // Regular expression of acceptable characters that may start a phone number for the purposes of + // parsing. This allows us to strip away meaningless prefixes to phone numbers that may be + // mistakenly given to us. This consists of digits, the plus symbol and arabic-indic digits. This + // does not contain alpha characters, although they may be used later in the number. It also does + // not include other punctuation, as this will be stripped later during parsing and is of no + // information value when parsing a number. + private static final String VALID_START_CHAR = "[" + PLUS_CHARS + DIGITS + "]"; + private static final Pattern VALID_START_CHAR_PATTERN = Pattern.compile(VALID_START_CHAR); + + // Regular expression of characters typically used to start a second phone number for the purposes + // of parsing. This allows us to strip off parts of the number that are actually the start of + // another number, such as for: (530) 583-6985 x302/x2303 -> the second extension here makes this + // actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second + // extension so that the first number is parsed correctly. + private static final String SECOND_NUMBER_START = "[\\\\/] *x"; + static final Pattern SECOND_NUMBER_START_PATTERN = Pattern.compile(SECOND_NUMBER_START); + + // Regular expression of trailing characters that we want to remove. We remove all characters that + // are not alpha or numerical characters. The hash character is retained here, as it may signify + // the previous block was an extension. + private static final String UNWANTED_END_CHARS = "[[\\P{N}&&\\P{L}]&&[^#]]+$"; + static final Pattern UNWANTED_END_CHAR_PATTERN = Pattern.compile(UNWANTED_END_CHARS); + + // We use this pattern to check if the phone number has at least three letters in it - if so, then + // we treat it as a number where some phone-number digits are represented by letters. + private static final Pattern VALID_ALPHA_PHONE_PATTERN = Pattern.compile("(?:.*?[A-Za-z]){3}.*"); + + // Regular expression of viable phone numbers. This is location independent. Checks we have at + // least three leading digits, and only valid punctuation, alpha characters and + // digits in the phone number. Does not include extension data. + // The symbol 'x' is allowed here as valid punctuation since it is often used as a placeholder for + // carrier codes, for example in Brazilian phone numbers. We also allow multiple "+" characters at + // the start. + // Corresponds to the following: + // [digits]{minLengthNsn}| + // plus_sign*(([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])* + // + // The first reg-ex is to allow short numbers (two digits long) to be parsed if they are entered + // as "15" etc, but only if there is no punctuation in them. The second expression restricts the + // number of digits to three or more, but then allows them to be in international form, and to + // have alpha-characters and punctuation. + // + // Note VALID_PUNCTUATION starts with a -, so must be the first in the range. + private static final String VALID_PHONE_NUMBER = + DIGITS + "{" + MIN_LENGTH_FOR_NSN + "}" + "|" + + "[" + PLUS_CHARS + "]*+(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" + + VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*"; + + // Default extension prefix to use when formatting. This will be put in front of any extension + // component of the number, after the main national number is formatted. For example, if you wish + // the default extension formatting to be " extn: 3456", then you should specify " extn: " here + // as the default extension prefix. This can be overridden by region-specific preferences. + private static final String DEFAULT_EXTN_PREFIX = " ext. "; + + // Regexp of all possible ways to write extensions, for use when parsing. This will be run as a + // case-insensitive regexp match. Wide character versions are also provided after each ASCII + // version. + private static final String EXTN_PATTERNS_FOR_PARSING = createExtnPattern(true); + static final String EXTN_PATTERNS_FOR_MATCHING = createExtnPattern(false); + + // Regular expression of valid global-number-digits for the phone-context parameter, following the + // syntax defined in RFC3966. + private static final String RFC3966_VISUAL_SEPARATOR = "[\\-\\.\\(\\)]?"; + private static final String RFC3966_PHONE_DIGIT = + "(" + DIGITS + "|" + RFC3966_VISUAL_SEPARATOR + ")"; + private static final String RFC3966_GLOBAL_NUMBER_DIGITS = + "^\\" + PLUS_SIGN + RFC3966_PHONE_DIGIT + "*" + DIGITS + RFC3966_PHONE_DIGIT + "*$"; + static final Pattern RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN = + Pattern.compile(RFC3966_GLOBAL_NUMBER_DIGITS); + + // Regular expression of valid domainname for the phone-context parameter, following the syntax + // defined in RFC3966. + private static final String ALPHANUM = VALID_ALPHA + DIGITS; + private static final String RFC3966_DOMAINLABEL = + "[" + ALPHANUM + "]+((\\-)*[" + ALPHANUM + "])*"; + private static final String RFC3966_TOPLABEL = + "[" + VALID_ALPHA + "]+((\\-)*[" + ALPHANUM + "])*"; + private static final String RFC3966_DOMAINNAME = + "^(" + RFC3966_DOMAINLABEL + "\\.)*" + RFC3966_TOPLABEL + "\\.?$"; + static final Pattern RFC3966_DOMAINNAME_PATTERN = Pattern.compile(RFC3966_DOMAINNAME); + + /** + * Helper method for constructing regular expressions for parsing. Creates an expression that + * captures up to maxLength digits. + */ + private static String extnDigits(int maxLength) { + return "(" + DIGITS + "{1," + maxLength + "})"; + } + + /** + * Helper initialiser method to create the regular-expression pattern to match extensions. + * Note that there are currently six capturing groups for the extension itself. If this number is + * changed, MaybeStripExtension needs to be updated. + */ + private static String createExtnPattern(boolean forParsing) { + // We cap the maximum length of an extension based on the ambiguity of the way the extension is + // prefixed. As per ITU, the officially allowed length for extensions is actually 40, but we + // don't support this since we haven't seen real examples and this introduces many false + // interpretations as the extension labels are not standardized. + int extLimitAfterExplicitLabel = 20; + int extLimitAfterLikelyLabel = 15; + int extLimitAfterAmbiguousChar = 9; + int extLimitWhenNotSure = 6; + + String possibleSeparatorsBetweenNumberAndExtLabel = "[ \u00A0\\t,]*"; + // Optional full stop (.) or colon, followed by zero or more spaces/tabs/commas. + String possibleCharsAfterExtLabel = "[:\\.\uFF0E]?[ \u00A0\\t,-]*"; + String optionalExtnSuffix = "#?"; + + // Here the extension is called out in more explicit way, i.e mentioning it obvious patterns + // like "ext.". Canonical-equivalence doesn't seem to be an option with Android java, so we + // allow two options for representing the accented o - the character itself, and one in the + // unicode decomposed form with the combining acute accent. + String explicitExtLabels = + "(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|\u0434\u043E\u0431|anexo)"; + // One-character symbols that can be used to indicate an extension, and less commonly used + // or more ambiguous extension labels. + String ambiguousExtLabels = "(?:[x\uFF58#\uFF03~\uFF5E]|int|\uFF49\uFF4E\uFF54)"; + // When extension is not separated clearly. + String ambiguousSeparator = "[- ]+"; + + String rfcExtn = RFC3966_EXTN_PREFIX + extnDigits(extLimitAfterExplicitLabel); + String explicitExtn = possibleSeparatorsBetweenNumberAndExtLabel + explicitExtLabels + + possibleCharsAfterExtLabel + extnDigits(extLimitAfterExplicitLabel) + + optionalExtnSuffix; + String ambiguousExtn = possibleSeparatorsBetweenNumberAndExtLabel + ambiguousExtLabels + + possibleCharsAfterExtLabel + extnDigits(extLimitAfterAmbiguousChar) + optionalExtnSuffix; + String americanStyleExtnWithSuffix = ambiguousSeparator + extnDigits(extLimitWhenNotSure) + "#"; + + // The first regular expression covers RFC 3966 format, where the extension is added using + // ";ext=". The second more generic where extension is mentioned with explicit labels like + // "ext:". In both the above cases we allow more numbers in extension than any other extension + // labels. The third one captures when single character extension labels or less commonly used + // labels are used. In such cases we capture fewer extension digits in order to reduce the + // chance of falsely interpreting two numbers beside each other as a number + extension. The + // fourth one covers the special case of American numbers where the extension is written with a + // hash at the end, such as "- 503#". + String extensionPattern = + rfcExtn + "|" + + explicitExtn + "|" + + ambiguousExtn + "|" + + americanStyleExtnWithSuffix; + // Additional pattern that is supported when parsing extensions, not when matching. + if (forParsing) { + // This is same as possibleSeparatorsBetweenNumberAndExtLabel, but not matching comma as + // extension label may have it. + String possibleSeparatorsNumberExtLabelNoComma = "[ \u00A0\\t]*"; + // ",," is commonly used for auto dialling the extension when connected. First comma is matched + // through possibleSeparatorsBetweenNumberAndExtLabel, so we do not repeat it here. Semi-colon + // works in Iphone and Android also to pop up a button with the extension number following. + String autoDiallingAndExtLabelsFound = "(?:,{2}|;)"; + + String autoDiallingExtn = possibleSeparatorsNumberExtLabelNoComma + + autoDiallingAndExtLabelsFound + possibleCharsAfterExtLabel + + extnDigits(extLimitAfterLikelyLabel) + optionalExtnSuffix; + String onlyCommasExtn = possibleSeparatorsNumberExtLabelNoComma + + "(?:,)+" + possibleCharsAfterExtLabel + extnDigits(extLimitAfterAmbiguousChar) + + optionalExtnSuffix; + // Here the first pattern is exclusively for extension autodialling formats which are used + // when dialling and in this case we accept longer extensions. However, the second pattern + // is more liberal on the number of commas that acts as extension labels, so we have a strict + // cap on the number of digits in such extensions. + return extensionPattern + "|" + + autoDiallingExtn + "|" + + onlyCommasExtn; + } + return extensionPattern; + } + + // Regexp of all known extension prefixes used by different regions followed by 1 or more valid + // digits, for use when parsing. + private static final Pattern EXTN_PATTERN = + Pattern.compile("(?:" + EXTN_PATTERNS_FOR_PARSING + ")$", REGEX_FLAGS); + + // We append optionally the extension pattern to the end here, as a valid phone number may + // have an extension prefix appended, followed by 1 or more digits. + private static final Pattern VALID_PHONE_NUMBER_PATTERN = + Pattern.compile(VALID_PHONE_NUMBER + "(?:" + EXTN_PATTERNS_FOR_PARSING + ")?", REGEX_FLAGS); + + static final Pattern NON_DIGITS_PATTERN = Pattern.compile("(\\D+)"); + + // The FIRST_GROUP_PATTERN was originally set to $1 but there are some countries for which the + // first group is not used in the national pattern (e.g. Argentina) so the $1 group does not match + // correctly. Therefore, we use \d, so that the first group actually used in the pattern will be + // matched. + private static final Pattern FIRST_GROUP_PATTERN = Pattern.compile("(\\$\\d)"); + // Constants used in the formatting rules to represent the national prefix, first group and + // carrier code respectively. + private static final String NP_STRING = "$NP"; + private static final String FG_STRING = "$FG"; + private static final String CC_STRING = "$CC"; + + // A pattern that is used to determine if the national prefix formatting rule has the first group + // only, i.e., does not start with the national prefix. Note that the pattern explicitly allows + // for unbalanced parentheses. + private static final Pattern FIRST_GROUP_ONLY_PREFIX_PATTERN = Pattern.compile("\\(?\\$1\\)?"); + + private static PhoneNumberUtil instance = null; + + public static final String REGION_CODE_FOR_NON_GEO_ENTITY = "001"; + + /** + * INTERNATIONAL and NATIONAL formats are consistent with the definition in ITU-T Recommendation + * E.123. However we follow local conventions such as using '-' instead of whitespace as + * separators. For example, the number of the Google Switzerland office will be written as + * "+41 44 668 1800" in INTERNATIONAL format, and as "044 668 1800" in NATIONAL format. E164 + * format is as per INTERNATIONAL format but with no formatting applied, e.g. "+41446681800". + * RFC3966 is as per INTERNATIONAL format, but with all spaces and other separating symbols + * replaced with a hyphen, and with any phone number extension appended with ";ext=". It also + * will have a prefix of "tel:" added, e.g. "tel:+41-44-668-1800". + * + * Note: If you are considering storing the number in a neutral format, you are highly advised to + * use the PhoneNumber class. + */ + public enum PhoneNumberFormat { + E164, + INTERNATIONAL, + NATIONAL, + RFC3966 + } + + /** + * Type of phone numbers. + */ + public enum PhoneNumberType { + FIXED_LINE, + MOBILE, + // In some regions (e.g. the USA), it is impossible to distinguish between fixed-line and + // mobile numbers by looking at the phone number itself. + FIXED_LINE_OR_MOBILE, + // Freephone lines + TOLL_FREE, + PREMIUM_RATE, + // The cost of this call is shared between the caller and the recipient, and is hence typically + // less than PREMIUM_RATE calls. See // http://en.wikipedia.org/wiki/Shared_Cost_Service for + // more information. + SHARED_COST, + // Voice over IP numbers. This includes TSoIP (Telephony Service over IP). + VOIP, + // A personal number is associated with a particular person, and may be routed to either a + // MOBILE or FIXED_LINE number. Some more information can be found here: + // http://en.wikipedia.org/wiki/Personal_Numbers + PERSONAL_NUMBER, + PAGER, + // Used for "Universal Access Numbers" or "Company Numbers". They may be further routed to + // specific offices, but allow one number to be used for a company. + UAN, + // Used for "Voice Mail Access Numbers". + VOICEMAIL, + // A phone number is of type UNKNOWN when it does not fit any of the known patterns for a + // specific region. + UNKNOWN + } + + /** + * Types of phone number matches. See detailed description beside the isNumberMatch() method. + */ + public enum MatchType { + NOT_A_NUMBER, + NO_MATCH, + SHORT_NSN_MATCH, + NSN_MATCH, + EXACT_MATCH, + } + + /** + * Possible outcomes when testing if a PhoneNumber is possible. + */ + public enum ValidationResult { + /** The number length matches that of valid numbers for this region. */ + IS_POSSIBLE, + /** + * The number length matches that of local numbers for this region only (i.e. numbers that may + * be able to be dialled within an area, but do not have all the information to be dialled from + * anywhere inside or outside the country). + */ + IS_POSSIBLE_LOCAL_ONLY, + /** The number has an invalid country calling code. */ + INVALID_COUNTRY_CODE, + /** The number is shorter than all valid numbers for this region. */ + TOO_SHORT, + /** + * The number is longer than the shortest valid numbers for this region, shorter than the + * longest valid numbers for this region, and does not itself have a number length that matches + * valid numbers for this region. This can also be returned in the case where + * isPossibleNumberForTypeWithReason was called, and there are no numbers of this type at all + * for this region. + */ + INVALID_LENGTH, + /** The number is longer than all valid numbers for this region. */ + TOO_LONG, + } + + /** + * Leniency when {@linkplain PhoneNumberUtil#findNumbers finding} potential phone numbers in text + * segments. The levels here are ordered in increasing strictness. + */ + public enum Leniency { + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber) + * possible}, but not necessarily {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}. + */ + POSSIBLE { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + return util.isPossibleNumber(number); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber) + * possible} and {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}. Numbers written + * in national format must have their national-prefix present if it is usually written for a + * number of this type. + */ + VALID { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate.toString(), util)) { + return false; + } + return PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and + * are grouped in a possible way for this locale. For example, a US number written as + * "65 02 53 00 00" and "650253 0000" are not accepted at this leniency level, whereas + * "650 253 0000", "650 2530000" or "6502530000" are. + * Numbers with more than one '/' symbol in the national significant number are also dropped at + * this level. + *

+ * Warning: This level might result in lower coverage especially for regions outside of country + * code "+1". If you are not sure about which level to use, email the discussion group + * libphonenumber-discuss@googlegroups.com. + */ + STRICT_GROUPING { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + String candidateString = candidate.toString(); + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + return matcher.checkNumberGroupingIsValid( + number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() { + @Override + public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, + String[] expectedNumberGroups) { + return PhoneNumberMatcher.allNumberGroupsRemainGrouped( + util, number, normalizedCandidate, expectedNumberGroups); + } + }); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and + * are grouped in the same way that we would have formatted it, or as a single block. For + * example, a US number written as "650 2530000" is not accepted at this leniency level, whereas + * "650 253 0000" or "6502530000" are. + * Numbers with more than one '/' symbol are also dropped at this level. + *

+ * Warning: This level might result in lower coverage especially for regions outside of country + * code "+1". If you are not sure about which level to use, email the discussion group + * libphonenumber-discuss@googlegroups.com. + */ + EXACT_GROUPING { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + String candidateString = candidate.toString(); + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + return matcher.checkNumberGroupingIsValid( + number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() { + @Override + public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, + String[] expectedNumberGroups) { + return PhoneNumberMatcher.allNumberGroupsAreExactlyPresent( + util, number, normalizedCandidate, expectedNumberGroups); + } + }); + } + }; + + /** Returns true if {@code number} is a verified number according to this leniency. */ + abstract boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher); + } + + // A source of metadata for different regions. + private final MetadataSource metadataSource; + + // A mapping from a country calling code to the region codes which denote the region represented + // by that country calling code. In the case of multiple regions sharing a calling code, such as + // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be + // first. + private final Map> countryCallingCodeToRegionCodeMap; + + // An API for validation checking. + private final MatcherApi matcherApi = RegexBasedMatcher.create(); + + // The set of regions that share country calling code 1. + // There are roughly 26 regions. + // We set the initial capacity of the HashSet to 35 to offer a load factor of roughly 0.75. + private final Set nanpaRegions = new HashSet<>(35); + + // A cache for frequently used region-specific regular expressions. + // The initial capacity is set to 100 as this seems to be an optimal value for Android, based on + // performance measurements. + private final RegexCache regexCache = new RegexCache(100); + + // The set of regions the library supports. + // There are roughly 240 of them and we set the initial capacity of the HashSet to 320 to offer a + // load factor of roughly 0.75. + private final Set supportedRegions = new HashSet<>(320); + + // The set of country calling codes that map to the non-geo entity region ("001"). This set + // currently contains < 12 elements so the default capacity of 16 (load factor=0.75) is fine. + private final Set countryCodesForNonGeographicalRegion = new HashSet<>(); + + /** + * This class implements a singleton, the constructor is only visible to facilitate testing. + */ + // @VisibleForTesting + PhoneNumberUtil(MetadataSource metadataSource, + Map> countryCallingCodeToRegionCodeMap) { + this.metadataSource = metadataSource; + this.countryCallingCodeToRegionCodeMap = countryCallingCodeToRegionCodeMap; + for (Map.Entry> entry : countryCallingCodeToRegionCodeMap.entrySet()) { + List regionCodes = entry.getValue(); + // We can assume that if the country calling code maps to the non-geo entity region code then + // that's the only region code it maps to. + if (regionCodes.size() == 1 && REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCodes.get(0))) { + // This is the subset of all country codes that map to the non-geo entity region code. + countryCodesForNonGeographicalRegion.add(entry.getKey()); + } else { + // The supported regions set does not include the "001" non-geo entity region code. + supportedRegions.addAll(regionCodes); + } + } + // If the non-geo entity still got added to the set of supported regions it must be because + // there are entries that list the non-geo entity alongside normal regions (which is wrong). + // If we discover this, remove the non-geo entity from the set of supported regions and log. + if (supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY)) { + logger.log(Level.WARNING, "invalid metadata (country calling code was mapped to the non-geo " + + "entity as well as specific region(s))"); + } + nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE)); + } + + /** + * Attempts to extract a possible number from the string passed in. This currently strips all + * leading characters that cannot be used to start a phone number. Characters that can be used to + * start a phone number are defined in the VALID_START_CHAR_PATTERN. If none of these characters + * are found in the number passed in, an empty string is returned. This function also attempts to + * strip off any alternative extensions or endings if two or more are present, such as in the case + * of: (530) 583-6985 x302/x2303. The second extension here makes this actually two phone numbers, + * (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second extension so that the first + * number is parsed correctly. + * + * @param number the string that might contain a phone number + * @return the number, stripped of any non-phone-number prefix (such as "Tel:") or an empty + * string if no character used to start phone numbers (such as + or any digit) is found in the + * number + */ + static CharSequence extractPossibleNumber(CharSequence number) { + Matcher m = VALID_START_CHAR_PATTERN.matcher(number); + if (m.find()) { + number = number.subSequence(m.start(), number.length()); + // Remove trailing non-alpha non-numerical characters. + Matcher trailingCharsMatcher = UNWANTED_END_CHAR_PATTERN.matcher(number); + if (trailingCharsMatcher.find()) { + number = number.subSequence(0, trailingCharsMatcher.start()); + } + // Check for extra numbers at the end. + Matcher secondNumber = SECOND_NUMBER_START_PATTERN.matcher(number); + if (secondNumber.find()) { + number = number.subSequence(0, secondNumber.start()); + } + return number; + } else { + return ""; + } + } + + /** + * Checks to see if the string of characters could possibly be a phone number at all. At the + * moment, checks to see that the string begins with at least 2 digits, ignoring any punctuation + * commonly found in phone numbers. + * This method does not require the number to be normalized in advance - but does assume that + * leading non-number symbols have been removed, such as by the method extractPossibleNumber. + * + * @param number string to be checked for viability as a phone number + * @return true if the number could be a phone number of some sort, otherwise false + */ + // @VisibleForTesting + static boolean isViablePhoneNumber(CharSequence number) { + if (number.length() < MIN_LENGTH_FOR_NSN) { + return false; + } + Matcher m = VALID_PHONE_NUMBER_PATTERN.matcher(number); + return m.matches(); + } + + /** + * Normalizes a string of characters representing a phone number. This performs the following + * conversions: + * - Punctuation is stripped. + * For ALPHA/VANITY numbers: + * - Letters are converted to their numeric representation on a telephone keypad. The keypad + * used here is the one defined in ITU Recommendation E.161. This is only done if there are 3 + * or more letters in the number, to lessen the risk that such letters are typos. + * For other numbers: + * - Wide-ascii digits are converted to normal ASCII (European) digits. + * - Arabic-Indic numerals are converted to European numerals. + * - Spurious alpha characters are stripped. + * + * @param number a StringBuilder of characters representing a phone number that will be + * normalized in place + */ + static StringBuilder normalize(StringBuilder number) { + Matcher m = VALID_ALPHA_PHONE_PATTERN.matcher(number); + if (m.matches()) { + number.replace(0, number.length(), normalizeHelper(number, ALPHA_PHONE_MAPPINGS, true)); + } else { + number.replace(0, number.length(), normalizeDigitsOnly(number)); + } + return number; + } + + /** + * Normalizes a string of characters representing a phone number. This converts wide-ascii and + * arabic-indic numerals to European numerals, and strips punctuation and alpha characters. + * + * @param number a string of characters representing a phone number + * @return the normalized string version of the phone number + */ + public static String normalizeDigitsOnly(CharSequence number) { + return normalizeDigits(number, false /* strip non-digits */).toString(); + } + + static StringBuilder normalizeDigits(CharSequence number, boolean keepNonDigits) { + StringBuilder normalizedDigits = new StringBuilder(number.length()); + for (int i = 0; i < number.length(); i++) { + char c = number.charAt(i); + int digit = Character.digit(c, 10); + if (digit != -1) { + normalizedDigits.append(digit); + } else if (keepNonDigits) { + normalizedDigits.append(c); + } + } + return normalizedDigits; + } + + /** + * Normalizes a string of characters representing a phone number. This strips all characters which + * are not diallable on a mobile phone keypad (including all non-ASCII digits). + * + * @param number a string of characters representing a phone number + * @return the normalized string version of the phone number + */ + public static String normalizeDiallableCharsOnly(CharSequence number) { + return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */); + } + + /** + * Converts all alpha characters in a number to their respective digits on a keypad, but retains + * existing formatting. + */ + public static String convertAlphaCharactersInNumber(CharSequence number) { + return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, false); + } + + /** + * Gets the length of the geographical area code from the + * PhoneNumber object passed in, so that clients could use it + * to split a national significant number into geographical area code and subscriber number. It + * works in such a way that the resultant subscriber number should be diallable, at least on some + * devices. An example of how this could be used: + * + *

{@code
+   * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+   * PhoneNumber number = phoneUtil.parse("16502530000", "US");
+   * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+   * String areaCode;
+   * String subscriberNumber;
+   *
+   * int areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
+   * if (areaCodeLength > 0) {
+   *   areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
+   *   subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
+   * } else {
+   *   areaCode = "";
+   *   subscriberNumber = nationalSignificantNumber;
+   * }
+   * }
+ * + * N.B.: area code is a very ambiguous concept, so the I18N team generally recommends against + * using it for most purposes, but recommends using the more general {@code national_number} + * instead. Read the following carefully before deciding to use this method: + *
    + *
  • geographical area codes change over time, and this method honors those changes; + * therefore, it doesn't guarantee the stability of the result it produces. + *
  • subscriber numbers may not be diallable from all devices (notably mobile devices, which + * typically requires the full national_number to be dialled in most regions). + *
  • most non-geographical numbers have no area codes, including numbers from non-geographical + * entities + *
  • some geographical numbers have no area codes. + *
+ * @param number the PhoneNumber object for which clients + * want to know the length of the area code + * @return the length of area code of the PhoneNumber object + * passed in + */ + public int getLengthOfGeographicalAreaCode(PhoneNumber number) { + PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number)); + if (metadata == null) { + return 0; + } + + PhoneNumberType type = getNumberType(number); + int countryCallingCode = number.getCountryCode(); + // If a country doesn't use a national prefix, and this number doesn't have an Italian leading + // zero, we assume it is a closed dialling plan with no area codes. + // Note:this is our general assumption, but there are exceptions which are tracked in + // COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES. + if (!metadata.hasNationalPrefix() && !number.isItalianLeadingZero() + && !COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES.contains(countryCallingCode)) { + return 0; + } + + if (type == PhoneNumberType.MOBILE + // Note this is a rough heuristic; it doesn't cover Indonesia well, for example, where area + // codes are present for some mobile phones but not for others. We have no better way of + // representing this in the metadata at this point. + && GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES.contains(countryCallingCode)) { + return 0; + } + + if (!isNumberGeographical(type, countryCallingCode)) { + return 0; + } + + return getLengthOfNationalDestinationCode(number); + } + + /** + * Gets the length of the national destination code (NDC) from the + * PhoneNumber object passed in, so that clients could use it + * to split a national significant number into NDC and subscriber number. The NDC of a phone + * number is normally the first group of digit(s) right after the country calling code when the + * number is formatted in the international format, if there is a subscriber number part that + * follows. + * + * N.B.: similar to an area code, not all numbers have an NDC! + * + * An example of how this could be used: + * + *
{@code
+   * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+   * PhoneNumber number = phoneUtil.parse("18002530000", "US");
+   * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+   * String nationalDestinationCode;
+   * String subscriberNumber;
+   *
+   * int nationalDestinationCodeLength = phoneUtil.getLengthOfNationalDestinationCode(number);
+   * if (nationalDestinationCodeLength > 0) {
+   *   nationalDestinationCode = nationalSignificantNumber.substring(0,
+   *       nationalDestinationCodeLength);
+   *   subscriberNumber = nationalSignificantNumber.substring(nationalDestinationCodeLength);
+   * } else {
+   *   nationalDestinationCode = "";
+   *   subscriberNumber = nationalSignificantNumber;
+   * }
+   * }
+ * + * Refer to the unittests to see the difference between this function and + * {@link #getLengthOfGeographicalAreaCode}. + * + * @param number the PhoneNumber object for which clients + * want to know the length of the NDC + * @return the length of NDC of the PhoneNumber object + * passed in, which could be zero + */ + public int getLengthOfNationalDestinationCode(PhoneNumber number) { + PhoneNumber copiedProto; + if (number.hasExtension()) { + // We don't want to alter the proto given to us, but we don't want to include the extension + // when we format it, so we copy it and clear the extension here. + copiedProto = new PhoneNumber(); + copiedProto.mergeFrom(number); + copiedProto.clearExtension(); + } else { + copiedProto = number; + } + + String nationalSignificantNumber = format(copiedProto, + PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); + String[] numberGroups = NON_DIGITS_PATTERN.split(nationalSignificantNumber); + // The pattern will start with "+COUNTRY_CODE " so the first group will always be the empty + // string (before the + symbol) and the second group will be the country calling code. The third + // group will be area code if it is not the last group. + if (numberGroups.length <= 3) { + return 0; + } + + if (getNumberType(number) == PhoneNumberType.MOBILE) { + // For example Argentinian mobile numbers, when formatted in the international format, are in + // the form of +54 9 NDC XXXX.... As a result, we take the length of the third group (NDC) and + // add the length of the second group (which is the mobile token), which also forms part of + // the national significant number. This assumes that the mobile token is always formatted + // separately from the rest of the phone number. + String mobileToken = getCountryMobileToken(number.getCountryCode()); + if (!mobileToken.equals("")) { + return numberGroups[2].length() + numberGroups[3].length(); + } + } + return numberGroups[2].length(); + } + + /** + * Returns the mobile token for the provided country calling code if it has one, otherwise + * returns an empty string. A mobile token is a number inserted before the area code when dialing + * a mobile number from that country from abroad. + * + * @param countryCallingCode the country calling code for which we want the mobile token + * @return the mobile token, as a string, for the given country calling code + */ + public static String getCountryMobileToken(int countryCallingCode) { + if (MOBILE_TOKEN_MAPPINGS.containsKey(countryCallingCode)) { + return MOBILE_TOKEN_MAPPINGS.get(countryCallingCode); + } + return ""; + } + + /** + * Normalizes a string of characters representing a phone number by replacing all characters found + * in the accompanying map with the values therein, and stripping all other characters if + * removeNonMatches is true. + * + * @param number a string of characters representing a phone number + * @param normalizationReplacements a mapping of characters to what they should be replaced by in + * the normalized version of the phone number + * @param removeNonMatches indicates whether characters that are not able to be replaced should + * be stripped from the number. If this is false, they will be left unchanged in the number. + * @return the normalized string version of the phone number + */ + private static String normalizeHelper(CharSequence number, + Map normalizationReplacements, + boolean removeNonMatches) { + StringBuilder normalizedNumber = new StringBuilder(number.length()); + for (int i = 0; i < number.length(); i++) { + char character = number.charAt(i); + Character newDigit = normalizationReplacements.get(Character.toUpperCase(character)); + if (newDigit != null) { + normalizedNumber.append(newDigit); + } else if (!removeNonMatches) { + normalizedNumber.append(character); + } + // If neither of the above are true, we remove this character. + } + return normalizedNumber.toString(); + } + + /** + * Sets or resets the PhoneNumberUtil singleton instance. If set to null, the next call to + * {@code getInstance()} will load (and return) the default instance. + */ + // @VisibleForTesting + static synchronized void setInstance(PhoneNumberUtil util) { + instance = util; + } + + /** + * Returns all regions the library has metadata for. + * + * @return an unordered set of the two-letter region codes for every geographical region the + * library supports + */ + public Set getSupportedRegions() { + return Collections.unmodifiableSet(supportedRegions); + } + + /** + * Returns all global network calling codes the library has metadata for. + * + * @return an unordered set of the country calling codes for every non-geographical entity the + * library supports + */ + public Set getSupportedGlobalNetworkCallingCodes() { + return Collections.unmodifiableSet(countryCodesForNonGeographicalRegion); + } + + /** + * Returns all country calling codes the library has metadata for, covering both non-geographical + * entities (global network calling codes) and those used for geographical entities. This could be + * used to populate a drop-down box of country calling codes for a phone-number widget, for + * instance. + * + * @return an unordered set of the country calling codes for every geographical and + * non-geographical entity the library supports + */ + public Set getSupportedCallingCodes() { + return Collections.unmodifiableSet(countryCallingCodeToRegionCodeMap.keySet()); + } + + /** + * Returns true if there is any possible number data set for a particular PhoneNumberDesc. + */ + private static boolean descHasPossibleNumberData(PhoneNumberDesc desc) { + // If this is empty, it means numbers of this type inherit from the "general desc" -> the value + // "-1" means that no numbers exist for this type. + return desc.getPossibleLengthCount() != 1 || desc.getPossibleLength(0) != -1; + } + + // Note: descHasData must account for any of MetadataFilter's excludableChildFields potentially + // being absent from the metadata. It must check them all. For any changes in descHasData, ensure + // that all the excludableChildFields are still being checked. If your change is safe simply + // mention why during a review without needing to change MetadataFilter. + /** + * Returns true if there is any data set for a particular PhoneNumberDesc. + */ + private static boolean descHasData(PhoneNumberDesc desc) { + // Checking most properties since we don't know what's present, since a custom build may have + // stripped just one of them (e.g. liteBuild strips exampleNumber). We don't bother checking the + // possibleLengthsLocalOnly, since if this is the only thing that's present we don't really + // support the type at all: no type-specific methods will work with only this data. + return desc.hasExampleNumber() + || descHasPossibleNumberData(desc) + || desc.hasNationalNumberPattern(); + } + + /** + * Returns the types we have metadata for based on the PhoneMetadata object passed in, which must + * be non-null. + */ + private Set getSupportedTypesForMetadata(PhoneMetadata metadata) { + Set types = new TreeSet<>(); + for (PhoneNumberType type : PhoneNumberType.values()) { + if (type == PhoneNumberType.FIXED_LINE_OR_MOBILE || type == PhoneNumberType.UNKNOWN) { + // Never return FIXED_LINE_OR_MOBILE (it is a convenience type, and represents that a + // particular number type can't be determined) or UNKNOWN (the non-type). + continue; + } + if (descHasData(getNumberDescByType(metadata, type))) { + types.add(type); + } + } + return Collections.unmodifiableSet(types); + } + + /** + * Returns the types for a given region which the library has metadata for. Will not include + * FIXED_LINE_OR_MOBILE (if numbers in this region could be classified as FIXED_LINE_OR_MOBILE, + * both FIXED_LINE and MOBILE would be present) and UNKNOWN. + * + * No types will be returned for invalid or unknown region codes. + */ + public Set getSupportedTypesForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return Collections.unmodifiableSet(new TreeSet()); + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + return getSupportedTypesForMetadata(metadata); + } + + /** + * Returns the types for a country-code belonging to a non-geographical entity which the library + * has metadata for. Will not include FIXED_LINE_OR_MOBILE (if numbers for this non-geographical + * entity could be classified as FIXED_LINE_OR_MOBILE, both FIXED_LINE and MOBILE would be + * present) and UNKNOWN. + * + * No types will be returned for country calling codes that do not map to a known non-geographical + * entity. + */ + public Set getSupportedTypesForNonGeoEntity(int countryCallingCode) { + PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); + if (metadata == null) { + logger.log(Level.WARNING, "Unknown country calling code for a non-geographical entity " + + "provided: " + countryCallingCode); + return Collections.unmodifiableSet(new TreeSet()); + } + return getSupportedTypesForMetadata(metadata); + } + + /** + * Gets a {@link PhoneNumberUtil} instance to carry out international phone number formatting, + * parsing, or validation. The instance is loaded with all phone number metadata. + * + *

The {@link PhoneNumberUtil} is implemented as a singleton. Therefore, calling getInstance + * multiple times will only result in one instance being created. + * + * @return a PhoneNumberUtil instance + */ + public static synchronized PhoneNumberUtil getInstance() { + if (instance == null) { + MetadataLoader metadataLoader = DefaultMetadataDependenciesProvider.getInstance() + .getMetadataLoader(); + setInstance(createInstance(metadataLoader)); + } + return instance; + } + + /** + * Create a new {@link PhoneNumberUtil} instance to carry out international phone number + * formatting, parsing, or validation. The instance is loaded with all metadata by + * using the metadataLoader specified. + * + *

This method should only be used in the rare case in which you want to manage your own + * metadata loading. Calling this method multiple times is very expensive, as each time + * a new instance is created from scratch. When in doubt, use {@link #getInstance}. + * + * @param metadataLoader customized metadata loader. This should not be null + * @return a PhoneNumberUtil instance + */ + public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) { + if (metadataLoader == null) { + throw new IllegalArgumentException("metadataLoader could not be null."); + } + return createInstance(new MetadataSourceImpl( + DefaultMetadataDependenciesProvider.getInstance().getPhoneNumberMetadataFileNameProvider(), + metadataLoader, + DefaultMetadataDependenciesProvider.getInstance().getMetadataParser() + )); + } + + /** + * Create a new {@link PhoneNumberUtil} instance to carry out international phone number + * formatting, parsing, or validation. The instance is loaded with all metadata by + * using the metadataSource specified. + * + *

This method should only be used in the rare case in which you want to manage your own + * metadata loading. Calling this method multiple times is very expensive, as each time + * a new instance is created from scratch. When in doubt, use {@link #getInstance}. + * + * @param metadataSource customized metadata source. This should not be null + * @return a PhoneNumberUtil instance + */ + private static PhoneNumberUtil createInstance(MetadataSource metadataSource) { + if (metadataSource == null) { + throw new IllegalArgumentException("metadataSource could not be null."); + } + return new PhoneNumberUtil(metadataSource, + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap()); + } + + /** + * Helper function to check if the national prefix formatting rule has the first group only, i.e., + * does not start with the national prefix. + */ + static boolean formattingRuleHasFirstGroupOnly(String nationalPrefixFormattingRule) { + return nationalPrefixFormattingRule.length() == 0 + || FIRST_GROUP_ONLY_PREFIX_PATTERN.matcher(nationalPrefixFormattingRule).matches(); + } + + /** + * Tests whether a phone number has a geographical association. It checks if the number is + * associated with a certain region in the country to which it belongs. Note that this doesn't + * verify if the number is actually in use. + */ + public boolean isNumberGeographical(PhoneNumber phoneNumber) { + return isNumberGeographical(getNumberType(phoneNumber), phoneNumber.getCountryCode()); + } + + /** + * Overload of isNumberGeographical(PhoneNumber), since calculating the phone number type is + * expensive; if we have already done this, we don't want to do it again. + */ + public boolean isNumberGeographical(PhoneNumberType phoneNumberType, int countryCallingCode) { + return phoneNumberType == PhoneNumberType.FIXED_LINE + || phoneNumberType == PhoneNumberType.FIXED_LINE_OR_MOBILE + || (GEO_MOBILE_COUNTRIES.contains(countryCallingCode) + && phoneNumberType == PhoneNumberType.MOBILE); + } + + /** + * Helper function to check region code is not unknown or null. + */ + private boolean isValidRegionCode(String regionCode) { + return regionCode != null && supportedRegions.contains(regionCode); + } + + /** + * Helper function to check the country calling code is valid. + */ + private boolean hasValidCountryCallingCode(int countryCallingCode) { + return countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode); + } + + /** + * Formats a phone number in the specified format using default rules. Note that this does not + * promise to produce a phone number that the user can dial from where they are - although we do + * format in either 'national' or 'international' format depending on what the client asks for, we + * do not currently support a more abbreviated format, such as for users in the same "area" who + * could potentially dial the number without area code. Note that if the phone number has a + * country calling code of 0 or an otherwise invalid country calling code, we cannot work out + * which formatting rules to apply so we return the national significant number with no formatting + * applied. + * + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into + * @return the formatted phone number + */ + public String format(PhoneNumber number, PhoneNumberFormat numberFormat) { + if (number.getNationalNumber() == 0) { + // Unparseable numbers that kept their raw input just use that. + // This is the only case where a number can be formatted as E164 without a + // leading '+' symbol (but the original number wasn't parseable anyway). + String rawInput = number.getRawInput(); + if (rawInput.length() > 0 || !number.hasCountryCode()) { + return rawInput; + } + } + StringBuilder formattedNumber = new StringBuilder(20); + format(number, numberFormat, formattedNumber); + return formattedNumber.toString(); + } + + /** + * Same as {@link #format(PhoneNumber, PhoneNumberFormat)}, but accepts a mutable StringBuilder as + * a parameter to decrease object creation when invoked many times. + */ + public void format(PhoneNumber number, PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + // Clear the StringBuilder first. + formattedNumber.setLength(0); + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + + if (numberFormat == PhoneNumberFormat.E164) { + // Early exit for E164 case (even if the country calling code is invalid) since no formatting + // of the national number needs to be applied. Extensions are not formatted. + formattedNumber.append(nationalSignificantNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.E164, + formattedNumber); + return; + } + if (!hasValidCountryCallingCode(countryCallingCode)) { + formattedNumber.append(nationalSignificantNumber); + return; + } + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid (which means that the + // region code cannot be ZZ and must be one of our supported region codes). + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, numberFormat)); + maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber); + } + + /** + * Formats a phone number in the specified format using client-defined formatting rules. Note that + * if the phone number has a country calling code of zero or an otherwise invalid country calling + * code, we cannot work out things like whether there should be a national prefix applied, or how + * to format extensions, so we return the national significant number with no formatting applied. + * + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into + * @param userDefinedFormats formatting rules specified by clients + * @return the formatted phone number + */ + public String formatByPattern(PhoneNumber number, + PhoneNumberFormat numberFormat, + List userDefinedFormats) { + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + + StringBuilder formattedNumber = new StringBuilder(20); + + NumberFormat formattingPattern = + chooseFormattingPatternForNumber(userDefinedFormats, nationalSignificantNumber); + if (formattingPattern == null) { + // If no pattern above is matched, we format the number as a whole. + formattedNumber.append(nationalSignificantNumber); + } else { + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); + // Before we do a replacement of the national prefix pattern $NP with the national prefix, we + // need to copy the rule so that subsequent replacements for different numbers have the + // appropriate national prefix. + numFormatCopy.mergeFrom(formattingPattern); + String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule(); + if (nationalPrefixFormattingRule.length() > 0) { + String nationalPrefix = metadata.getNationalPrefix(); + if (nationalPrefix.length() > 0) { + // Replace $NP with national prefix and $FG with the first group ($1). + nationalPrefixFormattingRule = + nationalPrefixFormattingRule.replace(NP_STRING, nationalPrefix); + nationalPrefixFormattingRule = nationalPrefixFormattingRule.replace(FG_STRING, "$1"); + numFormatCopy.setNationalPrefixFormattingRule(nationalPrefixFormattingRule); + } else { + // We don't want to have a rule for how to format the national prefix if there isn't one. + numFormatCopy.clearNationalPrefixFormattingRule(); + } + } + formattedNumber.append( + formatNsnUsingPattern(nationalSignificantNumber, numFormatCopy.build(), numberFormat)); + } + maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber); + return formattedNumber.toString(); + } + + /** + * Formats a phone number in national format for dialing using the carrier as specified in the + * {@code carrierCode}. The {@code carrierCode} will always be used regardless of whether the + * phone number already has a preferred domestic carrier code stored. If {@code carrierCode} + * contains an empty string, returns the number in national format without any carrier code. + * + * @param number the phone number to be formatted + * @param carrierCode the carrier selection code to be used + * @return the formatted phone number in national format for dialing using the carrier as + * specified in the {@code carrierCode} + */ + public String formatNationalNumberWithCarrierCode(PhoneNumber number, CharSequence carrierCode) { + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + + StringBuilder formattedNumber = new StringBuilder(20); + formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, + PhoneNumberFormat.NATIONAL, carrierCode)); + maybeAppendFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.NATIONAL, + formattedNumber); + return formattedNumber.toString(); + } + + private PhoneMetadata getMetadataForRegionOrCallingCode( + int countryCallingCode, String regionCode) { + return REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + ? getMetadataForNonGeographicalRegion(countryCallingCode) + : getMetadataForRegion(regionCode); + } + + /** + * Formats a phone number in national format for dialing using the carrier as specified in the + * preferredDomesticCarrierCode field of the PhoneNumber object passed in. If that is missing, + * use the {@code fallbackCarrierCode} passed in instead. If there is no + * {@code preferredDomesticCarrierCode}, and the {@code fallbackCarrierCode} contains an empty + * string, return the number in national format without any carrier code. + * + *

Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier code passed in + * should take precedence over the number's {@code preferredDomesticCarrierCode} when formatting. + * + * @param number the phone number to be formatted + * @param fallbackCarrierCode the carrier selection code to be used, if none is found in the + * phone number itself + * @return the formatted phone number in national format for dialing using the number's + * {@code preferredDomesticCarrierCode}, or the {@code fallbackCarrierCode} passed in if + * none is found + */ + public String formatNationalNumberWithPreferredCarrierCode(PhoneNumber number, + CharSequence fallbackCarrierCode) { + return formatNationalNumberWithCarrierCode(number, + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + number.getPreferredDomesticCarrierCode().length() > 0 + ? number.getPreferredDomesticCarrierCode() + : fallbackCarrierCode); + } + + /** + * Returns a number formatted in such a way that it can be dialed from a mobile phone in a + * specific region. If the number cannot be reached from the region (e.g. some countries block + * toll-free numbers from being called outside of the country), the method returns an empty + * string. + * + * @param number the phone number to be formatted + * @param regionCallingFrom the region where the call is being placed + * @param withFormatting whether the number should be returned with formatting symbols, such as + * spaces and dashes. + * @return the formatted phone number + */ + public String formatNumberForMobileDialing(PhoneNumber number, String regionCallingFrom, + boolean withFormatting) { + int countryCallingCode = number.getCountryCode(); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return number.hasRawInput() ? number.getRawInput() : ""; + } + + String formattedNumber = ""; + // Clear the extension, as that part cannot normally be dialed together with the main number. + PhoneNumber numberNoExt = new PhoneNumber().mergeFrom(number).clearExtension(); + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + PhoneNumberType numberType = getNumberType(numberNoExt); + boolean isValidNumber = (numberType != PhoneNumberType.UNKNOWN); + if (regionCallingFrom.equals(regionCode)) { + boolean isFixedLineOrMobile = + (numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) + || (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE); + // Carrier codes may be needed in some countries. We handle this here. + if (regionCode.equals("BR") && isFixedLineOrMobile) { + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + formattedNumber = numberNoExt.getPreferredDomesticCarrierCode().length() > 0 + ? formattedNumber = formatNationalNumberWithPreferredCarrierCode(numberNoExt, "") + // Brazilian fixed line and mobile numbers need to be dialed with a carrier code when + // called within Brazil. Without that, most of the carriers won't connect the call. + // Because of that, we return an empty string here. + : ""; + } else if (countryCallingCode == NANPA_COUNTRY_CODE) { + // For NANPA countries, we output international format for numbers that can be dialed + // internationally, since that always works, except for numbers which might potentially be + // short numbers, which are always dialled in national format. + PhoneMetadata regionMetadata = getMetadataForRegion(regionCallingFrom); + if (canBeInternationallyDialled(numberNoExt) + && testNumberLength(getNationalSignificantNumber(numberNoExt), regionMetadata) + != ValidationResult.TOO_SHORT) { + formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); + } else { + formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); + } + } else { + // For non-geographical countries, and Mexican, Chilean, and Uzbek fixed line and mobile + // numbers, we output international format for numbers that can be dialed internationally as + // that always works. + if ((regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITY) + // MX fixed line and mobile numbers should always be formatted in international format, + // even when dialed within MX. For national format to work, a carrier code needs to be + // used, and the correct carrier code depends on if the caller and callee are from the + // same local area. It is trickier to get that to work correctly than using + // international format, which is tested to work fine on all carriers. + // CL fixed line numbers need the national prefix when dialing in the national format, + // but don't have it when used for display. The reverse is true for mobile numbers. As + // a result, we output them in the international format to make it work. + // UZ mobile and fixed-line numbers have to be formatted in international format or + // prefixed with special codes like 03, 04 (for fixed-line) and 05 (for mobile) for + // dialling successfully from mobile devices. As we do not have complete information on + // special codes and to be consistent with formatting across all phone types we return + // the number in international format here. + || ((regionCode.equals("MX") || regionCode.equals("CL") + || regionCode.equals("UZ")) && isFixedLineOrMobile)) + && canBeInternationallyDialled(numberNoExt)) { + formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); + } else { + formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); + } + } + } else if (isValidNumber && canBeInternationallyDialled(numberNoExt)) { + // We assume that short numbers are not diallable from outside their region, so if a number + // is not a valid regular length phone number, we treat it as if it cannot be internationally + // dialled. + return withFormatting ? format(numberNoExt, PhoneNumberFormat.INTERNATIONAL) + : format(numberNoExt, PhoneNumberFormat.E164); + } + return withFormatting ? formattedNumber + : normalizeDiallableCharsOnly(formattedNumber); + } + + /** + * Formats a phone number for out-of-country dialing purposes. If no regionCallingFrom is + * supplied, we format the number in its INTERNATIONAL format. If the country calling code is the + * same as that of the region where the number is from, then NATIONAL formatting will be applied. + * + *

If the number itself has a country calling code of zero or an otherwise invalid country + * calling code, then we return the number with no formatting applied. + * + *

Note this function takes care of the case for calling inside of NANPA and between Russia and + * Kazakhstan (who share the same country calling code). In those cases, no international prefix + * is used. For regions which have multiple international prefixes, the number in its + * INTERNATIONAL format will be returned instead. + * + * @param number the phone number to be formatted + * @param regionCallingFrom the region where the call is being placed + * @return the formatted phone number + */ + public String formatOutOfCountryCallingNumber(PhoneNumber number, + String regionCallingFrom) { + if (!isValidRegionCode(regionCallingFrom)) { + logger.log(Level.WARNING, + "Trying to format number from invalid region " + + regionCallingFrom + + ". International formatting applied."); + return format(number, PhoneNumberFormat.INTERNATIONAL); + } + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + if (countryCallingCode == NANPA_COUNTRY_CODE) { + if (isNANPACountry(regionCallingFrom)) { + // For NANPA regions, return the national format for these regions but prefix it with the + // country calling code. + return countryCallingCode + " " + format(number, PhoneNumberFormat.NATIONAL); + } + } else if (countryCallingCode == getCountryCodeForValidRegion(regionCallingFrom)) { + // If regions share a country calling code, the country calling code need not be dialled. + // This also applies when dialling within a region, so this if clause covers both these cases. + // Technically this is the case for dialling from La Reunion to other overseas departments of + // France (French Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover this + // edge case for now and for those cases return the version including country calling code. + // Details here: http://www.petitfute.com/voyage/225-info-pratiques-reunion + return format(number, PhoneNumberFormat.NATIONAL); + } + // Metadata cannot be null because we checked 'isValidRegionCode()' above. + PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom); + String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix(); + + // In general, if there is a preferred international prefix, use that. Otherwise, for regions + // that have multiple international prefixes, the international format of the number is + // returned since we would not know which one to use. + String internationalPrefixForFormatting = ""; + if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) { + internationalPrefixForFormatting = + metadataForRegionCallingFrom.getPreferredInternationalPrefix(); + } else if (SINGLE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches()) { + internationalPrefixForFormatting = internationalPrefix; + } + + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadataForRegion = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + String formattedNationalNumber = + formatNsn(nationalSignificantNumber, metadataForRegion, PhoneNumberFormat.INTERNATIONAL); + StringBuilder formattedNumber = new StringBuilder(formattedNationalNumber); + maybeAppendFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + prefixNumberWithCountryCallingCode(countryCallingCode, + PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + } + return formattedNumber.toString(); + } + + /** + * Formats a phone number using the original phone number format (e.g. INTERNATIONAL or NATIONAL) + * that the number is parsed from, provided that the number has been parsed with {@link + * parseAndKeepRawInput}. Otherwise the number will be formatted in NATIONAL format. + * + *

The original format is embedded in the country_code_source field of the PhoneNumber object + * passed in, which is only set when parsing keeps the raw input. When we don't have a formatting + * pattern for the number, the method falls back to returning the raw input. + * + *

Note this method guarantees no digit will be inserted, removed or modified as a result of + * formatting. + * + * @param number the phone number that needs to be formatted in its original number format + * @param regionCallingFrom the region whose IDD needs to be prefixed if the original number has + * one + * @return the formatted phone number in its original number format + */ + public String formatInOriginalFormat(PhoneNumber number, String regionCallingFrom) { + NumberFormat formatRule = chooseFormattingPatternForNumber(number); + if (number.hasRawInput() && formatRule == null) { + // We check if we have the formatting pattern because without that, we might format the number + // as a group without national prefix. + return number.getRawInput(); + } + if (!number.hasCountryCodeSource()) { + return format(number, PhoneNumberFormat.NATIONAL); + } + String formattedNumber; + switch (number.getCountryCodeSource()) { + case FROM_NUMBER_WITH_PLUS_SIGN: + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL); + break; + case FROM_NUMBER_WITH_IDD: + formattedNumber = formatOutOfCountryCallingNumber(number, regionCallingFrom); + break; + case FROM_NUMBER_WITHOUT_PLUS_SIGN: + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL).substring(1); + break; + case FROM_DEFAULT_COUNTRY: + // Fall-through to default case. + default: + String regionCode = getRegionCodeForCountryCode(number.getCountryCode()); + // We strip non-digits from the NDD here, and from the raw input later, so that we can + // compare them easily. + String nationalPrefix = getNddPrefixForRegion(regionCode, true /* strip non-digits */); + String nationalFormat = format(number, PhoneNumberFormat.NATIONAL); + if (nationalPrefix == null || nationalPrefix.length() == 0) { + // If the region doesn't have a national prefix at all, we can safely return the national + // format without worrying about a national prefix being added. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we check if the original number was entered with a national prefix. + if (rawInputContainsNationalPrefix( + number.getRawInput(), nationalPrefix, regionCode)) { + // If so, we can safely return the national format. + formattedNumber = nationalFormat; + break; + } + // The format rule could still be null here if the national number was 0 and there was no + // raw input (this should not be possible for numbers generated by the phonenumber library + // as they would also not have a country calling code and we would have exited earlier). + if (formatRule == null) { + formattedNumber = nationalFormat; + break; + } + // When the format we apply to this number doesn't contain national prefix, we can just + // return the national format. + // TODO: Refactor the code below with the code in + // isNationalPrefixPresentIfRequired. + String candidateNationalPrefixRule = formatRule.getNationalPrefixFormattingRule(); + // We assume that the first-group symbol will never be _before_ the national prefix. + int indexOfFirstGroup = candidateNationalPrefixRule.indexOf("$1"); + if (indexOfFirstGroup <= 0) { + formattedNumber = nationalFormat; + break; + } + candidateNationalPrefixRule = + candidateNationalPrefixRule.substring(0, indexOfFirstGroup); + candidateNationalPrefixRule = normalizeDigitsOnly(candidateNationalPrefixRule); + if (candidateNationalPrefixRule.length() == 0) { + // National prefix not used when formatting this number. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we need to remove the national prefix from our output. + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); + numFormatCopy.mergeFrom(formatRule); + numFormatCopy.clearNationalPrefixFormattingRule(); + List numberFormats = new ArrayList<>(1); + numberFormats.add(numFormatCopy.build()); + formattedNumber = formatByPattern(number, PhoneNumberFormat.NATIONAL, numberFormats); + break; + } + String rawInput = number.getRawInput(); + // If no digit is inserted/removed/modified as a result of our formatting, we return the + // formatted phone number; otherwise we return the raw input the user entered. + if (formattedNumber != null && rawInput.length() > 0) { + String normalizedFormattedNumber = normalizeDiallableCharsOnly(formattedNumber); + String normalizedRawInput = normalizeDiallableCharsOnly(rawInput); + if (!normalizedFormattedNumber.equals(normalizedRawInput)) { + formattedNumber = rawInput; + } + } + return formattedNumber; + } + + // Check if rawInput, which is assumed to be in the national format, has a national prefix. The + // national prefix is assumed to be in digits-only form. + private boolean rawInputContainsNationalPrefix(String rawInput, String nationalPrefix, + String regionCode) { + String normalizedNationalNumber = normalizeDigitsOnly(rawInput); + if (normalizedNationalNumber.startsWith(nationalPrefix)) { + try { + // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the national prefix + // when written without it (e.g. 0777123) if we just do prefix matching. To tackle that, we + // check the validity of the number if the assumed national prefix is removed (777123 won't + // be valid in Japan). + return isValidNumber( + parse(normalizedNationalNumber.substring(nationalPrefix.length()), regionCode)); + } catch (NumberParseException e) { + return false; + } + } + return false; + } + + private NumberFormat chooseFormattingPatternForNumber(PhoneNumber number) { + int countryCallingCode = number.getCountryCode(); + String phoneNumberRegion = getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, phoneNumberRegion); + if (metadata == null) { + return null; + } + String nationalNumber = getNationalSignificantNumber(number); + return chooseFormattingPatternForNumber(metadata.getNumberFormatList(), nationalNumber); + } + + NumberFormat chooseFormattingPatternForNumber(List availableFormats, + String nationalNumber) { + for (NumberFormat numFormat : availableFormats) { + int size = numFormat.getLeadingDigitsPatternCount(); + if (size == 0 || regexCache.getPatternForRegex( + // We always use the last leading_digits_pattern, as it is the most detailed. + numFormat.getLeadingDigitsPattern(size - 1)).matcher(nationalNumber).lookingAt()) { + Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber); + if (m.matches()) { + return numFormat; + } + } + } + return null; + } + + /** + * Formats a phone number for out-of-country dialing purposes. + * + * Note that in this version, if the number was entered originally using alpha characters and + * this version of the number is stored in raw_input, this representation of the number will be + * used rather than the digit representation. Grouping information, as specified by characters + * such as "-" and " ", will be retained. + * + *

Caveats:

+ *
    + *
  • This will not produce good results if the country calling code is both present in the raw + * input _and_ is the start of the national number. This is not a problem in the regions + * which typically use alpha numbers. + *
  • This will also not produce good results if the raw input has any grouping information + * within the first three digits of the national number, and if the function needs to strip + * preceding digits/words in the raw input before these digits. Normally people group the + * first three digits together so this is not a huge problem - and will be fixed if it + * proves to be so. + *
+ * + * @param number the phone number that needs to be formatted + * @param regionCallingFrom the region where the call is being placed + * @return the formatted phone number + */ + public String formatOutOfCountryKeepingAlphaChars(PhoneNumber number, + String regionCallingFrom) { + String rawInput = number.getRawInput(); + // If there is no raw input, then we can't keep alpha characters because there aren't any. + // In this case, we return formatOutOfCountryCallingNumber. + if (rawInput.length() == 0) { + return formatOutOfCountryCallingNumber(number, regionCallingFrom); + } + int countryCode = number.getCountryCode(); + if (!hasValidCountryCallingCode(countryCode)) { + return rawInput; + } + // Strip any prefix such as country calling code, IDD, that was present. We do this by comparing + // the number in raw_input with the parsed number. + // To do this, first we normalize punctuation. We retain number grouping symbols such as " " + // only. + rawInput = normalizeHelper(rawInput, ALL_PLUS_NUMBER_GROUPING_SYMBOLS, true); + // Now we trim everything before the first three digits in the parsed number. We choose three + // because all valid alpha numbers have 3 digits at the start - if it does not, then we don't + // trim anything at all. Similarly, if the national number was less than three digits, we don't + // trim anything at all. + String nationalNumber = getNationalSignificantNumber(number); + if (nationalNumber.length() > 3) { + int firstNationalNumberDigit = rawInput.indexOf(nationalNumber.substring(0, 3)); + if (firstNationalNumberDigit != -1) { + rawInput = rawInput.substring(firstNationalNumberDigit); + } + } + PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom); + if (countryCode == NANPA_COUNTRY_CODE) { + if (isNANPACountry(regionCallingFrom)) { + return countryCode + " " + rawInput; + } + } else if (metadataForRegionCallingFrom != null + && countryCode == getCountryCodeForValidRegion(regionCallingFrom)) { + NumberFormat formattingPattern = + chooseFormattingPatternForNumber(metadataForRegionCallingFrom.getNumberFormatList(), + nationalNumber); + if (formattingPattern == null) { + // If no pattern above is matched, we format the original input. + return rawInput; + } + NumberFormat.Builder newFormat = NumberFormat.newBuilder(); + newFormat.mergeFrom(formattingPattern); + // The first group is the first group of digits that the user wrote together. + newFormat.setPattern("(\\d+)(.*)"); + // Here we just concatenate them back together after the national prefix has been fixed. + newFormat.setFormat("$1$2"); + // Now we format using this pattern instead of the default pattern, but with the national + // prefix prefixed if necessary. + // This will not work in the cases where the pattern (and not the leading digits) decide + // whether a national prefix needs to be used, since we have overridden the pattern to match + // anything, but that is not the case in the metadata to date. + return formatNsnUsingPattern(rawInput, newFormat.build(), PhoneNumberFormat.NATIONAL); + } + String internationalPrefixForFormatting = ""; + // If an unsupported region-calling-from is entered, or a country with multiple international + // prefixes, the international format of the number is returned, unless there is a preferred + // international prefix. + if (metadataForRegionCallingFrom != null) { + String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix(); + internationalPrefixForFormatting = + SINGLE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches() + ? internationalPrefix + : metadataForRegionCallingFrom.getPreferredInternationalPrefix(); + } + StringBuilder formattedNumber = new StringBuilder(rawInput); + String regionCode = getRegionCodeForCountryCode(countryCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadataForRegion = getMetadataForRegionOrCallingCode(countryCode, regionCode); + // Strip any extension + maybeStripExtension(formattedNumber); + // Append the formatted extension + maybeAppendFormattedExtension( + number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL, formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + // Invalid region entered as country-calling-from (so no metadata was found for it) or the + // region chosen has multiple international dialling prefixes. + if (!isValidRegionCode(regionCallingFrom)) { + logger.log(Level.WARNING, + "Trying to format number from invalid region " + + regionCallingFrom + + ". International formatting applied."); + } + prefixNumberWithCountryCallingCode(countryCode, + PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + } + return formattedNumber.toString(); + } + + /** + * Gets the national significant number of a phone number. Note a national significant number + * doesn't contain a national prefix or any formatting. + * + * @param number the phone number for which the national significant number is needed + * @return the national significant number of the PhoneNumber object passed in + */ + public String getNationalSignificantNumber(PhoneNumber number) { + // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix. + StringBuilder nationalNumber = new StringBuilder(); + if (number.isItalianLeadingZero() && number.getNumberOfLeadingZeros() > 0) { + char[] zeros = new char[number.getNumberOfLeadingZeros()]; + Arrays.fill(zeros, '0'); + nationalNumber.append(new String(zeros)); + } + nationalNumber.append(number.getNationalNumber()); + return nationalNumber.toString(); + } + + /** + * A helper function that is used by format and formatByPattern. + */ + private void prefixNumberWithCountryCallingCode(int countryCallingCode, + PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + switch (numberFormat) { + case E164: + formattedNumber.insert(0, countryCallingCode).insert(0, PLUS_SIGN); + return; + case INTERNATIONAL: + formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, PLUS_SIGN); + return; + case RFC3966: + formattedNumber.insert(0, "-").insert(0, countryCallingCode).insert(0, PLUS_SIGN) + .insert(0, RFC3966_PREFIX); + return; + case NATIONAL: + default: + return; + } + } + + // Simple wrapper of formatNsn for the common case of no carrier code. + private String formatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat) { + return formatNsn(number, metadata, numberFormat, null); + } + + // Note in some regions, the national number can be written in two completely different ways + // depending on whether it forms part of the NATIONAL format or INTERNATIONAL format. The + // numberFormat parameter here is used to specify which format to use for those cases. If a + // carrierCode is specified, this will be inserted into the formatted string to replace $CC. + private String formatNsn(String number, + PhoneMetadata metadata, + PhoneNumberFormat numberFormat, + CharSequence carrierCode) { + List intlNumberFormats = metadata.getIntlNumberFormatList(); + // When the intlNumberFormats exists, we use that to format national number for the + // INTERNATIONAL format instead of using the numberDesc.numberFormats. + List availableFormats = + (intlNumberFormats.size() == 0 || numberFormat == PhoneNumberFormat.NATIONAL) + ? metadata.getNumberFormatList() + : metadata.getIntlNumberFormatList(); + NumberFormat formattingPattern = chooseFormattingPatternForNumber(availableFormats, number); + return (formattingPattern == null) + ? number + : formatNsnUsingPattern(number, formattingPattern, numberFormat, carrierCode); + } + + // Simple wrapper of formatNsnUsingPattern for the common case of no carrier code. + String formatNsnUsingPattern(String nationalNumber, + NumberFormat formattingPattern, + PhoneNumberFormat numberFormat) { + return formatNsnUsingPattern(nationalNumber, formattingPattern, numberFormat, null); + } + + // Note that carrierCode is optional - if null or an empty string, no carrier code replacement + // will take place. + private String formatNsnUsingPattern(String nationalNumber, + NumberFormat formattingPattern, + PhoneNumberFormat numberFormat, + CharSequence carrierCode) { + String numberFormatRule = formattingPattern.getFormat(); + Matcher m = + regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber); + String formattedNationalNumber = ""; + if (numberFormat == PhoneNumberFormat.NATIONAL + && carrierCode != null && carrierCode.length() > 0 + && formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) { + // Replace the $CC in the formatting rule with the desired carrier code. + String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule(); + carrierCodeFormattingRule = carrierCodeFormattingRule.replace(CC_STRING, carrierCode); + // Now replace the $FG in the formatting rule with the first group and the carrier code + // combined in the appropriate way. + numberFormatRule = FIRST_GROUP_PATTERN.matcher(numberFormatRule) + .replaceFirst(carrierCodeFormattingRule); + formattedNationalNumber = m.replaceAll(numberFormatRule); + } else { + // Use the national prefix formatting rule instead. + String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule(); + if (numberFormat == PhoneNumberFormat.NATIONAL + && nationalPrefixFormattingRule != null + && nationalPrefixFormattingRule.length() > 0) { + Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule); + formattedNationalNumber = + m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule)); + } else { + formattedNationalNumber = m.replaceAll(numberFormatRule); + } + } + if (numberFormat == PhoneNumberFormat.RFC3966) { + // Strip any leading punctuation. + Matcher matcher = SEPARATOR_PATTERN.matcher(formattedNationalNumber); + if (matcher.lookingAt()) { + formattedNationalNumber = matcher.replaceFirst(""); + } + // Replace the rest with a dash between each number group. + formattedNationalNumber = matcher.reset(formattedNationalNumber).replaceAll("-"); + } + return formattedNationalNumber; + } + + /** + * Gets a valid number for the specified region. + * + * @param regionCode the region for which an example number is needed + * @return a valid fixed-line number for the specified region. Returns null when the metadata + * does not contain such information, or the region 001 is passed in. For 001 (representing + * non-geographical numbers), call {@link #getExampleNumberForNonGeoEntity} instead. + */ + public PhoneNumber getExampleNumber(String regionCode) { + return getExampleNumberForType(regionCode, PhoneNumberType.FIXED_LINE); + } + + /** + * Gets an invalid number for the specified region. This is useful for unit-testing purposes, + * where you want to test what will happen with an invalid number. Note that the number that is + * returned will always be able to be parsed and will have the correct country code. It may also + * be a valid *short* number/code for this region. Validity checking such numbers is handled with + * {@link com.google.i18n.phonenumbers.ShortNumberInfo}. + * + * @param regionCode the region for which an example number is needed + * @return an invalid number for the specified region. Returns null when an unsupported region or + * the region 001 (Earth) is passed in. + */ + public PhoneNumber getInvalidExampleNumber(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return null; + } + // We start off with a valid fixed-line number since every country supports this. Alternatively + // we could start with a different number type, since fixed-line numbers typically have a wide + // breadth of valid number lengths and we may have to make it very short before we get an + // invalid number. + PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), + PhoneNumberType.FIXED_LINE); + if (!desc.hasExampleNumber()) { + // This shouldn't happen; we have a test for this. + return null; + } + String exampleNumber = desc.getExampleNumber(); + // Try and make the number invalid. We do this by changing the length. We try reducing the + // length of the number, since currently no region has a number that is the same length as + // MIN_LENGTH_FOR_NSN. This is probably quicker than making the number longer, which is another + // alternative. We could also use the possible number pattern to extract the possible lengths of + // the number to make this faster, but this method is only for unit-testing so simplicity is + // preferred to performance. We don't want to return a number that can't be parsed, so we check + // the number is long enough. We try all possible lengths because phone number plans often have + // overlapping prefixes so the number 123456 might be valid as a fixed-line number, and 12345 as + // a mobile number. It would be faster to loop in a different order, but we prefer numbers that + // look closer to real numbers (and it gives us a variety of different lengths for the resulting + // phone numbers - otherwise they would all be MIN_LENGTH_FOR_NSN digits long.) + for (int phoneNumberLength = exampleNumber.length() - 1; + phoneNumberLength >= MIN_LENGTH_FOR_NSN; + phoneNumberLength--) { + String numberToTry = exampleNumber.substring(0, phoneNumberLength); + try { + PhoneNumber possiblyValidNumber = parse(numberToTry, regionCode); + if (!isValidNumber(possiblyValidNumber)) { + return possiblyValidNumber; + } + } catch (NumberParseException e) { + // Shouldn't happen: we have already checked the length, we know example numbers have + // only valid digits, and we know the region code is fine. + } + } + // We have a test to check that this doesn't happen for any of our supported regions. + return null; + } + + /** + * Gets a valid number for the specified region and number type. + * + * @param regionCode the region for which an example number is needed + * @param type the type of number that is needed + * @return a valid number for the specified region and type. Returns null when the metadata + * does not contain such information or if an invalid region or region 001 was entered. + * For 001 (representing non-geographical numbers), call + * {@link #getExampleNumberForNonGeoEntity} instead. + */ + public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) { + // Check the region code is valid. + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return null; + } + PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), type); + try { + if (desc.hasExampleNumber()) { + return parse(desc.getExampleNumber(), regionCode); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + return null; + } + + /** + * Gets a valid number for the specified number type (it may belong to any country). + * + * @param type the type of number that is needed + * @return a valid number for the specified type. Returns null when the metadata + * does not contain such information. This should only happen when no numbers of this type are + * allocated anywhere in the world anymore. + */ + public PhoneNumber getExampleNumberForType(PhoneNumberType type) { + for (String regionCode : getSupportedRegions()) { + PhoneNumber exampleNumber = getExampleNumberForType(regionCode, type); + if (exampleNumber != null) { + return exampleNumber; + } + } + // If there wasn't an example number for a region, try the non-geographical entities. + for (int countryCallingCode : getSupportedGlobalNetworkCallingCodes()) { + PhoneNumberDesc desc = getNumberDescByType( + getMetadataForNonGeographicalRegion(countryCallingCode), type); + try { + if (desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + } + // There are no example numbers of this type for any country in the library. + return null; + } + + /** + * Gets a valid number for the specified country calling code for a non-geographical entity. + * + * @param countryCallingCode the country calling code for a non-geographical entity + * @return a valid number for the non-geographical entity. Returns null when the metadata + * does not contain such information, or the country calling code passed in does not belong + * to a non-geographical entity. + */ + public PhoneNumber getExampleNumberForNonGeoEntity(int countryCallingCode) { + PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); + if (metadata != null) { + // For geographical entities, fixed-line data is always present. However, for non-geographical + // entities, this is not the case, so we have to go through different types to find the + // example number. We don't check fixed-line or personal number since they aren't used by + // non-geographical entities (if this changes, a unit-test will catch this.) + for (PhoneNumberDesc desc : Arrays.asList(metadata.getMobile(), metadata.getTollFree(), + metadata.getSharedCost(), metadata.getVoip(), metadata.getVoicemail(), + metadata.getUan(), metadata.getPremiumRate())) { + try { + if (desc != null && desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + } + } else { + logger.log(Level.WARNING, + "Invalid or unknown country calling code provided: " + countryCallingCode); + } + return null; + } + + /** + * Appends the formatted extension of a phone number to formattedNumber, if the phone number had + * an extension specified. + */ + private void maybeAppendFormattedExtension(PhoneNumber number, PhoneMetadata metadata, + PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + if (number.hasExtension() && number.getExtension().length() > 0) { + if (numberFormat == PhoneNumberFormat.RFC3966) { + formattedNumber.append(RFC3966_EXTN_PREFIX).append(number.getExtension()); + } else { + if (metadata.hasPreferredExtnPrefix()) { + formattedNumber.append(metadata.getPreferredExtnPrefix()).append(number.getExtension()); + } else { + formattedNumber.append(DEFAULT_EXTN_PREFIX).append(number.getExtension()); + } + } + } + } + + PhoneNumberDesc getNumberDescByType(PhoneMetadata metadata, PhoneNumberType type) { + switch (type) { + case PREMIUM_RATE: + return metadata.getPremiumRate(); + case TOLL_FREE: + return metadata.getTollFree(); + case MOBILE: + return metadata.getMobile(); + case FIXED_LINE: + case FIXED_LINE_OR_MOBILE: + return metadata.getFixedLine(); + case SHARED_COST: + return metadata.getSharedCost(); + case VOIP: + return metadata.getVoip(); + case PERSONAL_NUMBER: + return metadata.getPersonalNumber(); + case PAGER: + return metadata.getPager(); + case UAN: + return metadata.getUan(); + case VOICEMAIL: + return metadata.getVoicemail(); + default: + return metadata.getGeneralDesc(); + } + } + + /** + * Gets the type of a valid phone number. + * + * @param number the phone number that we want to know the type + * @return the type of the phone number, or UNKNOWN if it is invalid + */ + public PhoneNumberType getNumberType(PhoneNumber number) { + String regionCode = getRegionCodeForNumber(number); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode); + if (metadata == null) { + return PhoneNumberType.UNKNOWN; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return getNumberTypeHelper(nationalSignificantNumber, metadata); + } + + private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) { + if (!isNumberMatchingDesc(nationalNumber, metadata.getGeneralDesc())) { + return PhoneNumberType.UNKNOWN; + } + + if (isNumberMatchingDesc(nationalNumber, metadata.getPremiumRate())) { + return PhoneNumberType.PREMIUM_RATE; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getTollFree())) { + return PhoneNumberType.TOLL_FREE; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getSharedCost())) { + return PhoneNumberType.SHARED_COST; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getVoip())) { + return PhoneNumberType.VOIP; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getPersonalNumber())) { + return PhoneNumberType.PERSONAL_NUMBER; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getPager())) { + return PhoneNumberType.PAGER; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getUan())) { + return PhoneNumberType.UAN; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getVoicemail())) { + return PhoneNumberType.VOICEMAIL; + } + + boolean isFixedLine = isNumberMatchingDesc(nationalNumber, metadata.getFixedLine()); + if (isFixedLine) { + if (metadata.getSameMobileAndFixedLinePattern()) { + return PhoneNumberType.FIXED_LINE_OR_MOBILE; + } else if (isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { + return PhoneNumberType.FIXED_LINE_OR_MOBILE; + } + return PhoneNumberType.FIXED_LINE; + } + // Otherwise, test to see if the number is mobile. Only do this if certain that the patterns for + // mobile and fixed line aren't the same. + if (!metadata.getSameMobileAndFixedLinePattern() + && isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { + return PhoneNumberType.MOBILE; + } + return PhoneNumberType.UNKNOWN; + } + + /** + * Returns the metadata for the given region code or {@code null} if the region code is invalid or + * unknown. + * + * @throws MissingMetadataException if the region code is valid, but metadata cannot be found. + */ + PhoneMetadata getMetadataForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + return null; + } + PhoneMetadata phoneMetadata = metadataSource.getMetadataForRegion(regionCode); + ensureMetadataIsNonNull(phoneMetadata, "Missing metadata for region code " + regionCode); + return phoneMetadata; + } + + /** + * Returns the metadata for the given country calling code or {@code null} if the country calling + * code is invalid or unknown. + * + * @throws MissingMetadataException if the country calling code is valid, but metadata cannot be + * found. + */ + PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { + if (!countryCodesForNonGeographicalRegion.contains(countryCallingCode)) { + return null; + } + PhoneMetadata phoneMetadata = metadataSource.getMetadataForNonGeographicalRegion( + countryCallingCode); + ensureMetadataIsNonNull(phoneMetadata, + "Missing metadata for country code " + countryCallingCode); + return phoneMetadata; + } + + private static void ensureMetadataIsNonNull(PhoneMetadata phoneMetadata, String message) { + if (phoneMetadata == null) { + throw new MissingMetadataException(message); + } + } + + boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) { + // Check if any possible number lengths are present; if so, we use them to avoid checking the + // validation pattern if they don't match. If they are absent, this means they match the general + // description, which we have already checked before checking a specific number type. + int actualLength = nationalNumber.length(); + List possibleLengths = numberDesc.getPossibleLengthList(); + if (possibleLengths.size() > 0 && !possibleLengths.contains(actualLength)) { + return false; + } + return matcherApi.matchNationalNumber(nationalNumber, numberDesc, false); + } + + /** + * Tests whether a phone number matches a valid pattern. Note this doesn't verify the number + * is actually in use, which is impossible to tell by just looking at a number itself. It only + * verifies whether the parsed, canonicalised number is valid: not whether a particular series of + * digits entered by the user is diallable from the region provided when parsing. For example, the + * number +41 (0) 78 927 2696 can be parsed into a number with country code "41" and national + * significant number "789272696". This is valid, while the original string is not diallable. + * + * @param number the phone number that we want to validate + * @return a boolean that indicates whether the number is of a valid pattern + */ + public boolean isValidNumber(PhoneNumber number) { + String regionCode = getRegionCodeForNumber(number); + return isValidNumberForRegion(number, regionCode); + } + + /** + * Tests whether a phone number is valid for a certain region. Note this doesn't verify the number + * is actually in use, which is impossible to tell by just looking at a number itself. If the + * country calling code is not the same as the country calling code for the region, this + * immediately exits with false. After this, the specific number pattern rules for the region are + * examined. This is useful for determining for example whether a particular number is valid for + * Canada, rather than just a valid NANPA number. + * Warning: In most cases, you want to use {@link #isValidNumber} instead. For example, this + * method will mark numbers from British Crown dependencies such as the Isle of Man as invalid for + * the region "GB" (United Kingdom), since it has its own region code, "IM", which may be + * undesirable. + * + * @param number the phone number that we want to validate + * @param regionCode the region that we want to validate the phone number for + * @return a boolean that indicates whether the number is of a valid pattern + */ + public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) { + int countryCode = number.getCountryCode(); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); + if ((metadata == null) + || (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + && countryCode != getCountryCodeForValidRegion(regionCode))) { + // Either the region code was invalid, or the country calling code for this number does not + // match that of the region code. + return false; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return getNumberTypeHelper(nationalSignificantNumber, metadata) != PhoneNumberType.UNKNOWN; + } + + /** + * Returns the region where a phone number is from. This could be used for geocoding at the region + * level. Only guarantees correct results for valid, full numbers (not short-codes, or invalid + * numbers). + * + * @param number the phone number whose origin we want to know + * @return the region where the phone number is from, or null if no region matches this calling + * code + */ + public String getRegionCodeForNumber(PhoneNumber number) { + int countryCode = number.getCountryCode(); + List regions = countryCallingCodeToRegionCodeMap.get(countryCode); + if (regions == null) { + logger.log(Level.INFO, "Missing/invalid country_code (" + countryCode + ")"); + return null; + } + if (regions.size() == 1) { + return regions.get(0); + } else { + return getRegionCodeForNumberFromRegionList(number, regions); + } + } + + private String getRegionCodeForNumberFromRegionList(PhoneNumber number, + List regionCodes) { + String nationalNumber = getNationalSignificantNumber(number); + for (String regionCode : regionCodes) { + // If leadingDigits is present, use this. Otherwise, do full validation. + // Metadata cannot be null because the region codes come from the country calling code map. + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata.hasLeadingDigits()) { + if (regexCache.getPatternForRegex(metadata.getLeadingDigits()) + .matcher(nationalNumber).lookingAt()) { + return regionCode; + } + } else if (getNumberTypeHelper(nationalNumber, metadata) != PhoneNumberType.UNKNOWN) { + return regionCode; + } + } + return null; + } + + /** + * Returns the region code that matches the specific country calling code. In the case of no + * region code being found, ZZ will be returned. In the case of multiple regions, the one + * designated in the metadata as the "main" region for this calling code will be returned. If the + * countryCallingCode entered is valid but doesn't match a specific region (such as in the case of + * non-geographical calling codes like 800) the value "001" will be returned (corresponding to + * the value for World in the UN M.49 schema). + */ + public String getRegionCodeForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return regionCodes == null ? UNKNOWN_REGION : regionCodes.get(0); + } + + /** + * Returns a list with the region codes that match the specific country calling code. For + * non-geographical country calling codes, the region code 001 is returned. Also, in the case + * of no region code being found, an empty list is returned. + */ + public List getRegionCodesForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return Collections.unmodifiableList(regionCodes == null ? new ArrayList(0) + : regionCodes); + } + + /** + * Returns the country calling code for a specific region. For example, this would be 1 for the + * United States, and 64 for New Zealand. + * + * @param regionCode the region that we want to get the country calling code for + * @return the country calling code for the region denoted by regionCode + */ + public int getCountryCodeForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); + return 0; + } + return getCountryCodeForValidRegion(regionCode); + } + + /** + * Returns the country calling code for a specific region. For example, this would be 1 for the + * United States, and 64 for New Zealand. Assumes the region is already valid. + * + * @param regionCode the region that we want to get the country calling code for + * @return the country calling code for the region denoted by regionCode + * @throws IllegalArgumentException if the region is invalid + */ + private int getCountryCodeForValidRegion(String regionCode) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + throw new IllegalArgumentException("Invalid region code: " + regionCode); + } + return metadata.getCountryCode(); + } + + /** + * Returns the national dialling prefix for a specific region. For example, this would be 1 for + * the United States, and 0 for New Zealand. Set stripNonDigits to true to strip symbols like "~" + * (which indicates a wait for a dialling tone) from the prefix returned. If no national prefix is + * present, we return null. + * + *

Warning: Do not use this method for do-your-own formatting - for some regions, the + * national dialling prefix is used only for certain types of numbers. Use the library's + * formatting functions to prefix the national prefix when required. + * + * @param regionCode the region that we want to get the dialling prefix for + * @param stripNonDigits true to strip non-digits from the national dialling prefix + * @return the dialling prefix for the region denoted by regionCode + */ + public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + logger.log(Level.WARNING, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); + return null; + } + String nationalPrefix = metadata.getNationalPrefix(); + // If no national prefix was found, we return null. + if (nationalPrefix.length() == 0) { + return null; + } + if (stripNonDigits) { + // Note: if any other non-numeric symbols are ever used in national prefixes, these would have + // to be removed here as well. + nationalPrefix = nationalPrefix.replace("~", ""); + } + return nationalPrefix; + } + + /** + * Checks if this is a region under the North American Numbering Plan Administration (NANPA). + * + * @return true if regionCode is one of the regions under NANPA + */ + public boolean isNANPACountry(String regionCode) { + return nanpaRegions.contains(regionCode); + } + + /** + * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. A valid vanity + * number will start with at least 3 digits and will have three or more alpha characters. This + * does not do region-specific checks - to work out if this number is actually valid for a region, + * it should be parsed and methods such as {@link #isPossibleNumberWithReason} and + * {@link #isValidNumber} should be used. + * + * @param number the number that needs to be checked + * @return true if the number is a valid vanity number + */ + public boolean isAlphaNumber(CharSequence number) { + if (!isViablePhoneNumber(number)) { + // Number is too short, or doesn't match the basic phone number pattern. + return false; + } + StringBuilder strippedNumber = new StringBuilder(number); + maybeStripExtension(strippedNumber); + return VALID_ALPHA_PHONE_PATTERN.matcher(strippedNumber).matches(); + } + + /** + * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of returning the reason + * for failure, this method returns true if the number is either a possible fully-qualified number + * (containing the area code and country code), or if the number could be a possible local number + * (with a country code, but missing an area code). Local numbers are considered possible if they + * could be possibly dialled in this format: if the area code is needed for a call to connect, the + * number is not considered possible without it. + * + * @param number the number that needs to be checked + * @return true if the number is possible + */ + public boolean isPossibleNumber(PhoneNumber number) { + ValidationResult result = isPossibleNumberWithReason(number); + return result == ValidationResult.IS_POSSIBLE + || result == ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + /** + * Convenience wrapper around {@link #isPossibleNumberForTypeWithReason}. Instead of returning the + * reason for failure, this method returns true if the number is either a possible fully-qualified + * number (containing the area code and country code), or if the number could be a possible local + * number (with a country code, but missing an area code). Local numbers are considered possible + * if they could be possibly dialled in this format: if the area code is needed for a call to + * connect, the number is not considered possible without it. + * + * @param number the number that needs to be checked + * @param type the type we are interested in + * @return true if the number is possible for this particular type + */ + public boolean isPossibleNumberForType(PhoneNumber number, PhoneNumberType type) { + ValidationResult result = isPossibleNumberForTypeWithReason(number, type); + return result == ValidationResult.IS_POSSIBLE + || result == ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + /** + * Helper method to check a number against possible lengths for this region, based on the metadata + * being passed in, and determine whether it matches, or is too short or too long. + */ + private ValidationResult testNumberLength(CharSequence number, PhoneMetadata metadata) { + return testNumberLength(number, metadata, PhoneNumberType.UNKNOWN); + } + + /** + * Helper method to check a number against possible lengths for this number type, and determine + * whether it matches, or is too short or too long. + */ + private ValidationResult testNumberLength( + CharSequence number, PhoneMetadata metadata, PhoneNumberType type) { + PhoneNumberDesc descForType = getNumberDescByType(metadata, type); + // There should always be "possibleLengths" set for every element. This is declared in the XML + // schema which is verified by PhoneNumberMetadataSchemaTest. + // For size efficiency, where a sub-description (e.g. fixed-line) has the same possibleLengths + // as the parent, this is missing, so we fall back to the general desc (where no numbers of the + // type exist at all, there is one possible length (-1) which is guaranteed not to match the + // length of any real phone number). + List possibleLengths = descForType.getPossibleLengthList().isEmpty() + ? metadata.getGeneralDesc().getPossibleLengthList() : descForType.getPossibleLengthList(); + + List localLengths = descForType.getPossibleLengthLocalOnlyList(); + + if (type == PhoneNumberType.FIXED_LINE_OR_MOBILE) { + if (!descHasPossibleNumberData(getNumberDescByType(metadata, PhoneNumberType.FIXED_LINE))) { + // The rare case has been encountered where no fixedLine data is available (true for some + // non-geographical entities), so we just check mobile. + return testNumberLength(number, metadata, PhoneNumberType.MOBILE); + } else { + PhoneNumberDesc mobileDesc = getNumberDescByType(metadata, PhoneNumberType.MOBILE); + if (descHasPossibleNumberData(mobileDesc)) { + // Merge the mobile data in if there was any. We have to make a copy to do this. + possibleLengths = new ArrayList<>(possibleLengths); + // Note that when adding the possible lengths from mobile, we have to again check they + // aren't empty since if they are this indicates they are the same as the general desc and + // should be obtained from there. + possibleLengths.addAll(mobileDesc.getPossibleLengthCount() == 0 + ? metadata.getGeneralDesc().getPossibleLengthList() + : mobileDesc.getPossibleLengthList()); + // The current list is sorted; we need to merge in the new list and re-sort (duplicates + // are okay). Sorting isn't so expensive because the lists are very small. + Collections.sort(possibleLengths); + + if (localLengths.isEmpty()) { + localLengths = mobileDesc.getPossibleLengthLocalOnlyList(); + } else { + localLengths = new ArrayList<>(localLengths); + localLengths.addAll(mobileDesc.getPossibleLengthLocalOnlyList()); + Collections.sort(localLengths); + } + } + } + } + + // If the type is not supported at all (indicated by the possible lengths containing -1 at this + // point) we return invalid length. + if (possibleLengths.get(0) == -1) { + return ValidationResult.INVALID_LENGTH; + } + + int actualLength = number.length(); + // This is safe because there is never an overlap beween the possible lengths and the local-only + // lengths; this is checked at build time. + if (localLengths.contains(actualLength)) { + return ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + int minimumLength = possibleLengths.get(0); + if (minimumLength == actualLength) { + return ValidationResult.IS_POSSIBLE; + } else if (minimumLength > actualLength) { + return ValidationResult.TOO_SHORT; + } else if (possibleLengths.get(possibleLengths.size() - 1) < actualLength) { + return ValidationResult.TOO_LONG; + } + // We skip the first element; we've already checked it. + return possibleLengths.subList(1, possibleLengths.size()).contains(actualLength) + ? ValidationResult.IS_POSSIBLE : ValidationResult.INVALID_LENGTH; + } + + /** + * Check whether a phone number is a possible number. It provides a more lenient check than + * {@link #isValidNumber} in the following sense: + *

    + *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting + * digits of the number. + *
  2. It doesn't attempt to figure out the type of the number, but uses general rules which + * applies to all types of phone numbers in a region. Therefore, it is much faster than + * isValidNumber. + *
  3. For some numbers (particularly fixed-line), many regions have the concept of area code, + * which together with subscriber number constitute the national significant number. It is + * sometimes okay to dial only the subscriber number when dialing in the same area. This + * function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is + * passed in. On the other hand, because isValidNumber validates using information on both + * starting digits (for fixed line numbers, that would most likely be area codes) and + * length (obviously includes the length of area codes for fixed line numbers), it will + * return false for the subscriber-number-only version. + *
+ * + *

There is a known issue with this + * method: if a number is possible only in a certain region among several regions that share the + * same country calling code, this method will consider only the "main" region. For example, + * +1310xxxx are valid numbers in Canada. However, they are not possible in the US. As a result, + * this method will return IS_POSSIBLE_LOCAL_ONLY for +1310xxxx. + * + * @param number the number that needs to be checked + * @return a ValidationResult object which indicates whether the number is possible + */ + public ValidationResult isPossibleNumberWithReason(PhoneNumber number) { + return isPossibleNumberForTypeWithReason(number, PhoneNumberType.UNKNOWN); + } + + /** + * Check whether a phone number is a possible number of a particular type. For types that don't + * exist in a particular region, this will return a result that isn't so useful; it is recommended + * that you use {@link #getSupportedTypesForRegion} or {@link #getSupportedTypesForNonGeoEntity} + * respectively before calling this method to determine whether you should call it for this number + * at all. + * + * This provides a more lenient check than {@link #isValidNumber} in the following sense: + * + *

    + *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting + * digits of the number. + *
  2. For some numbers (particularly fixed-line), many regions have the concept of area code, + * which together with subscriber number constitute the national significant number. It is + * sometimes okay to dial only the subscriber number when dialing in the same area. This + * function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is + * passed in. On the other hand, because isValidNumber validates using information on both + * starting digits (for fixed line numbers, that would most likely be area codes) and + * length (obviously includes the length of area codes for fixed line numbers), it will + * return false for the subscriber-number-only version. + *
+ * + *

There is a known issue with this + * method: if a number is possible only in a certain region among several regions that share the + * same country calling code, this method will consider only the "main" region. For example, + * +1310xxxx are valid numbers in Canada. However, they are not possible in the US. As a result, + * this method will return IS_POSSIBLE_LOCAL_ONLY for +1310xxxx. + * + * @param number the number that needs to be checked + * @param type the type we are interested in + * @return a ValidationResult object which indicates whether the number is possible + */ + public ValidationResult isPossibleNumberForTypeWithReason( + PhoneNumber number, PhoneNumberType type) { + String nationalNumber = getNationalSignificantNumber(number); + int countryCode = number.getCountryCode(); + // Note: For regions that share a country calling code, like NANPA numbers, we just use the + // rules from the default region (US in this case) since the getRegionCodeForNumber will not + // work if the number is possible but not valid. There is in fact one country calling code (290) + // where the possible number pattern differs between various regions (Saint Helena and Tristan + // da Cuñha), but this is handled by putting all possible lengths for any country with this + // country calling code in the metadata for the default region in this case. + if (!hasValidCountryCallingCode(countryCode)) { + return ValidationResult.INVALID_COUNTRY_CODE; + } + String regionCode = getRegionCodeForCountryCode(countryCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); + return testNumberLength(nationalNumber, metadata, type); + } + + /** + * Check whether a phone number is a possible number given a number in the form of a string, and + * the region where the number could be dialed from. It provides a more lenient check than + * {@link #isValidNumber}. See {@link #isPossibleNumber(PhoneNumber)} for details. + * + *

This method first parses the number, then invokes {@link #isPossibleNumber(PhoneNumber)} + * with the resultant PhoneNumber object. + * + * @param number the number that needs to be checked + * @param regionDialingFrom the region that we are expecting the number to be dialed from. + * Note this is different from the region where the number belongs. For example, the number + * +1 650 253 0000 is a number that belongs to US. When written in this form, it can be + * dialed from any region. When it is written as 00 1 650 253 0000, it can be dialed from any + * region which uses an international dialling prefix of 00. When it is written as + * 650 253 0000, it can only be dialed from within the US, and when written as 253 0000, it + * can only be dialed from within a smaller area in the US (Mountain View, CA, to be more + * specific). + * @return true if the number is possible + */ + public boolean isPossibleNumber(CharSequence number, String regionDialingFrom) { + try { + return isPossibleNumber(parse(number, regionDialingFrom)); + } catch (NumberParseException e) { + return false; + } + } + + /** + * Attempts to extract a valid number from a phone number that is too long to be valid, and resets + * the PhoneNumber object passed in to that valid version. If no valid number could be extracted, + * the PhoneNumber object passed in will not be modified. + * @param number a PhoneNumber object which contains a number that is too long to be valid + * @return true if a valid phone number can be successfully extracted + */ + public boolean truncateTooLongNumber(PhoneNumber number) { + if (isValidNumber(number)) { + return true; + } + PhoneNumber numberCopy = new PhoneNumber(); + numberCopy.mergeFrom(number); + long nationalNumber = number.getNationalNumber(); + do { + nationalNumber /= 10; + numberCopy.setNationalNumber(nationalNumber); + if (isPossibleNumberWithReason(numberCopy) == ValidationResult.TOO_SHORT + || nationalNumber == 0) { + return false; + } + } while (!isValidNumber(numberCopy)); + number.setNationalNumber(nationalNumber); + return true; + } + + /** + * Gets an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} for the specific region. + * + * @param regionCode the region where the phone number is being entered + * @return an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} object, which can be used + * to format phone numbers in the specific region "as you type" + */ + public AsYouTypeFormatter getAsYouTypeFormatter(String regionCode) { + return new AsYouTypeFormatter(regionCode); + } + + // Extracts country calling code from fullNumber, returns it and places the remaining number in + // nationalNumber. It assumes that the leading plus sign or IDD has already been removed. Returns + // 0 if fullNumber doesn't start with a valid country calling code, and leaves nationalNumber + // unmodified. + int extractCountryCode(StringBuilder fullNumber, StringBuilder nationalNumber) { + if ((fullNumber.length() == 0) || (fullNumber.charAt(0) == '0')) { + // Country codes do not begin with a '0'. + return 0; + } + int potentialCountryCode; + int numberLength = fullNumber.length(); + for (int i = 1; i <= MAX_LENGTH_COUNTRY_CODE && i <= numberLength; i++) { + potentialCountryCode = Integer.parseInt(fullNumber.substring(0, i)); + if (countryCallingCodeToRegionCodeMap.containsKey(potentialCountryCode)) { + nationalNumber.append(fullNumber.substring(i)); + return potentialCountryCode; + } + } + return 0; + } + + /** + * Tries to extract a country calling code from a number. This method will return zero if no + * country calling code is considered to be present. Country calling codes are extracted in the + * following ways: + *

    + *
  • by stripping the international dialing prefix of the region the person is dialing from, + * if this is present in the number, and looking at the next digits + *
  • by stripping the '+' sign if present and then looking at the next digits + *
  • by comparing the start of the number and the country calling code of the default region. + * If the number is not considered possible for the numbering plan of the default region + * initially, but starts with the country calling code of this region, validation will be + * reattempted after stripping this country calling code. If this number is considered a + * possible number, then the first digits will be considered the country calling code and + * removed as such. + *
+ * It will throw a NumberParseException if the number starts with a '+' but the country calling + * code supplied after this does not match that of any known region. + * + * @param number non-normalized telephone number that we wish to extract a country calling + * code from - may begin with '+' + * @param defaultRegionMetadata metadata about the region this number may be from + * @param nationalNumber a string buffer to store the national significant number in, in the case + * that a country calling code was extracted. The number is appended to any existing contents. + * If no country calling code was extracted, this will be left unchanged. + * @param keepRawInput true if the country_code_source and preferred_carrier_code fields of + * phoneNumber should be populated. + * @param phoneNumber the PhoneNumber object where the country_code and country_code_source need + * to be populated. Note the country_code is always populated, whereas country_code_source is + * only populated when keepCountryCodeSource is true. + * @return the country calling code extracted or 0 if none could be extracted + */ + // @VisibleForTesting + int maybeExtractCountryCode(CharSequence number, PhoneMetadata defaultRegionMetadata, + StringBuilder nationalNumber, boolean keepRawInput, + PhoneNumber phoneNumber) + throws NumberParseException { + if (number.length() == 0) { + return 0; + } + StringBuilder fullNumber = new StringBuilder(number); + // Set the default prefix to be something that will never match. + String possibleCountryIddPrefix = "NonMatch"; + if (defaultRegionMetadata != null) { + possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix(); + } + + CountryCodeSource countryCodeSource = + maybeStripInternationalPrefixAndNormalize(fullNumber, possibleCountryIddPrefix); + if (keepRawInput) { + phoneNumber.setCountryCodeSource(countryCodeSource); + } + if (countryCodeSource != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + if (fullNumber.length() <= MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD, + "Phone number had an IDD, but after this was not " + + "long enough to be a viable phone number."); + } + int potentialCountryCode = extractCountryCode(fullNumber, nationalNumber); + if (potentialCountryCode != 0) { + phoneNumber.setCountryCode(potentialCountryCode); + return potentialCountryCode; + } + + // If this fails, they must be using a strange country calling code that we don't recognize, + // or that doesn't exist. + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Country calling code supplied was not recognised."); + } else if (defaultRegionMetadata != null) { + // Check to see if the number starts with the country calling code for the default region. If + // so, we remove the country calling code, and do some checks on the validity of the number + // before and after. + int defaultCountryCode = defaultRegionMetadata.getCountryCode(); + String defaultCountryCodeString = String.valueOf(defaultCountryCode); + String normalizedNumber = fullNumber.toString(); + if (normalizedNumber.startsWith(defaultCountryCodeString)) { + StringBuilder potentialNationalNumber = + new StringBuilder(normalizedNumber.substring(defaultCountryCodeString.length())); + PhoneNumberDesc generalDesc = defaultRegionMetadata.getGeneralDesc(); + maybeStripNationalPrefixAndCarrierCode( + potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */); + // If the number was not valid before but is valid now, or if it was too long before, we + // consider the number with the country calling code stripped to be a better result and + // keep that instead. + if ((!matcherApi.matchNationalNumber(fullNumber, generalDesc, false) + && matcherApi.matchNationalNumber(potentialNationalNumber, generalDesc, false)) + || testNumberLength(fullNumber, defaultRegionMetadata) == ValidationResult.TOO_LONG) { + nationalNumber.append(potentialNationalNumber); + if (keepRawInput) { + phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); + } + phoneNumber.setCountryCode(defaultCountryCode); + return defaultCountryCode; + } + } + } + // No country calling code present. + phoneNumber.setCountryCode(0); + return 0; + } + + /** + * Strips the IDD from the start of the number if present. Helper function used by + * maybeStripInternationalPrefixAndNormalize. + */ + private boolean parsePrefixAsIdd(Pattern iddPattern, StringBuilder number) { + Matcher m = iddPattern.matcher(number); + if (m.lookingAt()) { + int matchEnd = m.end(); + // Only strip this if the first digit after the match is not a 0, since country calling codes + // cannot begin with 0. + Matcher digitMatcher = CAPTURING_DIGIT_PATTERN.matcher(number.substring(matchEnd)); + if (digitMatcher.find()) { + String normalizedGroup = normalizeDigitsOnly(digitMatcher.group(1)); + if (normalizedGroup.equals("0")) { + return false; + } + } + number.delete(0, matchEnd); + return true; + } + return false; + } + + /** + * Strips any international prefix (such as +, 00, 011) present in the number provided, normalizes + * the resulting number, and indicates if an international prefix was present. + * + * @param number the non-normalized telephone number that we wish to strip any international + * dialing prefix from + * @param possibleIddPrefix the international direct dialing prefix from the region we + * think this number may be dialed in + * @return the corresponding CountryCodeSource if an international dialing prefix could be + * removed from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if the number did + * not seem to be in international format + */ + // @VisibleForTesting + CountryCodeSource maybeStripInternationalPrefixAndNormalize( + StringBuilder number, + String possibleIddPrefix) { + if (number.length() == 0) { + return CountryCodeSource.FROM_DEFAULT_COUNTRY; + } + // Check to see if the number begins with one or more plus signs. + Matcher m = PLUS_CHARS_PATTERN.matcher(number); + if (m.lookingAt()) { + number.delete(0, m.end()); + // Can now normalize the rest of the number since we've consumed the "+" sign at the start. + normalize(number); + return CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN; + } + // Attempt to parse the first digits as an international prefix. + Pattern iddPattern = regexCache.getPatternForRegex(possibleIddPrefix); + normalize(number); + return parsePrefixAsIdd(iddPattern, number) + ? CountryCodeSource.FROM_NUMBER_WITH_IDD + : CountryCodeSource.FROM_DEFAULT_COUNTRY; + } + + /** + * Strips any national prefix (such as 0, 1) present in the number provided. + * + * @param number the normalized telephone number that we wish to strip any national + * dialing prefix from + * @param metadata the metadata for the region that we think this number is from + * @param carrierCode a place to insert the carrier code if one is extracted + * @return true if a national prefix or carrier code (or both) could be extracted + */ + // @VisibleForTesting + boolean maybeStripNationalPrefixAndCarrierCode( + StringBuilder number, PhoneMetadata metadata, StringBuilder carrierCode) { + int numberLength = number.length(); + String possibleNationalPrefix = metadata.getNationalPrefixForParsing(); + if (numberLength == 0 || possibleNationalPrefix.length() == 0) { + // Early return for numbers of zero length. + return false; + } + // Attempt to parse the first digits as a national prefix. + Matcher prefixMatcher = regexCache.getPatternForRegex(possibleNationalPrefix).matcher(number); + if (prefixMatcher.lookingAt()) { + PhoneNumberDesc generalDesc = metadata.getGeneralDesc(); + // Check if the original number is viable. + boolean isViableOriginalNumber = matcherApi.matchNationalNumber(number, generalDesc, false); + // prefixMatcher.group(numOfGroups) == null implies nothing was captured by the capturing + // groups in possibleNationalPrefix; therefore, no transformation is necessary, and we just + // remove the national prefix. + int numOfGroups = prefixMatcher.groupCount(); + String transformRule = metadata.getNationalPrefixTransformRule(); + if (transformRule == null || transformRule.length() == 0 + || prefixMatcher.group(numOfGroups) == null) { + // If the original number was viable, and the resultant number is not, we return. + if (isViableOriginalNumber + && !matcherApi.matchNationalNumber( + number.substring(prefixMatcher.end()), generalDesc, false)) { + return false; + } + if (carrierCode != null && numOfGroups > 0 && prefixMatcher.group(numOfGroups) != null) { + carrierCode.append(prefixMatcher.group(1)); + } + number.delete(0, prefixMatcher.end()); + return true; + } else { + // Check that the resultant number is still viable. If not, return. Check this by copying + // the string buffer and making the transformation on the copy first. + StringBuilder transformedNumber = new StringBuilder(number); + transformedNumber.replace(0, numberLength, prefixMatcher.replaceFirst(transformRule)); + if (isViableOriginalNumber + && !matcherApi.matchNationalNumber(transformedNumber.toString(), generalDesc, false)) { + return false; + } + if (carrierCode != null && numOfGroups > 1) { + carrierCode.append(prefixMatcher.group(1)); + } + number.replace(0, number.length(), transformedNumber.toString()); + return true; + } + } + return false; + } + + /** + * Strips any extension (as in, the part of the number dialled after the call is connected, + * usually indicated with extn, ext, x or similar) from the end of the number, and returns it. + * + * @param number the non-normalized telephone number that we wish to strip the extension from + * @return the phone extension + */ + // @VisibleForTesting + String maybeStripExtension(StringBuilder number) { + Matcher m = EXTN_PATTERN.matcher(number); + // If we find a potential extension, and the number preceding this is a viable number, we assume + // it is an extension. + if (m.find() && isViablePhoneNumber(number.substring(0, m.start()))) { + // The numbers are captured into groups in the regular expression. + for (int i = 1, length = m.groupCount(); i <= length; i++) { + if (m.group(i) != null) { + // We go through the capturing groups until we find one that captured some digits. If none + // did, then we will return the empty string. + String extension = m.group(i); + number.delete(m.start(), number.length()); + return extension; + } + } + } + return ""; + } + + /** + * Checks to see that the region code used is valid, or if it is not valid, that the number to + * parse starts with a + symbol so that we can attempt to infer the region from the number. + * Returns false if it cannot use the region provided and the region cannot be inferred. + */ + private boolean checkRegionForParsing(CharSequence numberToParse, String defaultRegion) { + if (!isValidRegionCode(defaultRegion)) { + // If the number is null or empty, we can't infer the region. + if ((numberToParse == null) || (numberToParse.length() == 0) + || !PLUS_CHARS_PATTERN.matcher(numberToParse).lookingAt()) { + return false; + } + } + return true; + } + + /** + * Parses a string and returns it as a phone number in proto buffer format. The method is quite + * lenient and looks for a number in the input text (raw input) and does not check whether the + * string is definitely only a phone number. To do this, it ignores punctuation and white-space, + * as well as any text before the number (e.g. a leading "Tel: ") and trims the non-number bits. + * It will accept a number in any format (E164, national, international etc), assuming it can be + * interpreted with the defaultRegion supplied. It also attempts to convert any alpha characters + * into digits if it thinks this is a vanity number of the type "1800 MICROSOFT". + * + *

This method will throw a {@link com.google.i18n.phonenumbers.NumberParseException} if the + * number is not considered to be a possible number. Note that validation of whether the number + * is actually a valid number for a particular region is not performed. This can be done + * separately with {@link #isValidNumber}. + * + *

Note this method canonicalizes the phone number such that different representations can be + * easily compared, no matter what form it was originally entered in (e.g. national, + * international). If you want to record context about the number being parsed, such as the raw + * input that was entered, how the country code was derived etc. then call {@link + * #parseAndKeepRawInput} instead. + * + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. It can also be provided in RFC3966 + * format. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. If the number + * is guaranteed to start with a '+' followed by the country calling code, then RegionCode.ZZ + * or null can be supplied. + * @return a phone number proto buffer filled with the parsed number + * @throws NumberParseException if the string is not considered to be a viable phone number (e.g. + * too few or too many digits) or if no default region was supplied and the number is not in + * international format (does not start with +) + */ + public PhoneNumber parse(CharSequence numberToParse, String defaultRegion) + throws NumberParseException { + PhoneNumber phoneNumber = new PhoneNumber(); + parse(numberToParse, defaultRegion, phoneNumber); + return phoneNumber; + } + + /** + * Same as {@link #parse(CharSequence, String)}, but accepts mutable PhoneNumber as a + * parameter to decrease object creation when invoked many times. + */ + public void parse(CharSequence numberToParse, String defaultRegion, PhoneNumber phoneNumber) + throws NumberParseException { + parseHelper(numberToParse, defaultRegion, false, true, phoneNumber); + } + + /** + * Parses a string and returns it in proto buffer format. This method differs from {@link #parse} + * in that it always populates the raw_input field of the protocol buffer with numberToParse as + * well as the country_code_source field. + * + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country calling code + * for the number in this case would be stored as that of the default region supplied. + * @return a phone number proto buffer filled with the parsed number + * @throws NumberParseException if the string is not considered to be a viable phone number or if + * no default region was supplied + */ + public PhoneNumber parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion) + throws NumberParseException { + PhoneNumber phoneNumber = new PhoneNumber(); + parseAndKeepRawInput(numberToParse, defaultRegion, phoneNumber); + return phoneNumber; + } + + /** + * Same as{@link #parseAndKeepRawInput(CharSequence, String)}, but accepts a mutable + * PhoneNumber as a parameter to decrease object creation when invoked many times. + */ + public void parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion, + PhoneNumber phoneNumber) + throws NumberParseException { + parseHelper(numberToParse, defaultRegion, true, true, phoneNumber); + } + + /** + * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. This + * is a shortcut for {@link #findNumbers(CharSequence, String, Leniency, long) + * getMatcher(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE)}. + * + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. + */ + public Iterable findNumbers(CharSequence text, String defaultRegion) { + return findNumbers(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE); + } + + /** + * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. + * + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. + * @param leniency the leniency to use when evaluating candidate phone numbers + * @param maxTries the maximum number of invalid numbers to try before giving up on the text. + * This is to cover degenerate cases where the text has a lot of false positives in it. Must + * be {@code >= 0}. + */ + public Iterable findNumbers( + final CharSequence text, final String defaultRegion, final Leniency leniency, + final long maxTries) { + + return new Iterable() { + @Override + public Iterator iterator() { + return new PhoneNumberMatcher( + PhoneNumberUtil.this, text, defaultRegion, leniency, maxTries); + } + }; + } + + /** + * A helper function to set the values related to leading zeros in a PhoneNumber. + */ + static void setItalianLeadingZerosForPhoneNumber(CharSequence nationalNumber, + PhoneNumber phoneNumber) { + if (nationalNumber.length() > 1 && nationalNumber.charAt(0) == '0') { + phoneNumber.setItalianLeadingZero(true); + int numberOfLeadingZeros = 1; + // Note that if the national number is all "0"s, the last "0" is not counted as a leading + // zero. + while (numberOfLeadingZeros < nationalNumber.length() - 1 + && nationalNumber.charAt(numberOfLeadingZeros) == '0') { + numberOfLeadingZeros++; + } + if (numberOfLeadingZeros != 1) { + phoneNumber.setNumberOfLeadingZeros(numberOfLeadingZeros); + } + } + } + + /** + * Parses a string and fills up the phoneNumber. This method is the same as the public + * parse() method, with the exception that it allows the default region to be null, for use by + * isNumberMatch(). checkRegion should be set to false if it is permitted for the default region + * to be null or unknown ("ZZ"). + * + * Note if any new field is added to this method that should always be filled in, even when + * keepRawInput is false, it should also be handled in the copyCoreFieldsOnly() method. + */ + private void parseHelper(CharSequence numberToParse, String defaultRegion, + boolean keepRawInput, boolean checkRegion, PhoneNumber phoneNumber) + throws NumberParseException { + if (numberToParse == null) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The phone number supplied was null."); + } else if (numberToParse.length() > MAX_INPUT_STRING_LENGTH) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG, + "The string supplied was too long to parse."); + } + + StringBuilder nationalNumber = new StringBuilder(); + String numberBeingParsed = numberToParse.toString(); + buildNationalNumberForParsing(numberBeingParsed, nationalNumber); + + if (!isViablePhoneNumber(nationalNumber)) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The string supplied did not seem to be a phone number."); + } + + // Check the region supplied is valid, or that the extracted number starts with some sort of + + // sign so the number's region can be determined. + if (checkRegion && !checkRegionForParsing(nationalNumber, defaultRegion)) { + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Missing or invalid default region."); + } + + if (keepRawInput) { + phoneNumber.setRawInput(numberBeingParsed); + } + // Attempt to parse extension first, since it doesn't require region-specific data and we want + // to have the non-normalised number here. + String extension = maybeStripExtension(nationalNumber); + if (extension.length() > 0) { + phoneNumber.setExtension(extension); + } + + PhoneMetadata regionMetadata = getMetadataForRegion(defaultRegion); + // Check to see if the number is given in international format so we know whether this number is + // from the default region or not. + StringBuilder normalizedNationalNumber = new StringBuilder(); + int countryCode = 0; + try { + // TODO: This method should really just take in the string buffer that has already + // been created, and just remove the prefix, rather than taking in a string and then + // outputting a string buffer. + countryCode = maybeExtractCountryCode(nationalNumber, regionMetadata, + normalizedNationalNumber, keepRawInput, phoneNumber); + } catch (NumberParseException e) { + Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber); + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE + && matcher.lookingAt()) { + // Strip the plus-char, and try again. + countryCode = maybeExtractCountryCode(nationalNumber.substring(matcher.end()), + regionMetadata, normalizedNationalNumber, + keepRawInput, phoneNumber); + if (countryCode == 0) { + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Could not interpret numbers after plus-sign."); + } + } else { + throw new NumberParseException(e.getErrorType(), e.getMessage()); + } + } + if (countryCode != 0) { + String phoneNumberRegion = getRegionCodeForCountryCode(countryCode); + if (!phoneNumberRegion.equals(defaultRegion)) { + // Metadata cannot be null because the country calling code is valid. + regionMetadata = getMetadataForRegionOrCallingCode(countryCode, phoneNumberRegion); + } + } else { + // If no extracted country calling code, use the region supplied instead. The national number + // is just the normalized version of the number we were given to parse. + normalizedNationalNumber.append(normalize(nationalNumber)); + if (defaultRegion != null) { + countryCode = regionMetadata.getCountryCode(); + phoneNumber.setCountryCode(countryCode); + } else if (keepRawInput) { + phoneNumber.clearCountryCodeSource(); + } + } + if (normalizedNationalNumber.length() < MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN, + "The string supplied is too short to be a phone number."); + } + if (regionMetadata != null) { + StringBuilder carrierCode = new StringBuilder(); + StringBuilder potentialNationalNumber = new StringBuilder(normalizedNationalNumber); + maybeStripNationalPrefixAndCarrierCode(potentialNationalNumber, regionMetadata, carrierCode); + // We require that the NSN remaining after stripping the national prefix and carrier code be + // long enough to be a possible length for the region. Otherwise, we don't do the stripping, + // since the original number could be a valid short number. + ValidationResult validationResult = testNumberLength(potentialNationalNumber, regionMetadata); + if (validationResult != ValidationResult.TOO_SHORT + && validationResult != ValidationResult.IS_POSSIBLE_LOCAL_ONLY + && validationResult != ValidationResult.INVALID_LENGTH) { + normalizedNationalNumber = potentialNationalNumber; + if (keepRawInput && carrierCode.length() > 0) { + phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString()); + } + } + } + int lengthOfNationalNumber = normalizedNationalNumber.length(); + if (lengthOfNationalNumber < MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN, + "The string supplied is too short to be a phone number."); + } + if (lengthOfNationalNumber > MAX_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG, + "The string supplied is too long to be a phone number."); + } + setItalianLeadingZerosForPhoneNumber(normalizedNationalNumber, phoneNumber); + phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString())); + } + + /** + * Extracts the value of the phone-context parameter of numberToExtractFrom where the index of + * ";phone-context=" is the parameter indexOfPhoneContext, following the syntax defined in + * RFC3966. + * + * @return the extracted string (possibly empty), or null if no phone-context parameter is found. + */ + private String extractPhoneContext(String numberToExtractFrom, int indexOfPhoneContext) { + // If no phone-context parameter is present + if (indexOfPhoneContext == -1) { + return null; + } + + int phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT.length(); + // If phone-context parameter is empty + if (phoneContextStart >= numberToExtractFrom.length()) { + return ""; + } + + int phoneContextEnd = numberToExtractFrom.indexOf(';', phoneContextStart); + // If phone-context is not the last parameter + if (phoneContextEnd != -1) { + return numberToExtractFrom.substring(phoneContextStart, phoneContextEnd); + } else { + return numberToExtractFrom.substring(phoneContextStart); + } + } + + /** + * Returns whether the value of phoneContext follows the syntax defined in RFC3966. + */ + private boolean isPhoneContextValid(String phoneContext) { + if (phoneContext == null) { + return true; + } + if (phoneContext.length() == 0) { + return false; + } + + // Does phone-context value match pattern of global-number-digits or domainname + return RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN.matcher(phoneContext).matches() + || RFC3966_DOMAINNAME_PATTERN.matcher(phoneContext).matches(); + } + + /** + * Converts numberToParse to a form that we can parse and write it to nationalNumber if it is + * written in RFC3966; otherwise extract a possible number out of it and write to nationalNumber. + */ + private void buildNationalNumberForParsing(String numberToParse, StringBuilder nationalNumber) + throws NumberParseException { + int indexOfPhoneContext = numberToParse.indexOf(RFC3966_PHONE_CONTEXT); + + String phoneContext = extractPhoneContext(numberToParse, indexOfPhoneContext); + if (!isPhoneContextValid(phoneContext)) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The phone-context value is invalid."); + } + if (phoneContext != null) { + // If the phone context contains a phone number prefix, we need to capture it, whereas domains + // will be ignored. + if (phoneContext.charAt(0) == PLUS_SIGN) { + // Additional parameters might follow the phone context. If so, we will remove them here + // because the parameters after phone context are not important for parsing the phone + // number. + nationalNumber.append(phoneContext); + } + + // Now append everything between the "tel:" prefix and the phone-context. This should include + // the national number, an optional extension or isdn-subaddress component. Note we also + // handle the case when "tel:" is missing, as we have seen in some of the phone number inputs. + // In that case, we append everything from the beginning. + int indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX); + int indexOfNationalNumber = + (indexOfRfc3966Prefix >= 0) ? indexOfRfc3966Prefix + RFC3966_PREFIX.length() : 0; + nationalNumber.append(numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext)); + } else { + // Extract a possible number from the string passed in (this strips leading characters that + // could not be the start of a phone number.) + nationalNumber.append(extractPossibleNumber(numberToParse)); + } + + // Delete the isdn-subaddress and everything after it if it is present. Note extension won't + // appear at the same time with isdn-subaddress according to paragraph 5.3 of the RFC3966 spec, + int indexOfIsdn = nationalNumber.indexOf(RFC3966_ISDN_SUBADDRESS); + if (indexOfIsdn > 0) { + nationalNumber.delete(indexOfIsdn, nationalNumber.length()); + } + // If both phone context and isdn-subaddress are absent but other parameters are present, the + // parameters are left in nationalNumber. This is because we are concerned about deleting + // content from a potential number string when there is no strong evidence that the number is + // actually written in RFC3966. + } + + /** + * Returns a new phone number containing only the fields needed to uniquely identify a phone + * number, rather than any fields that capture the context in which the phone number was created. + * These fields correspond to those set in parse() rather than parseAndKeepRawInput(). + */ + private static PhoneNumber copyCoreFieldsOnly(PhoneNumber phoneNumberIn) { + PhoneNumber phoneNumber = new PhoneNumber(); + phoneNumber.setCountryCode(phoneNumberIn.getCountryCode()); + phoneNumber.setNationalNumber(phoneNumberIn.getNationalNumber()); + if (phoneNumberIn.getExtension().length() > 0) { + phoneNumber.setExtension(phoneNumberIn.getExtension()); + } + if (phoneNumberIn.isItalianLeadingZero()) { + phoneNumber.setItalianLeadingZero(true); + // This field is only relevant if there are leading zeros at all. + phoneNumber.setNumberOfLeadingZeros(phoneNumberIn.getNumberOfLeadingZeros()); + } + return phoneNumber; + } + + /** + * Takes two phone numbers and compares them for equality. + * + *

Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero for Italian numbers + * and any extension present are the same. + * Returns NSN_MATCH if either or both has no region specified, and the NSNs and extensions are + * the same. + * Returns SHORT_NSN_MATCH if either or both has no region specified, or the region specified is + * the same, and one NSN could be a shorter version of the other number. This includes the case + * where one has an extension specified, and the other does not. + * Returns NO_MATCH otherwise. + * For example, the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. + * The numbers +1 345 657 1234 and 345 657 are a NO_MATCH. + * + * @param firstNumberIn first number to compare + * @param secondNumberIn second number to compare + * + * @return NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of equality + * of the two numbers, described in the method definition. + */ + public MatchType isNumberMatch(PhoneNumber firstNumberIn, PhoneNumber secondNumberIn) { + // We only care about the fields that uniquely define a number, so we copy these across + // explicitly. + PhoneNumber firstNumber = copyCoreFieldsOnly(firstNumberIn); + PhoneNumber secondNumber = copyCoreFieldsOnly(secondNumberIn); + // Early exit if both had extensions and these are different. + if (firstNumber.hasExtension() && secondNumber.hasExtension() + && !firstNumber.getExtension().equals(secondNumber.getExtension())) { + return MatchType.NO_MATCH; + } + int firstNumberCountryCode = firstNumber.getCountryCode(); + int secondNumberCountryCode = secondNumber.getCountryCode(); + // Both had country_code specified. + if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) { + if (firstNumber.exactlySameAs(secondNumber)) { + return MatchType.EXACT_MATCH; + } else if (firstNumberCountryCode == secondNumberCountryCode + && isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { + // A SHORT_NSN_MATCH occurs if there is a difference because of the presence or absence of + // an 'Italian leading zero', the presence or absence of an extension, or one NSN being a + // shorter variant of the other. + return MatchType.SHORT_NSN_MATCH; + } + // This is not a match. + return MatchType.NO_MATCH; + } + // Checks cases where one or both country_code fields were not specified. To make equality + // checks easier, we first set the country_code fields to be equal. + firstNumber.setCountryCode(secondNumberCountryCode); + // If all else was the same, then this is an NSN_MATCH. + if (firstNumber.exactlySameAs(secondNumber)) { + return MatchType.NSN_MATCH; + } + if (isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { + return MatchType.SHORT_NSN_MATCH; + } + return MatchType.NO_MATCH; + } + + // Returns true when one national number is the suffix of the other or both are the same. + private boolean isNationalNumberSuffixOfTheOther(PhoneNumber firstNumber, + PhoneNumber secondNumber) { + String firstNumberNationalNumber = String.valueOf(firstNumber.getNationalNumber()); + String secondNumberNationalNumber = String.valueOf(secondNumber.getNationalNumber()); + // Note that endsWith returns true if the numbers are equal. + return firstNumberNationalNumber.endsWith(secondNumberNationalNumber) + || secondNumberNationalNumber.endsWith(firstNumberNationalNumber); + } + + /** + * Takes two phone numbers as strings and compares them for equality. This is a convenience + * wrapper for {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known. + * + * @param firstNumber first number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @param secondNumber second number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. + */ + public MatchType isNumberMatch(CharSequence firstNumber, CharSequence secondNumber) { + try { + PhoneNumber firstNumberAsProto = parse(firstNumber, UNKNOWN_REGION); + return isNumberMatch(firstNumberAsProto, secondNumber); + } catch (NumberParseException e) { + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + try { + PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION); + return isNumberMatch(secondNumberAsProto, firstNumber); + } catch (NumberParseException e2) { + if (e2.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + try { + PhoneNumber firstNumberProto = new PhoneNumber(); + PhoneNumber secondNumberProto = new PhoneNumber(); + parseHelper(firstNumber, null, false, false, firstNumberProto); + parseHelper(secondNumber, null, false, false, secondNumberProto); + return isNumberMatch(firstNumberProto, secondNumberProto); + } catch (NumberParseException e3) { + // Fall through and return MatchType.NOT_A_NUMBER. + } + } + } + } + } + // One or more of the phone numbers we are trying to match is not a viable phone number. + return MatchType.NOT_A_NUMBER; + } + + /** + * Takes two phone numbers and compares them for equality. This is a convenience wrapper for + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known. + * + * @param firstNumber first number to compare in proto buffer format + * @param secondNumber second number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. + */ + public MatchType isNumberMatch(PhoneNumber firstNumber, CharSequence secondNumber) { + // First see if the second number has an implicit country calling code, by attempting to parse + // it. + try { + PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION); + return isNumberMatch(firstNumber, secondNumberAsProto); + } catch (NumberParseException e) { + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + // The second number has no country calling code. EXACT_MATCH is no longer possible. + // We parse it as if the region was the same as that for the first number, and if + // EXACT_MATCH is returned, we replace this with NSN_MATCH. + String firstNumberRegion = getRegionCodeForCountryCode(firstNumber.getCountryCode()); + try { + if (!firstNumberRegion.equals(UNKNOWN_REGION)) { + PhoneNumber secondNumberWithFirstNumberRegion = parse(secondNumber, firstNumberRegion); + MatchType match = isNumberMatch(firstNumber, secondNumberWithFirstNumberRegion); + if (match == MatchType.EXACT_MATCH) { + return MatchType.NSN_MATCH; + } + return match; + } else { + // If the first number didn't have a valid country calling code, then we parse the + // second number without one as well. + PhoneNumber secondNumberProto = new PhoneNumber(); + parseHelper(secondNumber, null, false, false, secondNumberProto); + return isNumberMatch(firstNumber, secondNumberProto); + } + } catch (NumberParseException e2) { + // Fall-through to return NOT_A_NUMBER. + } + } + } + // One or more of the phone numbers we are trying to match is not a viable phone number. + return MatchType.NOT_A_NUMBER; + } + + /** + * Returns true if the number can be dialled from outside the region, or unknown. If the number + * can only be dialled from within the region, returns false. Does not check the number is a valid + * number. Note that, at the moment, this method does not handle short numbers (which are + * currently all presumed to not be diallable from outside their country). + * + * @param number the phone-number for which we want to know whether it is diallable from + * outside the region + */ + public boolean canBeInternationallyDialled(PhoneNumber number) { + PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number)); + if (metadata == null) { + // Note numbers belonging to non-geographical entities (e.g. +800 numbers) are always + // internationally diallable, and will be caught here. + return true; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return !isNumberMatchingDesc(nationalSignificantNumber, metadata.getNoInternationalDialling()); + } + + /** + * Returns true if the supplied region supports mobile number portability. Returns false for + * invalid, unknown or regions that don't support mobile number portability. + * + * @param regionCode the region for which we want to know whether it supports mobile number + * portability or not + */ + public boolean isMobileNumberPortableRegion(String regionCode) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return false; + } + return metadata.getMobileNumberPortableRegion(); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonemetadata.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonemetadata.java new file mode 100644 index 0000000000..914c796368 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonemetadata.java @@ -0,0 +1,1188 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Definition of the class representing metadata for international telephone numbers. This class is + * hand created based on the class file compiled from phonemetadata.proto. Please refer to that file + * for detailed descriptions of the meaning of each field. + * + *

WARNING: This API isn't stable. It is considered libphonenumber-internal and can change at any + * time. We only declare it as public for easy inclusion in our build tools not in this package. + * Clients should not refer to this file, we do not commit to support backwards-compatibility or to + * warn about breaking changes. + */ + +package com.google.i18n.phonenumbers; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public final class Phonemetadata { + private Phonemetadata() {} + public static class NumberFormat implements Externalizable { + private static final long serialVersionUID = 1; + public NumberFormat() {} + + /** + * Provides a dummy builder to 'emulate' the API of the code generated by the latest version of + * Protocol Buffers. This lets BuildMetadataFromXml class to build with both this hand created + * class and the one generated by the latest version of Protocol Buffers. + */ + public static final class Builder extends NumberFormat { + public NumberFormat build() { + return this; + } + + public Builder mergeFrom(NumberFormat other) { + if (other.hasPattern()) { + setPattern(other.getPattern()); + } + if (other.hasFormat()) { + setFormat(other.getFormat()); + } + for (int i = 0; i < other.leadingDigitsPatternSize(); i++) { + addLeadingDigitsPattern(other.getLeadingDigitsPattern(i)); + } + if (other.hasNationalPrefixFormattingRule()) { + setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule()); + } + if (other.hasDomesticCarrierCodeFormattingRule()) { + setDomesticCarrierCodeFormattingRule(other.getDomesticCarrierCodeFormattingRule()); + } + if (other.hasNationalPrefixOptionalWhenFormatting()) { + setNationalPrefixOptionalWhenFormatting(other.getNationalPrefixOptionalWhenFormatting()); + } + return this; + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + // required string pattern = 1; + private boolean hasPattern; + private String pattern_ = ""; + public boolean hasPattern() { return hasPattern; } + public String getPattern() { return pattern_; } + public NumberFormat setPattern(String value) { + hasPattern = true; + pattern_ = value; + return this; + } + + // required string format = 2; + private boolean hasFormat; + private String format_ = ""; + public boolean hasFormat() { return hasFormat; } + public String getFormat() { return format_; } + public NumberFormat setFormat(String value) { + hasFormat = true; + format_ = value; + return this; + } + + // repeated string leading_digits_pattern = 3; + private java.util.List leadingDigitsPattern_ = new java.util.ArrayList(); + public java.util.List leadingDigitPatterns() { + return leadingDigitsPattern_; + } + @Deprecated + public int leadingDigitsPatternSize() { return getLeadingDigitsPatternCount(); } + public int getLeadingDigitsPatternCount() { return leadingDigitsPattern_.size(); } + public String getLeadingDigitsPattern(int index) { + return leadingDigitsPattern_.get(index); + } + public NumberFormat addLeadingDigitsPattern(String value) { + if (value == null) { + throw new NullPointerException(); + } + leadingDigitsPattern_.add(value); + return this; + } + + // optional string national_prefix_formatting_rule = 4; + private boolean hasNationalPrefixFormattingRule; + private String nationalPrefixFormattingRule_ = ""; + public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; } + public String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; } + public NumberFormat setNationalPrefixFormattingRule(String value) { + hasNationalPrefixFormattingRule = true; + nationalPrefixFormattingRule_ = value; + return this; + } + public NumberFormat clearNationalPrefixFormattingRule() { + hasNationalPrefixFormattingRule = false; + nationalPrefixFormattingRule_ = ""; + return this; + } + + // optional bool national_prefix_optional_when_formatting = 6 [default = false]; + private boolean hasNationalPrefixOptionalWhenFormatting; + private boolean nationalPrefixOptionalWhenFormatting_ = false; + public boolean hasNationalPrefixOptionalWhenFormatting() { + return hasNationalPrefixOptionalWhenFormatting; } + public boolean getNationalPrefixOptionalWhenFormatting() { + return nationalPrefixOptionalWhenFormatting_; } + public NumberFormat setNationalPrefixOptionalWhenFormatting(boolean value) { + hasNationalPrefixOptionalWhenFormatting = true; + nationalPrefixOptionalWhenFormatting_ = value; + return this; + } + + // optional string domestic_carrier_code_formatting_rule = 5; + private boolean hasDomesticCarrierCodeFormattingRule; + private String domesticCarrierCodeFormattingRule_ = ""; + public boolean hasDomesticCarrierCodeFormattingRule() { + return hasDomesticCarrierCodeFormattingRule; } + public String getDomesticCarrierCodeFormattingRule() { + return domesticCarrierCodeFormattingRule_; } + public NumberFormat setDomesticCarrierCodeFormattingRule(String value) { + hasDomesticCarrierCodeFormattingRule = true; + domesticCarrierCodeFormattingRule_ = value; + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeUTF(pattern_); + objectOutput.writeUTF(format_); + int leadingDigitsPatternSize = leadingDigitsPatternSize(); + objectOutput.writeInt(leadingDigitsPatternSize); + for (int i = 0; i < leadingDigitsPatternSize; i++) { + objectOutput.writeUTF(leadingDigitsPattern_.get(i)); + } + + objectOutput.writeBoolean(hasNationalPrefixFormattingRule); + if (hasNationalPrefixFormattingRule) { + objectOutput.writeUTF(nationalPrefixFormattingRule_); + } + objectOutput.writeBoolean(hasDomesticCarrierCodeFormattingRule); + if (hasDomesticCarrierCodeFormattingRule) { + objectOutput.writeUTF(domesticCarrierCodeFormattingRule_); + } + objectOutput.writeBoolean(nationalPrefixOptionalWhenFormatting_); + } + + public void readExternal(ObjectInput objectInput) throws IOException { + setPattern(objectInput.readUTF()); + setFormat(objectInput.readUTF()); + int leadingDigitsPatternSize = objectInput.readInt(); + for (int i = 0; i < leadingDigitsPatternSize; i++) { + leadingDigitsPattern_.add(objectInput.readUTF()); + } + if (objectInput.readBoolean()) { + setNationalPrefixFormattingRule(objectInput.readUTF()); + } + if (objectInput.readBoolean()) { + setDomesticCarrierCodeFormattingRule(objectInput.readUTF()); + } + setNationalPrefixOptionalWhenFormatting(objectInput.readBoolean()); + } + } + + public static class PhoneNumberDesc implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneNumberDesc() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneNumberDesc { + public PhoneNumberDesc build() { + return this; + } + + public Builder mergeFrom(PhoneNumberDesc other) { + if (other.hasNationalNumberPattern()) { + setNationalNumberPattern(other.getNationalNumberPattern()); + } + for (int i = 0; i < other.getPossibleLengthCount(); i++) { + addPossibleLength(other.getPossibleLength(i)); + } + for (int i = 0; i < other.getPossibleLengthLocalOnlyCount(); i++) { + addPossibleLengthLocalOnly(other.getPossibleLengthLocalOnly(i)); + } + if (other.hasExampleNumber()) { + setExampleNumber(other.getExampleNumber()); + } + return this; + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + // optional string national_number_pattern = 2; + private boolean hasNationalNumberPattern; + private String nationalNumberPattern_ = ""; + public boolean hasNationalNumberPattern() { return hasNationalNumberPattern; } + public String getNationalNumberPattern() { return nationalNumberPattern_; } + public PhoneNumberDesc setNationalNumberPattern(String value) { + hasNationalNumberPattern = true; + nationalNumberPattern_ = value; + return this; + } + public PhoneNumberDesc clearNationalNumberPattern() { + hasNationalNumberPattern = false; + nationalNumberPattern_ = ""; + return this; + } + + // repeated int32 possible_length = 9; + private java.util.List possibleLength_ = new java.util.ArrayList(); + public java.util.List getPossibleLengthList() { + return possibleLength_; + } + public int getPossibleLengthCount() { return possibleLength_.size(); } + public int getPossibleLength(int index) { + return possibleLength_.get(index); + } + public PhoneNumberDesc addPossibleLength(int value) { + possibleLength_.add(value); + return this; + } + public PhoneNumberDesc clearPossibleLength() { + possibleLength_.clear(); + return this; + } + + // repeated int32 possible_length_local_only = 10; + private java.util.List possibleLengthLocalOnly_ = new java.util.ArrayList(); + public java.util.List getPossibleLengthLocalOnlyList() { + return possibleLengthLocalOnly_; + } + public int getPossibleLengthLocalOnlyCount() { return possibleLengthLocalOnly_.size(); } + public int getPossibleLengthLocalOnly(int index) { + return possibleLengthLocalOnly_.get(index); + } + public PhoneNumberDesc addPossibleLengthLocalOnly(int value) { + possibleLengthLocalOnly_.add(value); + return this; + } + public PhoneNumberDesc clearPossibleLengthLocalOnly() { + possibleLengthLocalOnly_.clear(); + return this; + } + + // optional string example_number = 6; + private boolean hasExampleNumber; + private String exampleNumber_ = ""; + public boolean hasExampleNumber() { return hasExampleNumber; } + public String getExampleNumber() { return exampleNumber_; } + public PhoneNumberDesc setExampleNumber(String value) { + hasExampleNumber = true; + exampleNumber_ = value; + return this; + } + public PhoneNumberDesc clearExampleNumber() { + hasExampleNumber = false; + exampleNumber_ = ""; + return this; + } + + public boolean exactlySameAs(PhoneNumberDesc other) { + return nationalNumberPattern_.equals(other.nationalNumberPattern_) && + possibleLength_.equals(other.possibleLength_) && + possibleLengthLocalOnly_.equals(other.possibleLengthLocalOnly_) && + exampleNumber_.equals(other.exampleNumber_); + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeBoolean(hasNationalNumberPattern); + if (hasNationalNumberPattern) { + objectOutput.writeUTF(nationalNumberPattern_); + } + + int possibleLengthSize = getPossibleLengthCount(); + objectOutput.writeInt(possibleLengthSize); + for (int i = 0; i < possibleLengthSize; i++) { + objectOutput.writeInt(possibleLength_.get(i)); + } + + int possibleLengthLocalOnlySize = getPossibleLengthLocalOnlyCount(); + objectOutput.writeInt(possibleLengthLocalOnlySize); + for (int i = 0; i < possibleLengthLocalOnlySize; i++) { + objectOutput.writeInt(possibleLengthLocalOnly_.get(i)); + } + + objectOutput.writeBoolean(hasExampleNumber); + if (hasExampleNumber) { + objectOutput.writeUTF(exampleNumber_); + } + } + + public void readExternal(ObjectInput objectInput) throws IOException { + if (objectInput.readBoolean()) { + setNationalNumberPattern(objectInput.readUTF()); + } + + int possibleLengthSize = objectInput.readInt(); + for (int i = 0; i < possibleLengthSize; i++) { + possibleLength_.add(objectInput.readInt()); + } + + int possibleLengthLocalOnlySize = objectInput.readInt(); + for (int i = 0; i < possibleLengthLocalOnlySize; i++) { + possibleLengthLocalOnly_.add(objectInput.readInt()); + } + + if (objectInput.readBoolean()) { + setExampleNumber(objectInput.readUTF()); + } + } + } + + public static class PhoneMetadata implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneMetadata() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneMetadata { + public PhoneMetadata build() { + return this; + } + + public Builder setId(String value) { + super.setId(value); + return this; + } + + public Builder setInternationalPrefix(String value) { + super.setInternationalPrefix(value); + return this; + } + } + public static Builder newBuilder() { + return new Builder(); + } + + // optional PhoneNumberDesc general_desc = 1; + private boolean hasGeneralDesc; + private PhoneNumberDesc generalDesc_ = null; + public boolean hasGeneralDesc() { return hasGeneralDesc; } + public PhoneNumberDesc getGeneralDesc() { return generalDesc_; } + public PhoneNumberDesc getGeneralDescBuilder() { + if (generalDesc_ == null) { + generalDesc_ = new PhoneNumberDesc(); + } + return generalDesc_ ; + } + public PhoneMetadata setGeneralDesc(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasGeneralDesc = true; + generalDesc_ = value; + return this; + } + + // optional PhoneNumberDesc fixed_line = 2; + private boolean hasFixedLine; + private PhoneNumberDesc fixedLine_ = null; + public boolean hasFixedLine() { return hasFixedLine; } + public PhoneNumberDesc getFixedLine() { return fixedLine_; } + public PhoneMetadata setFixedLine(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasFixedLine = true; + fixedLine_ = value; + return this; + } + + // optional PhoneNumberDesc mobile = 3; + private boolean hasMobile; + private PhoneNumberDesc mobile_ = null; + public boolean hasMobile() { return hasMobile; } + public PhoneNumberDesc getMobile() { return mobile_; } + public PhoneMetadata setMobile(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasMobile = true; + mobile_ = value; + return this; + } + + // optional PhoneNumberDesc toll_free = 4; + private boolean hasTollFree; + private PhoneNumberDesc tollFree_ = null; + public boolean hasTollFree() { return hasTollFree; } + public PhoneNumberDesc getTollFree() { return tollFree_; } + public PhoneMetadata setTollFree(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasTollFree = true; + tollFree_ = value; + return this; + } + + // optional PhoneNumberDesc premium_rate = 5; + private boolean hasPremiumRate; + private PhoneNumberDesc premiumRate_ = null; + public boolean hasPremiumRate() { return hasPremiumRate; } + public PhoneNumberDesc getPremiumRate() { return premiumRate_; } + public PhoneMetadata setPremiumRate(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPremiumRate = true; + premiumRate_ = value; + return this; + } + + // optional PhoneNumberDesc shared_cost = 6; + private boolean hasSharedCost; + private PhoneNumberDesc sharedCost_ = null; + public boolean hasSharedCost() { return hasSharedCost; } + public PhoneNumberDesc getSharedCost() { return sharedCost_; } + public PhoneMetadata setSharedCost(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasSharedCost = true; + sharedCost_ = value; + return this; + } + + // optional PhoneNumberDesc personal_number = 7; + private boolean hasPersonalNumber; + private PhoneNumberDesc personalNumber_ = null; + public boolean hasPersonalNumber() { return hasPersonalNumber; } + public PhoneNumberDesc getPersonalNumber() { return personalNumber_; } + public PhoneMetadata setPersonalNumber(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPersonalNumber = true; + personalNumber_ = value; + return this; + } + + // optional PhoneNumberDesc voip = 8; + private boolean hasVoip; + private PhoneNumberDesc voip_ = null; + public boolean hasVoip() { return hasVoip; } + public PhoneNumberDesc getVoip() { return voip_; } + public PhoneMetadata setVoip(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasVoip = true; + voip_ = value; + return this; + } + + // optional PhoneNumberDesc pager = 21; + private boolean hasPager; + private PhoneNumberDesc pager_ = null; + public boolean hasPager() { return hasPager; } + public PhoneNumberDesc getPager() { return pager_; } + public PhoneMetadata setPager(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPager = true; + pager_ = value; + return this; + } + + // optional PhoneNumberDesc uan = 25; + private boolean hasUan; + private PhoneNumberDesc uan_ = null; + public boolean hasUan() { return hasUan; } + public PhoneNumberDesc getUan() { return uan_; } + public PhoneMetadata setUan(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasUan = true; + uan_ = value; + return this; + } + + // optional PhoneNumberDesc emergency = 27; + private boolean hasEmergency; + private PhoneNumberDesc emergency_ = null; + public boolean hasEmergency() { return hasEmergency; } + public PhoneNumberDesc getEmergency() { return emergency_; } + public PhoneMetadata setEmergency(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasEmergency = true; + emergency_ = value; + return this; + } + + // optional PhoneNumberDesc voicemail = 28; + private boolean hasVoicemail; + private PhoneNumberDesc voicemail_ = null; + public boolean hasVoicemail() { return hasVoicemail; } + public PhoneNumberDesc getVoicemail() { return voicemail_; } + public PhoneMetadata setVoicemail(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasVoicemail = true; + voicemail_ = value; + return this; + } + + // optional PhoneNumberDesc short_code = 29; + private boolean hasShortCode; + private PhoneNumberDesc shortCode_ = null; + public boolean hasShortCode() { return hasShortCode; } + public PhoneNumberDesc getShortCode() { return shortCode_; } + public PhoneMetadata setShortCode(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasShortCode = true; + shortCode_ = value; + return this; + } + + // optional PhoneNumberDesc standard_rate = 30; + private boolean hasStandardRate; + private PhoneNumberDesc standardRate_ = null; + public boolean hasStandardRate() { return hasStandardRate; } + public PhoneNumberDesc getStandardRate() { return standardRate_; } + public PhoneMetadata setStandardRate(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasStandardRate = true; + standardRate_ = value; + return this; + } + + // optional PhoneNumberDesc carrier_specific = 31; + private boolean hasCarrierSpecific; + private PhoneNumberDesc carrierSpecific_ = null; + public boolean hasCarrierSpecific() { return hasCarrierSpecific; } + public PhoneNumberDesc getCarrierSpecific() { return carrierSpecific_; } + public PhoneMetadata setCarrierSpecific(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasCarrierSpecific = true; + carrierSpecific_ = value; + return this; + } + + // optional PhoneNumberDesc sms_services = 33; + private boolean hasSmsServices; + private PhoneNumberDesc smsServices_ = null; + public boolean hasSmsServices() { return hasSmsServices; } + public PhoneNumberDesc getSmsServices() { return smsServices_; } + public PhoneMetadata setSmsServices(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasSmsServices = true; + smsServices_ = value; + return this; + } + + // optional PhoneNumberDesc noInternationalDialling = 24; + private boolean hasNoInternationalDialling; + private PhoneNumberDesc noInternationalDialling_ = null; + public boolean hasNoInternationalDialling() { return hasNoInternationalDialling; } + public PhoneNumberDesc getNoInternationalDialling() { return noInternationalDialling_; } + public PhoneMetadata setNoInternationalDialling(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasNoInternationalDialling = true; + noInternationalDialling_ = value; + return this; + } + + // required string id = 9; + private boolean hasId; + private String id_ = ""; + public boolean hasId() { return hasId; } + public String getId() { return id_; } + public PhoneMetadata setId(String value) { + hasId = true; + id_ = value; + return this; + } + + // optional int32 country_code = 10; + private boolean hasCountryCode; + private int countryCode_ = 0; + public boolean hasCountryCode() { return hasCountryCode; } + public int getCountryCode() { return countryCode_; } + public PhoneMetadata setCountryCode(int value) { + hasCountryCode = true; + countryCode_ = value; + return this; + } + + // optional string international_prefix = 11; + private boolean hasInternationalPrefix; + private String internationalPrefix_ = ""; + public boolean hasInternationalPrefix() { return hasInternationalPrefix; } + public String getInternationalPrefix() { return internationalPrefix_; } + public PhoneMetadata setInternationalPrefix(String value) { + hasInternationalPrefix = true; + internationalPrefix_ = value; + return this; + } + + // optional string preferred_international_prefix = 17; + private boolean hasPreferredInternationalPrefix; + private String preferredInternationalPrefix_ = ""; + public boolean hasPreferredInternationalPrefix() { return hasPreferredInternationalPrefix; } + public String getPreferredInternationalPrefix() { return preferredInternationalPrefix_; } + public PhoneMetadata setPreferredInternationalPrefix(String value) { + hasPreferredInternationalPrefix = true; + preferredInternationalPrefix_ = value; + return this; + } + public PhoneMetadata clearPreferredInternationalPrefix() { + hasPreferredInternationalPrefix = false; + preferredInternationalPrefix_ = ""; + return this; + } + + // optional string national_prefix = 12; + private boolean hasNationalPrefix; + private String nationalPrefix_ = ""; + public boolean hasNationalPrefix() { return hasNationalPrefix; } + public String getNationalPrefix() { return nationalPrefix_; } + public PhoneMetadata setNationalPrefix(String value) { + hasNationalPrefix = true; + nationalPrefix_ = value; + return this; + } + public PhoneMetadata clearNationalPrefix() { + hasNationalPrefix = false; + nationalPrefix_ = ""; + return this; + } + + // optional string preferred_extn_prefix = 13; + private boolean hasPreferredExtnPrefix; + private String preferredExtnPrefix_ = ""; + public boolean hasPreferredExtnPrefix() { return hasPreferredExtnPrefix; } + public String getPreferredExtnPrefix() { return preferredExtnPrefix_; } + public PhoneMetadata setPreferredExtnPrefix(String value) { + hasPreferredExtnPrefix = true; + preferredExtnPrefix_ = value; + return this; + } + public PhoneMetadata clearPreferredExtnPrefix() { + hasPreferredExtnPrefix = false; + preferredExtnPrefix_ = ""; + return this; + } + + // optional string national_prefix_for_parsing = 15; + private boolean hasNationalPrefixForParsing; + private String nationalPrefixForParsing_ = ""; + public boolean hasNationalPrefixForParsing() { return hasNationalPrefixForParsing; } + public String getNationalPrefixForParsing() { return nationalPrefixForParsing_; } + public PhoneMetadata setNationalPrefixForParsing(String value) { + hasNationalPrefixForParsing = true; + nationalPrefixForParsing_ = value; + return this; + } + + // optional string national_prefix_transform_rule = 16; + private boolean hasNationalPrefixTransformRule; + private String nationalPrefixTransformRule_ = ""; + public boolean hasNationalPrefixTransformRule() { return hasNationalPrefixTransformRule; } + public String getNationalPrefixTransformRule() { return nationalPrefixTransformRule_; } + public PhoneMetadata setNationalPrefixTransformRule(String value) { + hasNationalPrefixTransformRule = true; + nationalPrefixTransformRule_ = value; + return this; + } + public PhoneMetadata clearNationalPrefixTransformRule() { + hasNationalPrefixTransformRule = false; + nationalPrefixTransformRule_ = ""; + return this; + } + + // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false]; + private boolean hasSameMobileAndFixedLinePattern; + private boolean sameMobileAndFixedLinePattern_ = false; + public boolean hasSameMobileAndFixedLinePattern() { return hasSameMobileAndFixedLinePattern; } + public boolean getSameMobileAndFixedLinePattern() { return sameMobileAndFixedLinePattern_; } + public PhoneMetadata setSameMobileAndFixedLinePattern(boolean value) { + hasSameMobileAndFixedLinePattern = true; + sameMobileAndFixedLinePattern_ = value; + return this; + } + public PhoneMetadata clearSameMobileAndFixedLinePattern() { + hasSameMobileAndFixedLinePattern = false; + sameMobileAndFixedLinePattern_ = false; + return this; + } + + // repeated NumberFormat number_format = 19; + private java.util.List numberFormat_ = new java.util.ArrayList(); + @Deprecated + public java.util.List numberFormats() { + return getNumberFormatList(); + } + public java.util.List getNumberFormatList() { + return numberFormat_; + } + @Deprecated + public int numberFormatSize() { return getNumberFormatCount(); } + public int getNumberFormatCount() { return numberFormat_.size(); } + public NumberFormat getNumberFormat(int index) { + return numberFormat_.get(index); + } + public PhoneMetadata addNumberFormat(NumberFormat value) { + if (value == null) { + throw new NullPointerException(); + } + numberFormat_.add(value); + return this; + } + + // repeated NumberFormat intl_number_format = 20; + private java.util.List intlNumberFormat_ = + new java.util.ArrayList(); + @Deprecated + public java.util.List intlNumberFormats() { + return getIntlNumberFormatList(); + } + public java.util.List getIntlNumberFormatList() { + return intlNumberFormat_; + } + @Deprecated + public int intlNumberFormatSize() { return getIntlNumberFormatCount(); } + public int getIntlNumberFormatCount() { return intlNumberFormat_.size(); } + public NumberFormat getIntlNumberFormat(int index) { + return intlNumberFormat_.get(index); + } + + public PhoneMetadata addIntlNumberFormat(NumberFormat value) { + if (value == null) { + throw new NullPointerException(); + } + intlNumberFormat_.add(value); + return this; + } + public PhoneMetadata clearIntlNumberFormat() { + intlNumberFormat_.clear(); + return this; + } + + // optional bool main_country_for_code = 22 [default = false]; + private boolean hasMainCountryForCode; + private boolean mainCountryForCode_ = false; + public boolean hasMainCountryForCode() { return hasMainCountryForCode; } + public boolean isMainCountryForCode() { return mainCountryForCode_; } + // Method that lets this class have the same interface as the one generated by Protocol Buffers + // which is used by C++ build tools. + public boolean getMainCountryForCode() { return mainCountryForCode_; } + public PhoneMetadata setMainCountryForCode(boolean value) { + hasMainCountryForCode = true; + mainCountryForCode_ = value; + return this; + } + public PhoneMetadata clearMainCountryForCode() { + hasMainCountryForCode = false; + mainCountryForCode_ = false; + return this; + } + + // optional string leading_digits = 23; + private boolean hasLeadingDigits; + private String leadingDigits_ = ""; + public boolean hasLeadingDigits() { return hasLeadingDigits; } + public String getLeadingDigits() { return leadingDigits_; } + public PhoneMetadata setLeadingDigits(String value) { + hasLeadingDigits = true; + leadingDigits_ = value; + return this; + } + + // optional bool mobile_number_portable_region = 32 [default = false]; + private boolean hasMobileNumberPortableRegion; + private boolean mobileNumberPortableRegion_ = false; + public boolean hasMobileNumberPortableRegion() { return hasMobileNumberPortableRegion; } + @Deprecated + public boolean isMobileNumberPortableRegion() { return getMobileNumberPortableRegion(); } + public boolean getMobileNumberPortableRegion() { return mobileNumberPortableRegion_; } + public PhoneMetadata setMobileNumberPortableRegion(boolean value) { + hasMobileNumberPortableRegion = true; + mobileNumberPortableRegion_ = value; + return this; + } + public PhoneMetadata clearMobileNumberPortableRegion() { + hasMobileNumberPortableRegion = false; + mobileNumberPortableRegion_ = false; + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeBoolean(hasGeneralDesc); + if (hasGeneralDesc) { + generalDesc_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasFixedLine); + if (hasFixedLine) { + fixedLine_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasMobile); + if (hasMobile) { + mobile_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasTollFree); + if (hasTollFree) { + tollFree_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPremiumRate); + if (hasPremiumRate) { + premiumRate_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasSharedCost); + if (hasSharedCost) { + sharedCost_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPersonalNumber); + if (hasPersonalNumber) { + personalNumber_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasVoip); + if (hasVoip) { + voip_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPager); + if (hasPager) { + pager_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasUan); + if (hasUan) { + uan_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasEmergency); + if (hasEmergency) { + emergency_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasVoicemail); + if (hasVoicemail) { + voicemail_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasShortCode); + if (hasShortCode) { + shortCode_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasStandardRate); + if (hasStandardRate) { + standardRate_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasCarrierSpecific); + if (hasCarrierSpecific) { + carrierSpecific_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasSmsServices); + if (hasSmsServices) { + smsServices_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasNoInternationalDialling); + if (hasNoInternationalDialling) { + noInternationalDialling_.writeExternal(objectOutput); + } + + objectOutput.writeUTF(id_); + objectOutput.writeInt(countryCode_); + objectOutput.writeUTF(internationalPrefix_); + + objectOutput.writeBoolean(hasPreferredInternationalPrefix); + if (hasPreferredInternationalPrefix) { + objectOutput.writeUTF(preferredInternationalPrefix_); + } + + objectOutput.writeBoolean(hasNationalPrefix); + if (hasNationalPrefix) { + objectOutput.writeUTF(nationalPrefix_); + } + + objectOutput.writeBoolean(hasPreferredExtnPrefix); + if (hasPreferredExtnPrefix) { + objectOutput.writeUTF(preferredExtnPrefix_); + } + + objectOutput.writeBoolean(hasNationalPrefixForParsing); + if (hasNationalPrefixForParsing) { + objectOutput.writeUTF(nationalPrefixForParsing_); + } + + objectOutput.writeBoolean(hasNationalPrefixTransformRule); + if (hasNationalPrefixTransformRule) { + objectOutput.writeUTF(nationalPrefixTransformRule_); + } + + objectOutput.writeBoolean(sameMobileAndFixedLinePattern_); + + int numberFormatSize = numberFormatSize(); + objectOutput.writeInt(numberFormatSize); + for (int i = 0; i < numberFormatSize; i++) { + numberFormat_.get(i).writeExternal(objectOutput); + } + + int intlNumberFormatSize = intlNumberFormatSize(); + objectOutput.writeInt(intlNumberFormatSize); + for (int i = 0; i < intlNumberFormatSize; i++) { + intlNumberFormat_.get(i).writeExternal(objectOutput); + } + + objectOutput.writeBoolean(mainCountryForCode_); + + objectOutput.writeBoolean(hasLeadingDigits); + if (hasLeadingDigits) { + objectOutput.writeUTF(leadingDigits_); + } + + objectOutput.writeBoolean(mobileNumberPortableRegion_); + } + + public void readExternal(ObjectInput objectInput) throws IOException { + boolean hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setGeneralDesc(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setFixedLine(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setMobile(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setTollFree(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPremiumRate(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setSharedCost(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPersonalNumber(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setVoip(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPager(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setUan(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setEmergency(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setVoicemail(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setShortCode(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setStandardRate(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setCarrierSpecific(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setSmsServices(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setNoInternationalDialling(desc); + } + + setId(objectInput.readUTF()); + setCountryCode(objectInput.readInt()); + setInternationalPrefix(objectInput.readUTF()); + + boolean hasString = objectInput.readBoolean(); + if (hasString) { + setPreferredInternationalPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setPreferredExtnPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefixForParsing(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefixTransformRule(objectInput.readUTF()); + } + + setSameMobileAndFixedLinePattern(objectInput.readBoolean()); + + int nationalFormatSize = objectInput.readInt(); + for (int i = 0; i < nationalFormatSize; i++) { + NumberFormat numFormat = new NumberFormat(); + numFormat.readExternal(objectInput); + numberFormat_.add(numFormat); + } + + int intlNumberFormatSize = objectInput.readInt(); + for (int i = 0; i < intlNumberFormatSize; i++) { + NumberFormat numFormat = new NumberFormat(); + numFormat.readExternal(objectInput); + intlNumberFormat_.add(numFormat); + } + + setMainCountryForCode(objectInput.readBoolean()); + + hasString = objectInput.readBoolean(); + if (hasString) { + setLeadingDigits(objectInput.readUTF()); + } + + setMobileNumberPortableRegion(objectInput.readBoolean()); + } + } + + public static class PhoneMetadataCollection implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneMetadataCollection() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneMetadataCollection { + public PhoneMetadataCollection build() { + return this; + } + } + public static Builder newBuilder() { + return new Builder(); + } + + // repeated PhoneMetadata metadata = 1; + private java.util.List metadata_ = new java.util.ArrayList(); + + public java.util.List getMetadataList() { + return metadata_; + } + public int getMetadataCount() { return metadata_.size(); } + + public PhoneMetadataCollection addMetadata(PhoneMetadata value) { + if (value == null) { + throw new NullPointerException(); + } + metadata_.add(value); + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + int size = getMetadataCount(); + objectOutput.writeInt(size); + for (int i = 0; i < size; i++) { + metadata_.get(i).writeExternal(objectOutput); + } + } + + public void readExternal(ObjectInput objectInput) throws IOException { + int size = objectInput.readInt(); + for (int i = 0; i < size; i++) { + PhoneMetadata metadata = new PhoneMetadata(); + metadata.readExternal(objectInput); + metadata_.add(metadata); + } + } + + public PhoneMetadataCollection clear() { + metadata_.clear(); + return this; + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonenumber.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonenumber.java new file mode 100644 index 0000000000..fe88a465c6 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/Phonenumber.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Definition of the class representing international telephone numbers. This class is hand-created + * based on the class file compiled from phonenumber.proto. Please refer to that file for detailed + * descriptions of the meaning of each field. + */ + +package com.google.i18n.phonenumbers; + +import java.io.Serializable; + +public final class Phonenumber { + private Phonenumber() {} + public static class PhoneNumber implements Serializable { + private static final long serialVersionUID = 1L; + public enum CountryCodeSource { + FROM_NUMBER_WITH_PLUS_SIGN, + FROM_NUMBER_WITH_IDD, + FROM_NUMBER_WITHOUT_PLUS_SIGN, + FROM_DEFAULT_COUNTRY, + UNSPECIFIED + } + + public PhoneNumber() { + countryCodeSource_ = CountryCodeSource.UNSPECIFIED; + } + + // required int32 country_code = 1; + private boolean hasCountryCode; + private int countryCode_ = 0; + public boolean hasCountryCode() { return hasCountryCode; } + public int getCountryCode() { return countryCode_; } + public PhoneNumber setCountryCode(int value) { + hasCountryCode = true; + countryCode_ = value; + return this; + } + public PhoneNumber clearCountryCode() { + hasCountryCode = false; + countryCode_ = 0; + return this; + } + + // required uint64 national_number = 2; + private boolean hasNationalNumber; + private long nationalNumber_ = 0L; + public boolean hasNationalNumber() { return hasNationalNumber; } + public long getNationalNumber() { return nationalNumber_; } + public PhoneNumber setNationalNumber(long value) { + hasNationalNumber = true; + nationalNumber_ = value; + return this; + } + public PhoneNumber clearNationalNumber() { + hasNationalNumber = false; + nationalNumber_ = 0L; + return this; + } + + // optional string extension = 3; + private boolean hasExtension; + private java.lang.String extension_ = ""; + public boolean hasExtension() { return hasExtension; } + public String getExtension() { return extension_; } + public PhoneNumber setExtension(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasExtension = true; + extension_ = value; + return this; + } + public PhoneNumber clearExtension() { + hasExtension = false; + extension_ = ""; + return this; + } + + // optional bool italian_leading_zero = 4; + private boolean hasItalianLeadingZero; + private boolean italianLeadingZero_ = false; + public boolean hasItalianLeadingZero() { return hasItalianLeadingZero; } + public boolean isItalianLeadingZero() { return italianLeadingZero_; } + public PhoneNumber setItalianLeadingZero(boolean value) { + hasItalianLeadingZero = true; + italianLeadingZero_ = value; + return this; + } + public PhoneNumber clearItalianLeadingZero() { + hasItalianLeadingZero = false; + italianLeadingZero_ = false; + return this; + } + + // optional int32 number_of_leading_zeros = 8 [default = 1]; + private boolean hasNumberOfLeadingZeros; + private int numberOfLeadingZeros_ = 1; + public boolean hasNumberOfLeadingZeros() { return hasNumberOfLeadingZeros; } + public int getNumberOfLeadingZeros() { return numberOfLeadingZeros_; } + public PhoneNumber setNumberOfLeadingZeros(int value) { + hasNumberOfLeadingZeros = true; + numberOfLeadingZeros_ = value; + return this; + } + public PhoneNumber clearNumberOfLeadingZeros() { + hasNumberOfLeadingZeros = false; + numberOfLeadingZeros_ = 1; + return this; + } + + // optional string raw_input = 5; + private boolean hasRawInput; + private String rawInput_ = ""; + public boolean hasRawInput() { return hasRawInput; } + public String getRawInput() { return rawInput_; } + public PhoneNumber setRawInput(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasRawInput = true; + rawInput_ = value; + return this; + } + public PhoneNumber clearRawInput() { + hasRawInput = false; + rawInput_ = ""; + return this; + } + + // optional CountryCodeSource country_code_source = 6; + private boolean hasCountryCodeSource; + private CountryCodeSource countryCodeSource_; + public boolean hasCountryCodeSource() { return hasCountryCodeSource; } + public CountryCodeSource getCountryCodeSource() { return countryCodeSource_; } + public PhoneNumber setCountryCodeSource(CountryCodeSource value) { + if (value == null) { + throw new NullPointerException(); + } + hasCountryCodeSource = true; + countryCodeSource_ = value; + return this; + } + public PhoneNumber clearCountryCodeSource() { + hasCountryCodeSource = false; + countryCodeSource_ = CountryCodeSource.UNSPECIFIED; + return this; + } + + // optional string preferred_domestic_carrier_code = 7; + private boolean hasPreferredDomesticCarrierCode; + private java.lang.String preferredDomesticCarrierCode_ = ""; + public boolean hasPreferredDomesticCarrierCode() { return hasPreferredDomesticCarrierCode; } + public String getPreferredDomesticCarrierCode() { return preferredDomesticCarrierCode_; } + public PhoneNumber setPreferredDomesticCarrierCode(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasPreferredDomesticCarrierCode = true; + preferredDomesticCarrierCode_ = value; + return this; + } + public PhoneNumber clearPreferredDomesticCarrierCode() { + hasPreferredDomesticCarrierCode = false; + preferredDomesticCarrierCode_ = ""; + return this; + } + + public final PhoneNumber clear() { + clearCountryCode(); + clearNationalNumber(); + clearExtension(); + clearItalianLeadingZero(); + clearNumberOfLeadingZeros(); + clearRawInput(); + clearCountryCodeSource(); + clearPreferredDomesticCarrierCode(); + return this; + } + + public PhoneNumber mergeFrom(PhoneNumber other) { + if (other.hasCountryCode()) { + setCountryCode(other.getCountryCode()); + } + if (other.hasNationalNumber()) { + setNationalNumber(other.getNationalNumber()); + } + if (other.hasExtension()) { + setExtension(other.getExtension()); + } + if (other.hasItalianLeadingZero()) { + setItalianLeadingZero(other.isItalianLeadingZero()); + } + if (other.hasNumberOfLeadingZeros()) { + setNumberOfLeadingZeros(other.getNumberOfLeadingZeros()); + } + if (other.hasRawInput()) { + setRawInput(other.getRawInput()); + } + if (other.hasCountryCodeSource()) { + setCountryCodeSource(other.getCountryCodeSource()); + } + if (other.hasPreferredDomesticCarrierCode()) { + setPreferredDomesticCarrierCode(other.getPreferredDomesticCarrierCode()); + } + return this; + } + + public boolean exactlySameAs(PhoneNumber other) { + if (other == null) { + return false; + } + if (this == other) { + return true; + } + return (countryCode_ == other.countryCode_ && nationalNumber_ == other.nationalNumber_ && + extension_.equals(other.extension_) && italianLeadingZero_ == other.italianLeadingZero_ && + numberOfLeadingZeros_ == other.numberOfLeadingZeros_ && + rawInput_.equals(other.rawInput_) && countryCodeSource_ == other.countryCodeSource_ && + preferredDomesticCarrierCode_.equals(other.preferredDomesticCarrierCode_) && + hasPreferredDomesticCarrierCode() == other.hasPreferredDomesticCarrierCode()); + } + + @Override + public boolean equals(Object that) { + return (that instanceof PhoneNumber) && exactlySameAs((PhoneNumber) that); + } + + @Override + public int hashCode() { + // Simplified rendition of the hashCode function automatically generated from the proto + // compiler with java_generate_equals_and_hash set to true. We are happy with unset values to + // be considered equal to their explicitly-set equivalents, so don't check if any value is + // unknown. The only exception to this is the preferred domestic carrier code. + int hash = 41; + hash = (53 * hash) + getCountryCode(); + hash = (53 * hash) + Long.valueOf(getNationalNumber()).hashCode(); + hash = (53 * hash) + getExtension().hashCode(); + hash = (53 * hash) + (isItalianLeadingZero() ? 1231 : 1237); + hash = (53 * hash) + getNumberOfLeadingZeros(); + hash = (53 * hash) + getRawInput().hashCode(); + hash = (53 * hash) + getCountryCodeSource().hashCode(); + hash = (53 * hash) + getPreferredDomesticCarrierCode().hashCode(); + hash = (53 * hash) + (hasPreferredDomesticCarrierCode() ? 1231 : 1237); + return hash; + } + + @Override + public String toString() { + StringBuilder outputString = new StringBuilder(); + outputString.append("Country Code: ").append(countryCode_); + outputString.append(" National Number: ").append(nationalNumber_); + if (hasItalianLeadingZero() && isItalianLeadingZero()) { + outputString.append(" Leading Zero(s): true"); + } + if (hasNumberOfLeadingZeros()) { + outputString.append(" Number of leading zeros: ").append(numberOfLeadingZeros_); + } + if (hasExtension()) { + outputString.append(" Extension: ").append(extension_); + } + if (hasCountryCodeSource()) { + outputString.append(" Country Code Source: ").append(countryCodeSource_); + } + if (hasPreferredDomesticCarrierCode()) { + outputString.append(" Preferred Domestic Carrier Code: "). + append(preferredDomesticCarrierCode_); + } + return outputString.toString(); + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumberInfo.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumberInfo.java new file mode 100644 index 0000000000..7ce2972bac --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumberInfo.java @@ -0,0 +1,569 @@ +/* + * Copyright (C) 2013 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.internal.MatcherApi; +import com.google.i18n.phonenumbers.internal.RegexBasedMatcher; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Methods for getting information about short phone numbers, such as short codes and emergency + * numbers. Note that most commercial short numbers are not handled here, but by the + * {@link PhoneNumberUtil}. + * + * @author Shaopeng Jia + * @author David Yonge-Mallo + */ +public class ShortNumberInfo { + private static final Logger logger = Logger.getLogger(ShortNumberInfo.class.getName()); + + private static final ShortNumberInfo INSTANCE = + new ShortNumberInfo( + RegexBasedMatcher.create(), + DefaultMetadataDependenciesProvider.getInstance().getShortNumberMetadataSource()); + + // In these countries, if extra digits are added to an emergency number, it no longer connects + // to the emergency service. + private static final Set REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT = new HashSet<>(); + static { + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("BR"); + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("CL"); + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("NI"); + } + + /** Cost categories of short numbers. */ + public enum ShortNumberCost { + TOLL_FREE, + STANDARD_RATE, + PREMIUM_RATE, + UNKNOWN_COST + } + + /** Returns the singleton instance of the ShortNumberInfo. */ + public static ShortNumberInfo getInstance() { + return INSTANCE; + } + + // MatcherApi supports the basic matching method for checking if a given national number matches + // a national number pattern defined in the given {@code PhoneNumberDesc}. + private final MatcherApi matcherApi; + + // A mapping from a country calling code to the region codes which denote the region represented + // by that country calling code. In the case of multiple regions sharing a calling code, such as + // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be + // first. + private final Map> countryCallingCodeToRegionCodeMap; + + private final RegionMetadataSource shortNumberMetadataSource; + + // @VisibleForTesting + ShortNumberInfo(MatcherApi matcherApi, + RegionMetadataSource shortNumberMetadataSource) { + this.matcherApi = matcherApi; + this.shortNumberMetadataSource = shortNumberMetadataSource; + // TODO: Create ShortNumberInfo for a given map + this.countryCallingCodeToRegionCodeMap = + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap(); + } + + /** + * Returns a list with the region codes that match the specific country calling code. For + * non-geographical country calling codes, the region code 001 is returned. Also, in the case + * of no region code being found, an empty list is returned. + */ + private List getRegionCodesForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return Collections.unmodifiableList(regionCodes == null ? new ArrayList(0) + : regionCodes); + } + + /** + * Helper method to check that the country calling code of the number matches the region it's + * being dialed from. + */ + private boolean regionDialingFromMatchesNumber(PhoneNumber number, + String regionDialingFrom) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + return regionCodes.contains(regionDialingFrom); + } + + /** + * A thin wrapper around {@code shortNumberMetadataSource} which catches {@link + * IllegalArgumentException} for invalid region code and instead returns {@code null} + */ + private PhoneMetadata getShortNumberMetadataForRegion(String regionCode) { + if (regionCode == null) { + return null; + } + try { + return shortNumberMetadataSource.getMetadataForRegion(regionCode); + } catch (IllegalArgumentException e) { + return null; + } + } + + /** + * Check whether a short number is a possible number when dialed from the given region. This + * provides a more lenient check than {@link #isValidShortNumberForRegion}. + * + * @param number the short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the number is a possible short number + */ + public boolean isPossibleShortNumberForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return false; + } + int numberLength = getNationalSignificantNumber(number).length(); + return phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(numberLength); + } + + /** + * Check whether a short number is a possible number. If a country calling code is shared by + * multiple regions, this returns true if it's possible in any of them. This provides a more + * lenient check than {@link #isValidShortNumber}. See {@link + * #isPossibleShortNumberForRegion(PhoneNumber, String)} for details. + * + * @param number the short number to check + * @return whether the number is a possible short number + */ + public boolean isPossibleShortNumber(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + int shortNumberLength = getNationalSignificantNumber(number).length(); + for (String region : regionCodes) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(region); + if (phoneMetadata == null) { + continue; + } + if (phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(shortNumberLength)) { + return true; + } + } + return false; + } + + /** + * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify + * the number is actually in use, which is impossible to tell by just looking at the number + * itself. + * + * @param number the short number for which we want to test the validity + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number matches a valid pattern + */ + public boolean isValidShortNumberForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return false; + } + String shortNumber = getNationalSignificantNumber(number); + PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc(); + if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) { + return false; + } + PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode(); + return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc); + } + + /** + * Tests whether a short number matches a valid pattern. If a country calling code is shared by + * multiple regions, this returns true if it's valid in any of them. Note that this doesn't verify + * the number is actually in use, which is impossible to tell by just looking at the number + * itself. See {@link #isValidShortNumberForRegion(PhoneNumber, String)} for details. + * + * @param number the short number for which we want to test the validity + * @return whether the short number matches a valid pattern + */ + public boolean isValidShortNumber(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); + if (regionCodes.size() > 1 && regionCode != null) { + // If a matching region had been found for the phone number from among two or more regions, + // then we have already implicitly verified its validity for that region. + return true; + } + return isValidShortNumberForRegion(number, regionCode); + } + + /** + * Gets the expected cost category of a short number when dialed from a region (however, nothing + * is implied about its validity). If it is important that the number is valid, then its validity + * must first be checked using {@link #isValidShortNumberForRegion}. Note that emergency numbers + * are always considered toll-free. Example usage: + *

{@code
+   * // The region for which the number was parsed and the region we subsequently check against
+   * // need not be the same. Here we parse the number in the US and check it for Canada.
+   * PhoneNumber number = phoneUtil.parse("110", "US");
+   * ...
+   * String regionCode = "CA";
+   * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
+   * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
+   *   ShortNumberCost cost = shortInfo.getExpectedCostForRegion(number, regionCode);
+   *   // Do something with the cost information here.
+   * }}
+ * + * @param number the short number for which we want to know the expected cost category + * @param regionDialingFrom the region from which the number is dialed + * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if + * the number does not match a cost category. Note that an invalid number may match any cost + * category. + */ + public ShortNumberCost getExpectedCostForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return ShortNumberCost.UNKNOWN_COST; + } + // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null. + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return ShortNumberCost.UNKNOWN_COST; + } + + String shortNumber = getNationalSignificantNumber(number); + + // The possible lengths are not present for a particular sub-type if they match the general + // description; for this reason, we check the possible lengths against the general description + // first to allow an early exit if possible. + if (!phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(shortNumber.length())) { + return ShortNumberCost.UNKNOWN_COST; + } + + // The cost categories are tested in order of decreasing expense, since if for some reason the + // patterns overlap the most expensive matching cost category should be returned. + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) { + return ShortNumberCost.PREMIUM_RATE; + } + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) { + return ShortNumberCost.STANDARD_RATE; + } + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) { + return ShortNumberCost.TOLL_FREE; + } + if (isEmergencyNumber(shortNumber, regionDialingFrom)) { + // Emergency numbers are implicitly toll-free. + return ShortNumberCost.TOLL_FREE; + } + return ShortNumberCost.UNKNOWN_COST; + } + + /** + * Gets the expected cost category of a short number (however, nothing is implied about its + * validity). If the country calling code is unique to a region, this method behaves exactly the + * same as {@link #getExpectedCostForRegion(PhoneNumber, String)}. However, if the country + * calling code is shared by multiple regions, then it returns the highest cost in the sequence + * PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of + * UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE + * or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it + * might be a PREMIUM_RATE number. + *

+ * For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected + * cost returned by this method will be STANDARD_RATE, since the NANPA countries share the same + * country calling code. + *

+ * Note: If the region from which the number is dialed is known, it is highly preferable to call + * {@link #getExpectedCostForRegion(PhoneNumber, String)} instead. + * + * @param number the short number for which we want to know the expected cost category + * @return the highest expected cost category of the short number in the region(s) with the given + * country calling code + */ + public ShortNumberCost getExpectedCost(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + if (regionCodes.size() == 0) { + return ShortNumberCost.UNKNOWN_COST; + } + if (regionCodes.size() == 1) { + return getExpectedCostForRegion(number, regionCodes.get(0)); + } + ShortNumberCost cost = ShortNumberCost.TOLL_FREE; + for (String regionCode : regionCodes) { + ShortNumberCost costForRegion = getExpectedCostForRegion(number, regionCode); + switch (costForRegion) { + case PREMIUM_RATE: + return ShortNumberCost.PREMIUM_RATE; + case UNKNOWN_COST: + cost = ShortNumberCost.UNKNOWN_COST; + break; + case STANDARD_RATE: + if (cost != ShortNumberCost.UNKNOWN_COST) { + cost = ShortNumberCost.STANDARD_RATE; + } + break; + case TOLL_FREE: + // Do nothing. + break; + default: + logger.log(Level.SEVERE, "Unrecognised cost for region: " + costForRegion); + } + } + return cost; + } + + // Helper method to get the region code for a given phone number, from a list of possible region + // codes. If the list contains more than one region, the first region for which the number is + // valid is returned. + private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number, + List regionCodes) { + if (regionCodes.size() == 0) { + return null; + } else if (regionCodes.size() == 1) { + return regionCodes.get(0); + } + String nationalNumber = getNationalSignificantNumber(number); + for (String regionCode : regionCodes) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata != null + && matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getShortCode())) { + // The number is valid for this region. + return regionCode; + } + } + return null; + } + + /** + * Gets a valid short number for the specified region. + * + * @param regionCode the region for which an example short number is needed + * @return a valid short number for the specified region. Returns an empty string when the + * metadata does not contain such information. + */ + // @VisibleForTesting + String getExampleShortNumber(String regionCode) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata == null) { + return ""; + } + PhoneNumberDesc desc = phoneMetadata.getShortCode(); + if (desc.hasExampleNumber()) { + return desc.getExampleNumber(); + } + return ""; + } + + /** + * Gets a valid short number for the specified cost category. + * + * @param regionCode the region for which an example short number is needed + * @param cost the cost category of number that is needed + * @return a valid short number for the specified region and cost category. Returns an empty + * string when the metadata does not contain such information, or the cost is UNKNOWN_COST. + */ + // @VisibleForTesting + String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata == null) { + return ""; + } + PhoneNumberDesc desc = null; + switch (cost) { + case TOLL_FREE: + desc = phoneMetadata.getTollFree(); + break; + case STANDARD_RATE: + desc = phoneMetadata.getStandardRate(); + break; + case PREMIUM_RATE: + desc = phoneMetadata.getPremiumRate(); + break; + default: + // UNKNOWN_COST numbers are computed by the process of elimination from the other cost + // categories. + } + if (desc != null && desc.hasExampleNumber()) { + return desc.getExampleNumber(); + } + return ""; + } + + /** + * Returns true if the given number, exactly as dialed, might be used to connect to an emergency + * service in the given region. + *

+ * This method accepts a string, rather than a PhoneNumber, because it needs to distinguish + * cases such as "+1 911" and "911", where the former may not connect to an emergency service in + * all cases but the latter would. This method takes into account cases where the number might + * contain formatting, or might have additional digits appended (when it is okay to do that in + * the specified region). + * + * @param number the phone number to test + * @param regionCode the region where the phone number is being dialed + * @return whether the number might be used to connect to an emergency service in the given region + */ + public boolean connectsToEmergencyNumber(String number, String regionCode) { + return matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */); + } + + /** + * Returns true if the given number exactly matches an emergency service number in the given + * region. + *

+ * This method takes into account cases where the number might contain formatting, but doesn't + * allow additional digits to be appended. Note that {@code isEmergencyNumber(number, region)} + * implies {@code connectsToEmergencyNumber(number, region)}. + * + * @param number the phone number to test + * @param regionCode the region where the phone number is being dialed + * @return whether the number exactly matches an emergency services number in the given region + */ + public boolean isEmergencyNumber(CharSequence number, String regionCode) { + return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */); + } + + private boolean matchesEmergencyNumberHelper(CharSequence number, String regionCode, + boolean allowPrefixMatch) { + CharSequence possibleNumber = PhoneNumberUtil.extractPossibleNumber(number); + if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(possibleNumber).lookingAt()) { + // Returns false if the number starts with a plus sign. We don't believe dialing the country + // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can + // add additional logic here to handle it. + return false; + } + PhoneMetadata metadata = getShortNumberMetadataForRegion(regionCode); + if (metadata == null || !metadata.hasEmergency()) { + return false; + } + + String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(possibleNumber); + boolean allowPrefixMatchForRegion = + allowPrefixMatch && !REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.contains(regionCode); + return matcherApi.matchNationalNumber(normalizedNumber, metadata.getEmergency(), + allowPrefixMatchForRegion); + } + + /** + * Given a valid short number, determines whether it is carrier-specific (however, nothing is + * implied about its validity). Carrier-specific numbers may connect to a different end-point, or + * not connect at all, depending on the user's carrier. If it is important that the number is + * valid, then its validity must first be checked using {@link #isValidShortNumber} or + * {@link #isValidShortNumberForRegion}. + * + * @param number the valid short number to check + * @return whether the short number is carrier-specific, assuming the input was a valid short + * number + */ + public boolean isCarrierSpecific(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); + String nationalNumber = getNationalSignificantNumber(number); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + return (phoneMetadata != null) + && (matchesPossibleNumberAndNationalNumber(nationalNumber, + phoneMetadata.getCarrierSpecific())); + } + + /** + * Given a valid short number, determines whether it is carrier-specific when dialed from the + * given region (however, nothing is implied about its validity). Carrier-specific numbers may + * connect to a different end-point, or not connect at all, depending on the user's carrier. If + * it is important that the number is valid, then its validity must first be checked using + * {@link #isValidShortNumber} or {@link #isValidShortNumberForRegion}. Returns false if the + * number doesn't match the region provided. + * + * @param number the valid short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number is carrier-specific in the provided region, assuming the + * input was a valid short number + */ + public boolean isCarrierSpecificForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + String nationalNumber = getNationalSignificantNumber(number); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + return (phoneMetadata != null) + && (matchesPossibleNumberAndNationalNumber(nationalNumber, + phoneMetadata.getCarrierSpecific())); + } + + /** + * Given a valid short number, determines whether it is an SMS service (however, nothing is + * implied about its validity). An SMS service is where the primary or only intended usage is to + * receive and/or send text messages (SMSs). This includes MMS as MMS numbers downgrade to SMS if + * the other party isn't MMS-capable. If it is important that the number is valid, then its + * validity must first be checked using {@link #isValidShortNumber} or {@link + * #isValidShortNumberForRegion}. Returns false if the number doesn't match the region provided. + * + * @param number the valid short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number is an SMS service in the provided region, assuming the input + * was a valid short number + */ + public boolean isSmsServiceForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + return phoneMetadata != null + && matchesPossibleNumberAndNationalNumber(getNationalSignificantNumber(number), + phoneMetadata.getSmsServices()); + } + + /** + * Gets the national significant number of the a phone number. Note a national significant number + * doesn't contain a national prefix or any formatting. + *

+ * This is a temporary duplicate of the {@code getNationalSignificantNumber} method from + * {@code PhoneNumberUtil}. Ultimately a canonical static version should exist in a separate + * utility class (to prevent {@code ShortNumberInfo} needing to depend on PhoneNumberUtil). + * + * @param number the phone number for which the national significant number is needed + * @return the national significant number of the PhoneNumber object passed in + */ + private static String getNationalSignificantNumber(PhoneNumber number) { + // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix. + StringBuilder nationalNumber = new StringBuilder(); + if (number.isItalianLeadingZero()) { + char[] zeros = new char[number.getNumberOfLeadingZeros()]; + Arrays.fill(zeros, '0'); + nationalNumber.append(new String(zeros)); + } + nationalNumber.append(number.getNationalNumber()); + return nationalNumber.toString(); + } + + // TODO: Once we have benchmarked ShortNumberInfo, consider if it is worth keeping + // this performance optimization. + private boolean matchesPossibleNumberAndNationalNumber(String number, + PhoneNumberDesc numberDesc) { + if (numberDesc.getPossibleLengthCount() > 0 + && !numberDesc.getPossibleLengthList().contains(number.length())) { + return false; + } + return matcherApi.matchNationalNumber(number, numberDesc, false); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java new file mode 100644 index 0000000000..e2046b0cd3 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2013 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.HashSet; +import java.util.Set; + +public class ShortNumbersRegionCodeSet { + // A set of all region codes for which data is available. + public static Set getRegionCodeSet() { + // The capacity is set to 321 as there are 241 different entries, + // and this offers a load factor of roughly 0.75. + Set regionCodeSet = new HashSet(321); + + regionCodeSet.add("AC"); + regionCodeSet.add("AD"); + regionCodeSet.add("AE"); + regionCodeSet.add("AF"); + regionCodeSet.add("AG"); + regionCodeSet.add("AI"); + regionCodeSet.add("AL"); + regionCodeSet.add("AM"); + regionCodeSet.add("AO"); + regionCodeSet.add("AR"); + regionCodeSet.add("AS"); + regionCodeSet.add("AT"); + regionCodeSet.add("AU"); + regionCodeSet.add("AW"); + regionCodeSet.add("AX"); + regionCodeSet.add("AZ"); + regionCodeSet.add("BA"); + regionCodeSet.add("BB"); + regionCodeSet.add("BD"); + regionCodeSet.add("BE"); + regionCodeSet.add("BF"); + regionCodeSet.add("BG"); + regionCodeSet.add("BH"); + regionCodeSet.add("BI"); + regionCodeSet.add("BJ"); + regionCodeSet.add("BL"); + regionCodeSet.add("BM"); + regionCodeSet.add("BN"); + regionCodeSet.add("BO"); + regionCodeSet.add("BQ"); + regionCodeSet.add("BR"); + regionCodeSet.add("BS"); + regionCodeSet.add("BT"); + regionCodeSet.add("BW"); + regionCodeSet.add("BY"); + regionCodeSet.add("BZ"); + regionCodeSet.add("CA"); + regionCodeSet.add("CC"); + regionCodeSet.add("CD"); + regionCodeSet.add("CF"); + regionCodeSet.add("CG"); + regionCodeSet.add("CH"); + regionCodeSet.add("CI"); + regionCodeSet.add("CK"); + regionCodeSet.add("CL"); + regionCodeSet.add("CM"); + regionCodeSet.add("CN"); + regionCodeSet.add("CO"); + regionCodeSet.add("CR"); + regionCodeSet.add("CU"); + regionCodeSet.add("CV"); + regionCodeSet.add("CW"); + regionCodeSet.add("CX"); + regionCodeSet.add("CY"); + regionCodeSet.add("CZ"); + regionCodeSet.add("DE"); + regionCodeSet.add("DJ"); + regionCodeSet.add("DK"); + regionCodeSet.add("DM"); + regionCodeSet.add("DO"); + regionCodeSet.add("DZ"); + regionCodeSet.add("EC"); + regionCodeSet.add("EE"); + regionCodeSet.add("EG"); + regionCodeSet.add("EH"); + regionCodeSet.add("ER"); + regionCodeSet.add("ES"); + regionCodeSet.add("ET"); + regionCodeSet.add("FI"); + regionCodeSet.add("FJ"); + regionCodeSet.add("FK"); + regionCodeSet.add("FM"); + regionCodeSet.add("FO"); + regionCodeSet.add("FR"); + regionCodeSet.add("GA"); + regionCodeSet.add("GB"); + regionCodeSet.add("GD"); + regionCodeSet.add("GE"); + regionCodeSet.add("GF"); + regionCodeSet.add("GG"); + regionCodeSet.add("GH"); + regionCodeSet.add("GI"); + regionCodeSet.add("GL"); + regionCodeSet.add("GM"); + regionCodeSet.add("GN"); + regionCodeSet.add("GP"); + regionCodeSet.add("GR"); + regionCodeSet.add("GT"); + regionCodeSet.add("GU"); + regionCodeSet.add("GW"); + regionCodeSet.add("GY"); + regionCodeSet.add("HK"); + regionCodeSet.add("HN"); + regionCodeSet.add("HR"); + regionCodeSet.add("HT"); + regionCodeSet.add("HU"); + regionCodeSet.add("ID"); + regionCodeSet.add("IE"); + regionCodeSet.add("IL"); + regionCodeSet.add("IM"); + regionCodeSet.add("IN"); + regionCodeSet.add("IQ"); + regionCodeSet.add("IR"); + regionCodeSet.add("IS"); + regionCodeSet.add("IT"); + regionCodeSet.add("JE"); + regionCodeSet.add("JM"); + regionCodeSet.add("JO"); + regionCodeSet.add("JP"); + regionCodeSet.add("KE"); + regionCodeSet.add("KG"); + regionCodeSet.add("KH"); + regionCodeSet.add("KI"); + regionCodeSet.add("KM"); + regionCodeSet.add("KN"); + regionCodeSet.add("KP"); + regionCodeSet.add("KR"); + regionCodeSet.add("KW"); + regionCodeSet.add("KY"); + regionCodeSet.add("KZ"); + regionCodeSet.add("LA"); + regionCodeSet.add("LB"); + regionCodeSet.add("LC"); + regionCodeSet.add("LI"); + regionCodeSet.add("LK"); + regionCodeSet.add("LR"); + regionCodeSet.add("LS"); + regionCodeSet.add("LT"); + regionCodeSet.add("LU"); + regionCodeSet.add("LV"); + regionCodeSet.add("LY"); + regionCodeSet.add("MA"); + regionCodeSet.add("MC"); + regionCodeSet.add("MD"); + regionCodeSet.add("ME"); + regionCodeSet.add("MF"); + regionCodeSet.add("MG"); + regionCodeSet.add("MH"); + regionCodeSet.add("MK"); + regionCodeSet.add("ML"); + regionCodeSet.add("MM"); + regionCodeSet.add("MN"); + regionCodeSet.add("MO"); + regionCodeSet.add("MP"); + regionCodeSet.add("MQ"); + regionCodeSet.add("MR"); + regionCodeSet.add("MS"); + regionCodeSet.add("MT"); + regionCodeSet.add("MU"); + regionCodeSet.add("MV"); + regionCodeSet.add("MW"); + regionCodeSet.add("MX"); + regionCodeSet.add("MY"); + regionCodeSet.add("MZ"); + regionCodeSet.add("NA"); + regionCodeSet.add("NC"); + regionCodeSet.add("NE"); + regionCodeSet.add("NF"); + regionCodeSet.add("NG"); + regionCodeSet.add("NI"); + regionCodeSet.add("NL"); + regionCodeSet.add("NO"); + regionCodeSet.add("NP"); + regionCodeSet.add("NR"); + regionCodeSet.add("NU"); + regionCodeSet.add("NZ"); + regionCodeSet.add("OM"); + regionCodeSet.add("PA"); + regionCodeSet.add("PE"); + regionCodeSet.add("PF"); + regionCodeSet.add("PG"); + regionCodeSet.add("PH"); + regionCodeSet.add("PK"); + regionCodeSet.add("PL"); + regionCodeSet.add("PM"); + regionCodeSet.add("PR"); + regionCodeSet.add("PS"); + regionCodeSet.add("PT"); + regionCodeSet.add("PW"); + regionCodeSet.add("PY"); + regionCodeSet.add("QA"); + regionCodeSet.add("RE"); + regionCodeSet.add("RO"); + regionCodeSet.add("RS"); + regionCodeSet.add("RU"); + regionCodeSet.add("RW"); + regionCodeSet.add("SA"); + regionCodeSet.add("SB"); + regionCodeSet.add("SC"); + regionCodeSet.add("SD"); + regionCodeSet.add("SE"); + regionCodeSet.add("SG"); + regionCodeSet.add("SH"); + regionCodeSet.add("SI"); + regionCodeSet.add("SJ"); + regionCodeSet.add("SK"); + regionCodeSet.add("SL"); + regionCodeSet.add("SM"); + regionCodeSet.add("SN"); + regionCodeSet.add("SO"); + regionCodeSet.add("SR"); + regionCodeSet.add("SS"); + regionCodeSet.add("ST"); + regionCodeSet.add("SV"); + regionCodeSet.add("SX"); + regionCodeSet.add("SY"); + regionCodeSet.add("SZ"); + regionCodeSet.add("TC"); + regionCodeSet.add("TD"); + regionCodeSet.add("TG"); + regionCodeSet.add("TH"); + regionCodeSet.add("TJ"); + regionCodeSet.add("TL"); + regionCodeSet.add("TM"); + regionCodeSet.add("TN"); + regionCodeSet.add("TO"); + regionCodeSet.add("TR"); + regionCodeSet.add("TT"); + regionCodeSet.add("TV"); + regionCodeSet.add("TW"); + regionCodeSet.add("TZ"); + regionCodeSet.add("UA"); + regionCodeSet.add("UG"); + regionCodeSet.add("US"); + regionCodeSet.add("UY"); + regionCodeSet.add("UZ"); + regionCodeSet.add("VA"); + regionCodeSet.add("VC"); + regionCodeSet.add("VE"); + regionCodeSet.add("VG"); + regionCodeSet.add("VI"); + regionCodeSet.add("VN"); + regionCodeSet.add("VU"); + regionCodeSet.add("WF"); + regionCodeSet.add("WS"); + regionCodeSet.add("XK"); + regionCodeSet.add("YE"); + regionCodeSet.add("YT"); + regionCodeSet.add("ZA"); + regionCodeSet.add("ZM"); + regionCodeSet.add("ZW"); + + return regionCodeSet; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 new file mode 100644 index 0000000000..1510187d46 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 new file mode 100644 index 0000000000..3d86d493cb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 new file mode 100644 index 0000000000..72ac06a4a2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 new file mode 100644 index 0000000000..c5abeb6858 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 new file mode 100644 index 0000000000..fdef134299 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 new file mode 100644 index 0000000000..a404c3e891 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 new file mode 100644 index 0000000000..7496756575 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 new file mode 100644 index 0000000000..684e8e1e61 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 new file mode 100644 index 0000000000..c6148a8628 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 new file mode 100644 index 0000000000..e04014289d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 new file mode 100644 index 0000000000..f979aacc26 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 new file mode 100644 index 0000000000..6e38688c07 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 new file mode 100644 index 0000000000..7207f15f7e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 new file mode 100644 index 0000000000..426f6f89c7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 new file mode 100644 index 0000000000..2d5605b80e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 new file mode 100644 index 0000000000..161558328e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 new file mode 100644 index 0000000000..06f4b99f6c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 new file mode 100644 index 0000000000..175243cfdc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 new file mode 100644 index 0000000000..244a842c28 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 new file mode 100644 index 0000000000..b5335e7ed2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 new file mode 100644 index 0000000000..2f7b212cf0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 new file mode 100644 index 0000000000..2b6dd35943 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 new file mode 100644 index 0000000000..e23beaabe1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 new file mode 100644 index 0000000000..ff52ce4cc1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 new file mode 100644 index 0000000000..21d60dc6d3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 new file mode 100644 index 0000000000..2eafd93ee4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 new file mode 100644 index 0000000000..9b3af0a9ae Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 new file mode 100644 index 0000000000..0ec23d5729 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 new file mode 100644 index 0000000000..a17ebbbf3d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 new file mode 100644 index 0000000000..77374df900 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 new file mode 100644 index 0000000000..3dd783aed6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 new file mode 100644 index 0000000000..7355c1babc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 new file mode 100644 index 0000000000..64625de937 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 new file mode 100644 index 0000000000..a501a87f08 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 new file mode 100644 index 0000000000..f74102b958 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 new file mode 100644 index 0000000000..db17512850 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 new file mode 100644 index 0000000000..3db56a2563 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 new file mode 100644 index 0000000000..07537c978e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 new file mode 100644 index 0000000000..7a56715715 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 new file mode 100644 index 0000000000..ecd338a121 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 new file mode 100644 index 0000000000..49b1ee6e9e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 new file mode 100644 index 0000000000..36fbcee849 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 new file mode 100644 index 0000000000..853cd55bc5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 new file mode 100644 index 0000000000..42c771c756 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 new file mode 100644 index 0000000000..dfa294c229 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 new file mode 100644 index 0000000000..152bf34840 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 new file mode 100644 index 0000000000..76b8bf2c7d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 new file mode 100644 index 0000000000..c43d67c807 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 new file mode 100644 index 0000000000..45c6e6c557 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 new file mode 100644 index 0000000000..ada9c95fe8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 new file mode 100644 index 0000000000..78b3256834 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 new file mode 100644 index 0000000000..fe026b0d69 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 new file mode 100644 index 0000000000..56b7d66090 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 new file mode 100644 index 0000000000..634ecce02e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 new file mode 100644 index 0000000000..89f33ec6ca Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC new file mode 100644 index 0000000000..e5b1e8f20d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD new file mode 100644 index 0000000000..708a118b46 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE new file mode 100644 index 0000000000..3ec1512110 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF new file mode 100644 index 0000000000..b16f32963a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG new file mode 100644 index 0000000000..6118d9c1e1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI new file mode 100644 index 0000000000..0f145839ed Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL new file mode 100644 index 0000000000..9e80663c72 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM new file mode 100644 index 0000000000..0b71623998 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO new file mode 100644 index 0000000000..5345c505b4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR new file mode 100644 index 0000000000..7554f2df06 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS new file mode 100644 index 0000000000..ce57e4b5c8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT new file mode 100644 index 0000000000..124ad972d3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU new file mode 100644 index 0000000000..e2d65cd669 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW new file mode 100644 index 0000000000..1671079ae4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX new file mode 100644 index 0000000000..f89f906be8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ new file mode 100644 index 0000000000..21bb446caf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA new file mode 100644 index 0000000000..9f8e63bdc3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB new file mode 100644 index 0000000000..5cd771bf54 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD new file mode 100644 index 0000000000..5c4cb85a70 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE new file mode 100644 index 0000000000..fc413d6fa8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF new file mode 100644 index 0000000000..8375abe516 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG new file mode 100644 index 0000000000..503a558160 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH new file mode 100644 index 0000000000..0483e11c7e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI new file mode 100644 index 0000000000..0ee448eac3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ new file mode 100644 index 0000000000..38990a8995 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL new file mode 100644 index 0000000000..706168429c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM new file mode 100644 index 0000000000..dc8bf14fb1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN new file mode 100644 index 0000000000..2e5a9d8c56 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO new file mode 100644 index 0000000000..028a73fead Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ new file mode 100644 index 0000000000..b2aa5b880a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR new file mode 100644 index 0000000000..4722a6b884 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS new file mode 100644 index 0000000000..8223c67ee5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT new file mode 100644 index 0000000000..3a2a40c44a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW new file mode 100644 index 0000000000..0f877729f0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY new file mode 100644 index 0000000000..b5615e3466 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ new file mode 100644 index 0000000000..feac3a5b88 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA new file mode 100644 index 0000000000..18a08a5dc3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC new file mode 100644 index 0000000000..226552455f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD new file mode 100644 index 0000000000..dea8bcb416 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF new file mode 100644 index 0000000000..464e15519f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG new file mode 100644 index 0000000000..f12515e161 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH new file mode 100644 index 0000000000..ddbc79cac1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI new file mode 100644 index 0000000000..eacc997bba Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK new file mode 100644 index 0000000000..0b268b4bd6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL new file mode 100644 index 0000000000..0b4069634e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM new file mode 100644 index 0000000000..0dea728944 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN new file mode 100644 index 0000000000..43dc62fb8e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO new file mode 100644 index 0000000000..fa2b7deeb7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR new file mode 100644 index 0000000000..f0201674da Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU new file mode 100644 index 0000000000..795fd07218 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV new file mode 100644 index 0000000000..cbc793c896 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW new file mode 100644 index 0000000000..78e8c9f74c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX new file mode 100644 index 0000000000..bbd0e4d82b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY new file mode 100644 index 0000000000..3ed050adfd Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ new file mode 100644 index 0000000000..686d18a65a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE new file mode 100644 index 0000000000..250769a0e4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ new file mode 100644 index 0000000000..c4174f1e2c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK new file mode 100644 index 0000000000..b2af72b656 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM new file mode 100644 index 0000000000..d6b4f64fc2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO new file mode 100644 index 0000000000..8d9d06cbbb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ new file mode 100644 index 0000000000..fe704f355c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC new file mode 100644 index 0000000000..726b61cde5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE new file mode 100644 index 0000000000..75f93bd99a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG new file mode 100644 index 0000000000..5270ea38a6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH new file mode 100644 index 0000000000..d470ee3abe Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER new file mode 100644 index 0000000000..9ac4c6955a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES new file mode 100644 index 0000000000..f686b949d9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET new file mode 100644 index 0000000000..7988307b13 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI new file mode 100644 index 0000000000..0a0c7a0709 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ new file mode 100644 index 0000000000..303845b68e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK new file mode 100644 index 0000000000..f931d3bf2d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM new file mode 100644 index 0000000000..6fd391e565 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO new file mode 100644 index 0000000000..6637ff15c8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR new file mode 100644 index 0000000000..3d3ebbb4ff Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA new file mode 100644 index 0000000000..68a02bd132 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB new file mode 100644 index 0000000000..8c6657cf07 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD new file mode 100644 index 0000000000..b3057866dc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE new file mode 100644 index 0000000000..8f2cbfb6d2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF new file mode 100644 index 0000000000..2c27a29290 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG new file mode 100644 index 0000000000..7860e3113f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH new file mode 100644 index 0000000000..20a93cdc3a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI new file mode 100644 index 0000000000..9d235f9d4c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL new file mode 100644 index 0000000000..6881e2bbc9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM new file mode 100644 index 0000000000..5e62ed5a37 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN new file mode 100644 index 0000000000..a5be8c8439 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP new file mode 100644 index 0000000000..3c4e10e9cc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ new file mode 100644 index 0000000000..3f6a6da632 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR new file mode 100644 index 0000000000..75dd781eb8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT new file mode 100644 index 0000000000..c1c0d4f39f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU new file mode 100644 index 0000000000..54d99db7a4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW new file mode 100644 index 0000000000..3fdee90061 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY new file mode 100644 index 0000000000..eee7fc4fae Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK new file mode 100644 index 0000000000..3520b154d5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN new file mode 100644 index 0000000000..64788dcae1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR new file mode 100644 index 0000000000..76ba85efb8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT new file mode 100644 index 0000000000..057bee3e65 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU new file mode 100644 index 0000000000..7238138dd7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID new file mode 100644 index 0000000000..0a67a1a27a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE new file mode 100644 index 0000000000..9d9c82c169 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL new file mode 100644 index 0000000000..024675b99e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM new file mode 100644 index 0000000000..42f4bdf4f3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN new file mode 100644 index 0000000000..9e10ced9a4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO new file mode 100644 index 0000000000..9a9d77e5a0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ new file mode 100644 index 0000000000..d0d8e4cfaa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR new file mode 100644 index 0000000000..8f254a22cf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS new file mode 100644 index 0000000000..b1f7eb0292 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT new file mode 100644 index 0000000000..a07ef18283 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE new file mode 100644 index 0000000000..3a6542d64d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM new file mode 100644 index 0000000000..4b97837fca Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO new file mode 100644 index 0000000000..14bcd58a47 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP new file mode 100644 index 0000000000..1568a8f57e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE new file mode 100644 index 0000000000..8e10e28d41 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG new file mode 100644 index 0000000000..41797005fc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH new file mode 100644 index 0000000000..0156233aca Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI new file mode 100644 index 0000000000..e1beb0cdd9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM new file mode 100644 index 0000000000..483658cb93 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN new file mode 100644 index 0000000000..c249995264 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP new file mode 100644 index 0000000000..a12d7deeeb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR new file mode 100644 index 0000000000..ce4de56369 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW new file mode 100644 index 0000000000..27e1c8cf14 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY new file mode 100644 index 0000000000..95bed5e01f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ new file mode 100644 index 0000000000..346ae181e9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA new file mode 100644 index 0000000000..39c98b7375 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB new file mode 100644 index 0000000000..31946984c6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC new file mode 100644 index 0000000000..6820248c9e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI new file mode 100644 index 0000000000..db5e577972 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK new file mode 100644 index 0000000000..89a060b615 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR new file mode 100644 index 0000000000..c69e3ae3e9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS new file mode 100644 index 0000000000..68261efa7c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT new file mode 100644 index 0000000000..521df976c2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU new file mode 100644 index 0000000000..63217e0cfa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV new file mode 100644 index 0000000000..07323a7ed3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY new file mode 100644 index 0000000000..ccf6d2baef Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA new file mode 100644 index 0000000000..3c13bd9647 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC new file mode 100644 index 0000000000..34a35da4cd Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD new file mode 100644 index 0000000000..bd5d320624 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME new file mode 100644 index 0000000000..94f2430774 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF new file mode 100644 index 0000000000..dc4373bbb2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG new file mode 100644 index 0000000000..53d307b1f5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH new file mode 100644 index 0000000000..f9424efc7d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK new file mode 100644 index 0000000000..12b2210e5c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML new file mode 100644 index 0000000000..817f806046 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM new file mode 100644 index 0000000000..ec27b2c48c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN new file mode 100644 index 0000000000..1039995371 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO new file mode 100644 index 0000000000..b7e0c23fb3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP new file mode 100644 index 0000000000..c7659bad3e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ new file mode 100644 index 0000000000..ea6af790b6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR new file mode 100644 index 0000000000..fd7282a2db Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS new file mode 100644 index 0000000000..1a8393a0b1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT new file mode 100644 index 0000000000..1d9fa0604d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU new file mode 100644 index 0000000000..8780975977 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV new file mode 100644 index 0000000000..3e121e0a41 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW new file mode 100644 index 0000000000..7ff74bab1a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX new file mode 100644 index 0000000000..d33f966fb2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY new file mode 100644 index 0000000000..efad3c5bc2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ new file mode 100644 index 0000000000..c45028701b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA new file mode 100644 index 0000000000..fe4623de2e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC new file mode 100644 index 0000000000..ce01121470 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE new file mode 100644 index 0000000000..fb42930d36 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF new file mode 100644 index 0000000000..923bb18283 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG new file mode 100644 index 0000000000..b14cb361aa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI new file mode 100644 index 0000000000..3cc901dab1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL new file mode 100644 index 0000000000..3cd0ab0e03 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO new file mode 100644 index 0000000000..b807aa3dea Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP new file mode 100644 index 0000000000..ee2edd26be Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR new file mode 100644 index 0000000000..20864a9a59 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU new file mode 100644 index 0000000000..47b5118856 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ new file mode 100644 index 0000000000..34fd143c18 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM new file mode 100644 index 0000000000..7cf9a03d86 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA new file mode 100644 index 0000000000..014e949f77 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE new file mode 100644 index 0000000000..c8fffa02ec Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF new file mode 100644 index 0000000000..8e4c6f09e6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG new file mode 100644 index 0000000000..95fd8f4392 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH new file mode 100644 index 0000000000..e3ce4c51a6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK new file mode 100644 index 0000000000..37210beb31 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL new file mode 100644 index 0000000000..2fe18a2847 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM new file mode 100644 index 0000000000..592f052a1e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR new file mode 100644 index 0000000000..253a5eda92 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS new file mode 100644 index 0000000000..6ccfbb7f27 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT new file mode 100644 index 0000000000..1cb1fb6fe6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW new file mode 100644 index 0000000000..3783c6a81e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY new file mode 100644 index 0000000000..b1f8f3e7c8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA new file mode 100644 index 0000000000..f7b7f33ad4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE new file mode 100644 index 0000000000..1efaf2b721 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO new file mode 100644 index 0000000000..c2a71717e7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS new file mode 100644 index 0000000000..87cc3ffdb7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU new file mode 100644 index 0000000000..73562cace6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW new file mode 100644 index 0000000000..9538d1a644 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA new file mode 100644 index 0000000000..f8c860238a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB new file mode 100644 index 0000000000..539014c75c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC new file mode 100644 index 0000000000..0340ea64c9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD new file mode 100644 index 0000000000..e6b07106e7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE new file mode 100644 index 0000000000..5d862048e9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG new file mode 100644 index 0000000000..a9959bfa54 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH new file mode 100644 index 0000000000..2c6bbd1f8d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI new file mode 100644 index 0000000000..1a01783c99 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ new file mode 100644 index 0000000000..a475b19afc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK new file mode 100644 index 0000000000..e2788862fb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL new file mode 100644 index 0000000000..94038f18a2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM new file mode 100644 index 0000000000..df14671319 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN new file mode 100644 index 0000000000..ad8bad1a71 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO new file mode 100644 index 0000000000..c4a80bded3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR new file mode 100644 index 0000000000..a1965d0cda Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS new file mode 100644 index 0000000000..7c1a82a1e9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST new file mode 100644 index 0000000000..63ffc4404b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV new file mode 100644 index 0000000000..95054b58ac Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX new file mode 100644 index 0000000000..9d1c0e242c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY new file mode 100644 index 0000000000..3228df26c9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ new file mode 100644 index 0000000000..ce335be555 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA new file mode 100644 index 0000000000..248ff7c0c8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC new file mode 100644 index 0000000000..75da36f588 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD new file mode 100644 index 0000000000..719ade9853 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG new file mode 100644 index 0000000000..23c0f80878 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH new file mode 100644 index 0000000000..d8f9f301a6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ new file mode 100644 index 0000000000..ee20c517a9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK new file mode 100644 index 0000000000..f6092ebf3d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL new file mode 100644 index 0000000000..b969919d64 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM new file mode 100644 index 0000000000..a0508897bf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN new file mode 100644 index 0000000000..926d10400b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO new file mode 100644 index 0000000000..5a0b0a8f6a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR new file mode 100644 index 0000000000..8392e637dd Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT new file mode 100644 index 0000000000..99b760fa51 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV new file mode 100644 index 0000000000..47f5bcb867 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW new file mode 100644 index 0000000000..10970e4122 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ new file mode 100644 index 0000000000..670561c94f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA new file mode 100644 index 0000000000..72e05da797 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG new file mode 100644 index 0000000000..84eb43935a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US new file mode 100644 index 0000000000..65e034d428 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY new file mode 100644 index 0000000000..544748e7d8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ new file mode 100644 index 0000000000..e7f52e54b5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA new file mode 100644 index 0000000000..b595164fb4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC new file mode 100644 index 0000000000..1b04808283 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE new file mode 100644 index 0000000000..bdfb7d7b63 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG new file mode 100644 index 0000000000..9629cb595f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI new file mode 100644 index 0000000000..a0a7941882 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN new file mode 100644 index 0000000000..33692697f9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU new file mode 100644 index 0000000000..151e425973 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF new file mode 100644 index 0000000000..1f75adeca9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS new file mode 100644 index 0000000000..0efa97a1c1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK new file mode 100644 index 0000000000..eb7e6292d3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE new file mode 100644 index 0000000000..615db52ed0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT new file mode 100644 index 0000000000..749d8675a7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA new file mode 100644 index 0000000000..23bc348b1f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM new file mode 100644 index 0000000000..52e4c4a5be Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW new file mode 100644 index 0000000000..a4b68429dc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC new file mode 100644 index 0000000000..31befc231f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD new file mode 100644 index 0000000000..614e70c775 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE new file mode 100644 index 0000000000..e9968bba15 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF new file mode 100644 index 0000000000..0bc1491690 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG new file mode 100644 index 0000000000..0cb86c9099 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI new file mode 100644 index 0000000000..0b4d4fee13 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL new file mode 100644 index 0000000000..60db0b0940 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM new file mode 100644 index 0000000000..cbecebe4fa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO new file mode 100644 index 0000000000..9565c32236 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR new file mode 100644 index 0000000000..a056cd2373 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS new file mode 100644 index 0000000000..b25ab705de Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT new file mode 100644 index 0000000000..ffce32def9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU new file mode 100644 index 0000000000..e64990eaef Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW new file mode 100644 index 0000000000..960a9b2590 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX new file mode 100644 index 0000000000..8fcd3f9444 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ new file mode 100644 index 0000000000..373615b64f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA new file mode 100644 index 0000000000..aa64520819 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB new file mode 100644 index 0000000000..6b94258553 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD new file mode 100644 index 0000000000..2d91d8a2e3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE new file mode 100644 index 0000000000..3967c15c35 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF new file mode 100644 index 0000000000..73cbb89a45 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG new file mode 100644 index 0000000000..c9cee1453d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH new file mode 100644 index 0000000000..4c048fb12f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI new file mode 100644 index 0000000000..833325ee36 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ new file mode 100644 index 0000000000..cc5edf442b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL new file mode 100644 index 0000000000..8a9eeb543c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM new file mode 100644 index 0000000000..24ee0a145d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN new file mode 100644 index 0000000000..ae3b1f1972 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO new file mode 100644 index 0000000000..52c1ece21f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ new file mode 100644 index 0000000000..e33f379a9d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR new file mode 100644 index 0000000000..a2d1f1a033 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS new file mode 100644 index 0000000000..ed383266f4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT new file mode 100644 index 0000000000..47a4c6c19a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW new file mode 100644 index 0000000000..346bfb444c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY new file mode 100644 index 0000000000..5a9cce9d21 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ new file mode 100644 index 0000000000..255205afa8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA new file mode 100644 index 0000000000..3a78361e88 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC new file mode 100644 index 0000000000..500a225897 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD new file mode 100644 index 0000000000..1b326c9ef0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF new file mode 100644 index 0000000000..5d82f6188d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG new file mode 100644 index 0000000000..3d37a798f1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH new file mode 100644 index 0000000000..fcafbbebee Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI new file mode 100644 index 0000000000..a389c339b5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK new file mode 100644 index 0000000000..c4e5176fd7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL new file mode 100644 index 0000000000..87c02839b2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM new file mode 100644 index 0000000000..7625824089 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN new file mode 100644 index 0000000000..062fdcaff6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO new file mode 100644 index 0000000000..51b6508a15 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR new file mode 100644 index 0000000000..796fb16da9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU new file mode 100644 index 0000000000..2d18cf7da9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV new file mode 100644 index 0000000000..f97fc8ac85 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW new file mode 100644 index 0000000000..2c8cb66178 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX new file mode 100644 index 0000000000..9b91cf86d8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY new file mode 100644 index 0000000000..7feb7f8711 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ new file mode 100644 index 0000000000..b5cfbdc7a8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE new file mode 100644 index 0000000000..2895ccce16 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ new file mode 100644 index 0000000000..2457a13da1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK new file mode 100644 index 0000000000..b6e571bae1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM new file mode 100644 index 0000000000..c5264b25ed Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO new file mode 100644 index 0000000000..ca339572e3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ new file mode 100644 index 0000000000..f5695a193c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC new file mode 100644 index 0000000000..a42e53b9d3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE new file mode 100644 index 0000000000..e1448ef237 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG new file mode 100644 index 0000000000..9ff6e65376 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH new file mode 100644 index 0000000000..80c491c970 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER new file mode 100644 index 0000000000..e298284dcf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES new file mode 100644 index 0000000000..c4b40539de Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET new file mode 100644 index 0000000000..9c0c3c1fdd Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI new file mode 100644 index 0000000000..e50ad8f1e0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ new file mode 100644 index 0000000000..0275a2d27a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK new file mode 100644 index 0000000000..5c16cb200e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM new file mode 100644 index 0000000000..e06e4c19fb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO new file mode 100644 index 0000000000..dd4dd01ab9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR new file mode 100644 index 0000000000..4fde5fe011 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA new file mode 100644 index 0000000000..721ce4e441 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB new file mode 100644 index 0000000000..6eb65ad469 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD new file mode 100644 index 0000000000..e5cee36f64 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE new file mode 100644 index 0000000000..288d8883ae Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF new file mode 100644 index 0000000000..6cda55a525 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG new file mode 100644 index 0000000000..0a6ad17ca8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH new file mode 100644 index 0000000000..467315044f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI new file mode 100644 index 0000000000..2ae84745e1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL new file mode 100644 index 0000000000..6748aef666 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM new file mode 100644 index 0000000000..1b2a03a672 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN new file mode 100644 index 0000000000..fa8954a2cb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP new file mode 100644 index 0000000000..43e217f2ab Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR new file mode 100644 index 0000000000..1ac216e648 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT new file mode 100644 index 0000000000..ede385ac4d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU new file mode 100644 index 0000000000..f4e508cc80 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW new file mode 100644 index 0000000000..2bef055ca2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY new file mode 100644 index 0000000000..db33cceacc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK new file mode 100644 index 0000000000..d65427d37c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN new file mode 100644 index 0000000000..7ce9d8e647 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR new file mode 100644 index 0000000000..ddbf4654c8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT new file mode 100644 index 0000000000..ac6f5cd078 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU new file mode 100644 index 0000000000..f23d173a1a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID new file mode 100644 index 0000000000..64b6a35eff Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE new file mode 100644 index 0000000000..c6ea1e526a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL new file mode 100644 index 0000000000..8529cf27a0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM new file mode 100644 index 0000000000..7698e16dd1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN new file mode 100644 index 0000000000..5f0744e876 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ new file mode 100644 index 0000000000..63477f21f3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR new file mode 100644 index 0000000000..3451a0026c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS new file mode 100644 index 0000000000..96668f3235 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT new file mode 100644 index 0000000000..2a1f7ab7a6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE new file mode 100644 index 0000000000..4d01e44e08 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM new file mode 100644 index 0000000000..bcb6c85a3f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO new file mode 100644 index 0000000000..ec29ccde96 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP new file mode 100644 index 0000000000..485360c217 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE new file mode 100644 index 0000000000..d33355e193 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG new file mode 100644 index 0000000000..a2b22fc479 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH new file mode 100644 index 0000000000..b9610350a9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI new file mode 100644 index 0000000000..a381e3fe04 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM new file mode 100644 index 0000000000..9c4a073760 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN new file mode 100644 index 0000000000..7a3f1ae810 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP new file mode 100644 index 0000000000..093275551b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR new file mode 100644 index 0000000000..6c770c97d0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW new file mode 100644 index 0000000000..c37942e118 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY new file mode 100644 index 0000000000..3353ad9369 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ new file mode 100644 index 0000000000..03d7639434 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA new file mode 100644 index 0000000000..bcfc00618a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB new file mode 100644 index 0000000000..628496307e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC new file mode 100644 index 0000000000..bd295e7dfe Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI new file mode 100644 index 0000000000..f24d529e12 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK new file mode 100644 index 0000000000..bef8687933 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR new file mode 100644 index 0000000000..2dcb801dfd Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS new file mode 100644 index 0000000000..228c9d47fa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT new file mode 100644 index 0000000000..9ca9325385 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU new file mode 100644 index 0000000000..febd5a97db Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV new file mode 100644 index 0000000000..812f9222e9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY new file mode 100644 index 0000000000..5ef69345f6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA new file mode 100644 index 0000000000..a9203196eb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC new file mode 100644 index 0000000000..0fb1738c6d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD new file mode 100644 index 0000000000..703bf72052 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME new file mode 100644 index 0000000000..cc028a0e1c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF new file mode 100644 index 0000000000..7106c2f843 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG new file mode 100644 index 0000000000..29aadef6bf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH new file mode 100644 index 0000000000..e42f2eea25 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK new file mode 100644 index 0000000000..2f5696fb54 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML new file mode 100644 index 0000000000..9b903bad8d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM new file mode 100644 index 0000000000..922ffccc4a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN new file mode 100644 index 0000000000..44c35eb2f1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO new file mode 100644 index 0000000000..cab7cbe5ae Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP new file mode 100644 index 0000000000..577d33c7b1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ new file mode 100644 index 0000000000..f4965bc7cc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR new file mode 100644 index 0000000000..bd9cbf662d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS new file mode 100644 index 0000000000..f4dd3eca9f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT new file mode 100644 index 0000000000..75042eeebb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU new file mode 100644 index 0000000000..56c4fd6441 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV new file mode 100644 index 0000000000..4d7bcbbd24 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW new file mode 100644 index 0000000000..27ed1791cb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX new file mode 100644 index 0000000000..f5b17552ef Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY new file mode 100644 index 0000000000..28b81a588e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ new file mode 100644 index 0000000000..fcce2b3773 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA new file mode 100644 index 0000000000..c69a95ec37 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC new file mode 100644 index 0000000000..d1ae2941e4 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE new file mode 100644 index 0000000000..b933add408 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF new file mode 100644 index 0000000000..851a2b4956 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG new file mode 100644 index 0000000000..7229d6a28c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI new file mode 100644 index 0000000000..62dd13c116 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL new file mode 100644 index 0000000000..4c9128189c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO new file mode 100644 index 0000000000..7f0731331e Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP new file mode 100644 index 0000000000..d943ce5ca1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR new file mode 100644 index 0000000000..317c9d3fce Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU new file mode 100644 index 0000000000..55f86a23db Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ new file mode 100644 index 0000000000..e922a873ad Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM new file mode 100644 index 0000000000..3fff62fbcb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA new file mode 100644 index 0000000000..9c977677fa Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE new file mode 100644 index 0000000000..f660b534d6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF new file mode 100644 index 0000000000..b431f93433 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG new file mode 100644 index 0000000000..022009b726 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH new file mode 100644 index 0000000000..745f5cadac Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK new file mode 100644 index 0000000000..228f85a6b2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL new file mode 100644 index 0000000000..96ad400ae3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM new file mode 100644 index 0000000000..b07b532a37 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR new file mode 100644 index 0000000000..03bbbbd9c7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS new file mode 100644 index 0000000000..3a437d58e3 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT new file mode 100644 index 0000000000..be530d73a6 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW new file mode 100644 index 0000000000..dfa8e34031 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY new file mode 100644 index 0000000000..f8618ca22b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA new file mode 100644 index 0000000000..60774e9010 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE new file mode 100644 index 0000000000..83b0d7b509 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO new file mode 100644 index 0000000000..6173c031a1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS new file mode 100644 index 0000000000..4baaf09cbe Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU new file mode 100644 index 0000000000..ba90e65e3a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW new file mode 100644 index 0000000000..bf4c546402 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA new file mode 100644 index 0000000000..476baef6a7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB new file mode 100644 index 0000000000..46fc12706d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC new file mode 100644 index 0000000000..b3b13e738d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD new file mode 100644 index 0000000000..9c84b486ed Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE new file mode 100644 index 0000000000..2624935a08 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG new file mode 100644 index 0000000000..6aca982a55 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH new file mode 100644 index 0000000000..36c30aa95a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI new file mode 100644 index 0000000000..68f0d5610b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ new file mode 100644 index 0000000000..14b46668cf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK new file mode 100644 index 0000000000..94639e8082 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL new file mode 100644 index 0000000000..53fc6e66df Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM new file mode 100644 index 0000000000..9ce5a90dbf Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN new file mode 100644 index 0000000000..424f4f8f87 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO new file mode 100644 index 0000000000..9257eff825 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR new file mode 100644 index 0000000000..5bde39828f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS new file mode 100644 index 0000000000..23d11a4991 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST new file mode 100644 index 0000000000..1d52d4ed86 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV new file mode 100644 index 0000000000..b37645ec17 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX new file mode 100644 index 0000000000..1c247755b9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY new file mode 100644 index 0000000000..b71062fa2d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ new file mode 100644 index 0000000000..7284651d57 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC new file mode 100644 index 0000000000..7f9f221e45 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD new file mode 100644 index 0000000000..9d1f9e6518 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG new file mode 100644 index 0000000000..8bae33c68d Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH new file mode 100644 index 0000000000..5ec30571cb Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ new file mode 100644 index 0000000000..de63252fc7 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL new file mode 100644 index 0000000000..1cc6a1987f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM new file mode 100644 index 0000000000..7623973b28 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN new file mode 100644 index 0000000000..192ca3302c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO new file mode 100644 index 0000000000..4a340a72c0 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR new file mode 100644 index 0000000000..0847c59312 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT new file mode 100644 index 0000000000..bbf62cfc01 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV new file mode 100644 index 0000000000..4625d190d1 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW new file mode 100644 index 0000000000..17b8ee5a5a Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ new file mode 100644 index 0000000000..1118137e0c Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA new file mode 100644 index 0000000000..3cb25984dc Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG new file mode 100644 index 0000000000..7b9f64cfbe Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US new file mode 100644 index 0000000000..2c52287263 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY new file mode 100644 index 0000000000..a6b493cbc8 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ new file mode 100644 index 0000000000..3f18f85fb5 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA new file mode 100644 index 0000000000..f3a3a6e1c2 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC new file mode 100644 index 0000000000..cce977b1a9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE new file mode 100644 index 0000000000..033f6d3fad Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG new file mode 100644 index 0000000000..0e19a0bf25 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI new file mode 100644 index 0000000000..776e00630f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN new file mode 100644 index 0000000000..3246aa77ce Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU new file mode 100644 index 0000000000..3e55971753 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF new file mode 100644 index 0000000000..d2cf29bf73 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS new file mode 100644 index 0000000000..6eac506ea9 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK new file mode 100644 index 0000000000..847f9dd17b Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE new file mode 100644 index 0000000000..86864619ca Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT new file mode 100644 index 0000000000..23e960b504 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA new file mode 100644 index 0000000000..6b4e6e9042 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM new file mode 100644 index 0000000000..84d736c221 Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW new file mode 100644 index 0000000000..6f78c0005f Binary files /dev/null and b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW differ diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java new file mode 100644 index 0000000000..ef0cf67fa8 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.CountryCodeToRegionCodeMap; +import java.util.List; + +/** + * Utility class for checking whether identifiers region code and country calling code belong + * to geographical entities. For more information about geo vs. non-geo entities see {@link + * com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource} and {@link + * com.google.i18n.phonenumbers.metadata.source.NonGeographicalEntityMetadataSource} + */ +public final class GeoEntityUtility { + + /** Region code with a special meaning, used to mark non-geographical entities */ + public static final String REGION_CODE_FOR_NON_GEO_ENTITIES = "001"; + + /** Determines whether {@code regionCode} belongs to a geographical entity. */ + public static boolean isGeoEntity(String regionCode) { + return !regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITIES); + } + + /** + * Determines whether {@code countryCallingCode} belongs to a geographical entity. + * + *

A single country calling code could map to several different regions. It is considered that + * {@code countryCallingCode} belongs to a geo entity if all of these regions are geo entities + * + *

Note that this method will not throw an exception even when the underlying mapping for the + * {@code countryCallingCode} does not exist, instead it will return {@code false} + */ + public static boolean isGeoEntity(int countryCallingCode) { + List regionCodesForCountryCallingCode = + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap().get(countryCallingCode); + + return regionCodesForCountryCallingCode != null + && !regionCodesForCountryCallingCode.contains(REGION_CODE_FOR_NON_GEO_ENTITIES); + } + + private GeoEntityUtility() {} +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/MatcherApi.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/MatcherApi.java new file mode 100644 index 0000000000..d2c32b9eaf --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/MatcherApi.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; + +/** + * Internal phonenumber matching API used to isolate the underlying implementation of the + * matcher and allow different implementations to be swapped in easily. + */ +public interface MatcherApi { + /** + * Returns whether the given national number (a string containing only decimal digits) matches + * the national number pattern defined in the given {@code PhoneNumberDesc} message. + */ + boolean matchNationalNumber(CharSequence number, PhoneNumberDesc numberDesc, + boolean allowPrefixMatch); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java new file mode 100644 index 0000000000..ed18ed0948 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implementation of the matcher API using the regular expressions in the PhoneNumberDesc + * proto message to match numbers. + */ +public final class RegexBasedMatcher implements MatcherApi { + public static MatcherApi create() { + return new RegexBasedMatcher(); + } + + private final RegexCache regexCache = new RegexCache(100); + + private RegexBasedMatcher() {} + + // @Override + public boolean matchNationalNumber(CharSequence number, PhoneNumberDesc numberDesc, + boolean allowPrefixMatch) { + String nationalNumberPattern = numberDesc.getNationalNumberPattern(); + // We don't want to consider it a prefix match when matching non-empty input against an empty + // pattern. + if (nationalNumberPattern.length() == 0) { + return false; + } + return match(number, regexCache.getPatternForRegex(nationalNumberPattern), allowPrefixMatch); + } + + private static boolean match(CharSequence number, Pattern pattern, boolean allowPrefixMatch) { + Matcher matcher = pattern.matcher(number); + if (!matcher.lookingAt()) { + return false; + } else { + return (matcher.matches()) ? true : allowPrefixMatch; + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexCache.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexCache.java new file mode 100644 index 0000000000..f29005e23b --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/internal/RegexCache.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * LRU Cache for compiled regular expressions used by the libphonenumbers libary. + * + * @author Shaopeng Jia + */ +public class RegexCache { + private LRUCache cache; + + public RegexCache(int size) { + cache = new LRUCache(size); + } + + public Pattern getPatternForRegex(String regex) { + Pattern pattern = cache.get(regex); + if (pattern == null) { + pattern = Pattern.compile(regex); + cache.put(regex, pattern); + } + return pattern; + } + + // @VisibleForTesting + boolean containsRegex(String regex) { + return cache.containsKey(regex); + } + + private static class LRUCache { + // LinkedHashMap offers a straightforward implementation of LRU cache. + private LinkedHashMap map; + private int size; + + @SuppressWarnings("serial") + public LRUCache(int size) { + this.size = size; + // Using access-order instead of insertion-order. + map = new LinkedHashMap(size * 4 / 3 + 1, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > LRUCache.this.size; + } + }; + } + + public synchronized V get(K key) { + return map.get(key); + } + + public synchronized void put(K key, V value) { + map.put(key, value); + } + + public synchronized boolean containsKey(K key) { + return map.containsKey(key); + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java new file mode 100644 index 0000000000..6bf4df9413 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.metadata.init.ClassPathResourceMetadataLoader; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; +import com.google.i18n.phonenumbers.metadata.source.FormattingMetadataSource; +import com.google.i18n.phonenumbers.metadata.source.FormattingMetadataSourceImpl; +import com.google.i18n.phonenumbers.metadata.source.MetadataSource; +import com.google.i18n.phonenumbers.metadata.source.MetadataSourceImpl; +import com.google.i18n.phonenumbers.metadata.source.MultiFileModeFileNameProvider; +import com.google.i18n.phonenumbers.metadata.source.PhoneMetadataFileNameProvider; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSourceImpl; + +/** + * Provides metadata init and source dependencies when metadata is stored in multi-file mode and + * loaded as a classpath resource. + */ +public final class DefaultMetadataDependenciesProvider { + + private static final DefaultMetadataDependenciesProvider INSTANCE = new DefaultMetadataDependenciesProvider(); + + public static DefaultMetadataDependenciesProvider getInstance() { + return INSTANCE; + } + + private DefaultMetadataDependenciesProvider() { + } + + private final MetadataParser metadataParser = MetadataParser.newLenientParser(); + private final MetadataLoader metadataLoader = new ClassPathResourceMetadataLoader(); + + private final PhoneMetadataFileNameProvider phoneNumberMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto"); + private final MetadataSource phoneNumberMetadataSource = + new MetadataSourceImpl( + phoneNumberMetadataFileNameProvider, + metadataLoader, + metadataParser); + + private final PhoneMetadataFileNameProvider shortNumberMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto"); + private final RegionMetadataSource shortNumberMetadataSource = + new RegionMetadataSourceImpl( + shortNumberMetadataFileNameProvider, + metadataLoader, + metadataParser); + + private final PhoneMetadataFileNameProvider alternateFormatsMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto"); + private final FormattingMetadataSource alternateFormatsMetadataSource = + new FormattingMetadataSourceImpl( + alternateFormatsMetadataFileNameProvider, + metadataLoader, + metadataParser); + + public MetadataParser getMetadataParser() { + return metadataParser; + } + + public MetadataLoader getMetadataLoader() { + return metadataLoader; + } + + public PhoneMetadataFileNameProvider getPhoneNumberMetadataFileNameProvider() { + return phoneNumberMetadataFileNameProvider; + } + + public MetadataSource getPhoneNumberMetadataSource() { + return phoneNumberMetadataSource; + } + + public PhoneMetadataFileNameProvider getShortNumberMetadataFileNameProvider() { + return shortNumberMetadataFileNameProvider; + } + + public RegionMetadataSource getShortNumberMetadataSource() { + return shortNumberMetadataSource; + } + + public PhoneMetadataFileNameProvider getAlternateFormatsMetadataFileNameProvider() { + return alternateFormatsMetadataFileNameProvider; + } + + public FormattingMetadataSource getAlternateFormatsMetadataSource() { + return alternateFormatsMetadataSource; + } + + public String getCarrierDataDirectory() { + return "/com/google/i18n/phonenumbers/carrier/data/"; + } + + public String getGeocodingDataDirectory() { + return "/com/google/i18n/phonenumbers/geocoding/data/"; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java new file mode 100644 index 0000000000..76122b8ad8 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.init; + +import com.google.i18n.phonenumbers.MetadataLoader; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A {@link MetadataLoader} implementation that reads phone number metadata files as classpath + * resources. + */ +public final class ClassPathResourceMetadataLoader implements MetadataLoader { + + private static final Logger logger = + Logger.getLogger(ClassPathResourceMetadataLoader.class.getName()); + + @Override + public InputStream loadMetadata(String metadataFileName) { + InputStream inputStream = + ClassPathResourceMetadataLoader.class.getResourceAsStream(metadataFileName); + if (inputStream == null) { + logger.log(Level.WARNING, String.format("File %s not found", metadataFileName)); + } + return inputStream; + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java new file mode 100644 index 0000000000..e923dfadf7 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.init; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Exposes single method for parsing {@link InputStream} content into {@link Collection} of {@link + * PhoneMetadata} + */ +public final class MetadataParser { + + private static final Logger logger = Logger.getLogger(MetadataParser.class.getName()); + + /** + * Creates new instance in lenient mode, see {@link MetadataParser#parse(InputStream)} for more + * info. + */ + public static MetadataParser newLenientParser() { + return new MetadataParser(false); + } + + /** + * Creates new instance in strict mode, see {@link MetadataParser#parse(InputStream)} for more + * info + */ + public static MetadataParser newStrictParser() { + return new MetadataParser(true); + } + + private final boolean strictMode; + + private MetadataParser(boolean strictMode) { + this.strictMode = strictMode; + } + + /** + * Parses given {@link InputStream} into a {@link Collection} of {@link PhoneMetadata}. + * + * @throws IllegalArgumentException if {@code source} is {@code null} and strict mode is on + * @return parsed {@link PhoneMetadata}, or empty {@link Collection} if {@code source} is {@code + * null} and lenient mode is on + */ + public Collection parse(InputStream source) { + if (source == null) { + return handleNullSource(); + } + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(source); + PhoneMetadataCollection phoneMetadataCollection = new PhoneMetadataCollection(); + phoneMetadataCollection.readExternal(ois); + List phoneMetadata = phoneMetadataCollection.getMetadataList(); + // Sanity check; this should not happen if provided InputStream is valid + if (phoneMetadata.isEmpty()) { + throw new IllegalStateException("Empty metadata"); + } + return phoneMetadataCollection.getMetadataList(); + } catch (IOException e) { + throw new IllegalStateException("Unable to parse metadata file", e); + } finally { + if (ois != null) { + // This will close all underlying streams as well, including source. + close(ois); + } else { + close(source); + } + } + } + + private List handleNullSource() { + if (strictMode) { + throw new IllegalArgumentException("Source cannot be null"); + } + return Collections.emptyList(); + } + + private void close(InputStream inputStream) { + try { + inputStream.close(); + } catch (IOException e) { + logger.log(Level.WARNING, "Error closing input stream (ignored)", e); + } + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java new file mode 100644 index 0000000000..d621e0cf5f --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; +import java.io.InputStream; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A blocking implementation of {@link MetadataBootstrappingGuard}. Can be used for both single-file + * (bulk) and multi-file metadata + * + * @param needs to extend {@link MetadataContainer} + */ +final class BlockingMetadataBootstrappingGuard + implements MetadataBootstrappingGuard { + + private final MetadataLoader metadataLoader; + private final MetadataParser metadataParser; + private final T metadataContainer; + private final Map loadedFiles; // identity map + + BlockingMetadataBootstrappingGuard( + MetadataLoader metadataLoader, MetadataParser metadataParser, T metadataContainer) { + this.metadataLoader = metadataLoader; + this.metadataParser = metadataParser; + this.metadataContainer = metadataContainer; + this.loadedFiles = new ConcurrentHashMap<>(); + } + + @Override + public T getOrBootstrap(String phoneMetadataFile) { + if (!loadedFiles.containsKey(phoneMetadataFile)) { + bootstrapMetadata(phoneMetadataFile); + } + return metadataContainer; + } + + private synchronized void bootstrapMetadata(String phoneMetadataFile) { + // Additional check is needed because multiple threads could pass the first check when calling + // getOrBootstrap() at the same time for unloaded metadata file + if (loadedFiles.containsKey(phoneMetadataFile)) { + return; + } + Collection phoneMetadata = read(phoneMetadataFile); + for (PhoneMetadata metadata : phoneMetadata) { + metadataContainer.accept(metadata); + } + loadedFiles.put(phoneMetadataFile, phoneMetadataFile); + } + + private Collection read(String phoneMetadataFile) { + try { + InputStream metadataStream = metadataLoader.loadMetadata(phoneMetadataFile); + return metadataParser.parse(metadataStream); + } catch (IllegalArgumentException | IllegalStateException e) { + throw new IllegalStateException("Failed to read file " + phoneMetadataFile, e); + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java new file mode 100644 index 0000000000..7275749578 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; + +/** + * Implementation of {@link MetadataContainer} which is a composition of different {@link + * MapBackedMetadataContainer}s. It adds items to a single simpler container at a time depending on + * the content of {@link PhoneMetadata}. + */ +final class CompositeMetadataContainer implements MetadataContainer { + + private final MapBackedMetadataContainer metadataByCountryCode = + MapBackedMetadataContainer.byCountryCallingCode(); + private final MapBackedMetadataContainer metadataByRegionCode = + MapBackedMetadataContainer.byRegionCode(); + + /** + * Intended to be called for geographical regions only. For non-geographical entities, use {@link + * CompositeMetadataContainer#getMetadataBy(int)} + */ + PhoneMetadata getMetadataBy(String regionCode) { + return metadataByRegionCode.getMetadataBy(regionCode); + } + + /** + * Intended to be called for non-geographical entities only, such as 800 (country code assigned to + * the Universal International Freephone Service). For geographical regions, use {@link + * CompositeMetadataContainer#getMetadataBy(String)} + */ + PhoneMetadata getMetadataBy(int countryCallingCode) { + return metadataByCountryCode.getMetadataBy(countryCallingCode); + } + + /** + * If the metadata belongs to a specific geographical region (it has a region code other than + * {@link GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES}), it will be added to a {@link + * MapBackedMetadataContainer} which stores metadata by region code. Otherwise, it will be added + * to a {@link MapBackedMetadataContainer} which stores metadata by country calling code. This + * means that {@link CompositeMetadataContainer#getMetadataBy(int)} will not work for country + * calling codes such as 41 (country calling code for Switzerland), only for country calling codes + * such as 800 (country code assigned to the Universal International Freephone Service) + */ + @Override + public void accept(PhoneMetadata phoneMetadata) { + String regionCode = metadataByRegionCode.getKeyProvider().getKeyOf(phoneMetadata); + if (GeoEntityUtility.isGeoEntity(regionCode)) { + metadataByRegionCode.accept(phoneMetadata); + } else { + metadataByCountryCode.accept(phoneMetadata); + } + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java new file mode 100644 index 0000000000..f4f332cb21 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** A source of formatting phone metadata. */ +public interface FormattingMetadataSource { + + /** + * Returns formatting phone metadata for provided country calling code. + * + *

This method is similar to the one in {@link + * NonGeographicalEntityMetadataSource#getMetadataForNonGeographicalRegion(int)}, except that it + * will not fail for geographical regions, it can be used for both geo- and non-geo entities. + * + *

In case the provided {@code countryCallingCode} maps to several different regions, only one + * would contain formatting metadata. + * + * @return the phone metadata for provided {@code countryCallingCode}, or null if there is none. + */ + PhoneMetadata getFormattingMetadataForCountryCallingCode(int countryCallingCode); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java new file mode 100644 index 0000000000..d6a819099f --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link FormattingMetadataSource} guarded by {@link MetadataBootstrappingGuard} + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class FormattingMetadataSourceImpl implements FormattingMetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard> bootstrappingGuard; + + public FormattingMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard> bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public FormattingMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, MapBackedMetadataContainer.byCountryCallingCode())); + } + + @Override + public PhoneMetadata getFormattingMetadataForCountryCallingCode(int countryCallingCode) { + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(countryCallingCode)) + .getMetadataBy(countryCallingCode); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java new file mode 100644 index 0000000000..639280d87c --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * A {@link MetadataContainer} implementation backed by a {@link ConcurrentHashMap} with generic + * keys. + */ +final class MapBackedMetadataContainer implements MetadataContainer { + + static MapBackedMetadataContainer byRegionCode() { + return new MapBackedMetadataContainer<>( + new KeyProvider() { + @Override + public String getKeyOf(PhoneMetadata phoneMetadata) { + return phoneMetadata.getId(); + } + }); + } + + static MapBackedMetadataContainer byCountryCallingCode() { + return new MapBackedMetadataContainer<>( + new KeyProvider() { + @Override + public Integer getKeyOf(PhoneMetadata phoneMetadata) { + return phoneMetadata.getCountryCode(); + } + }); + } + + private final ConcurrentMap metadataMap; + + private final KeyProvider keyProvider; + + private MapBackedMetadataContainer(KeyProvider keyProvider) { + this.metadataMap = new ConcurrentHashMap<>(); + this.keyProvider = keyProvider; + } + + PhoneMetadata getMetadataBy(T key) { + return key != null ? metadataMap.get(key) : null; + } + + KeyProvider getKeyProvider() { + return keyProvider; + } + + @Override + public void accept(PhoneMetadata phoneMetadata) { + metadataMap.put(keyProvider.getKeyOf(phoneMetadata), phoneMetadata); + } + + interface KeyProvider { + T getKeyOf(PhoneMetadata phoneMetadata); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java new file mode 100644 index 0000000000..9380c5954d --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * Guard that ensures that metadata bootstrapping process (loading and parsing) is triggered only + * once per metadata file. + * + * @param needs to extend {@link MetadataContainer} + */ +public interface MetadataBootstrappingGuard { + + /** + * If metadata from the provided file has not yet been read, invokes loading and parsing from the + * provided file and adds the result to guarded {@link MetadataContainer}. + * + * @param phoneMetadataFile to read from + * @return guarded {@link MetadataContainer} + */ + T getOrBootstrap(String phoneMetadataFile); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java new file mode 100644 index 0000000000..3f6b21ed0e --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** + * A container for {@link PhoneMetadata} + */ +interface MetadataContainer { + + /** + * Adds {@link PhoneMetadata} to the container. It depends on the implementation of the interface + * what this means, for example {@link MapBackedMetadataContainer} simply adds the provided + * metadata into the backing map. Implementing classes should ensure thread-safety. + */ + void accept(PhoneMetadata phoneMetadata); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java new file mode 100644 index 0000000000..d353ce9694 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** A source of phone metadata split by different regions. */ +public interface MetadataSource extends RegionMetadataSource, NonGeographicalEntityMetadataSource { +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java new file mode 100644 index 0000000000..c3d1c7360b --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link MetadataSource} guarded by {@link MetadataBootstrappingGuard}. + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class MetadataSourceImpl implements MetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard bootstrappingGuard; + + public MetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public MetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, new CompositeMetadataContainer())); + } + + @Override + public PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { + if (GeoEntityUtility.isGeoEntity(countryCallingCode)) { + throw new IllegalArgumentException( + countryCallingCode + " calling code belongs to a geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(countryCallingCode)) + .getMetadataBy(countryCallingCode); + } + + @Override + public PhoneMetadata getMetadataForRegion(String regionCode) { + if (!GeoEntityUtility.isGeoEntity(regionCode)) { + throw new IllegalArgumentException(regionCode + " region code is a non-geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(regionCode)) + .getMetadataBy(regionCode); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java new file mode 100644 index 0000000000..c8a3270a6d --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + + +/** + * {@link PhoneMetadataFileNameProvider} implementation which appends key as a suffix to the + * predefined metadata file name base. + */ +public final class MultiFileModeFileNameProvider implements PhoneMetadataFileNameProvider { + + private final String phoneMetadataFileNamePrefix; + + public MultiFileModeFileNameProvider(String phoneMetadataFileNameBase) { + this.phoneMetadataFileNamePrefix = phoneMetadataFileNameBase + "_"; + } + + @Override + public String getFor(Object key) { + String keyAsString = key.toString(); + if (!isAlphanumeric(keyAsString)) { + throw new IllegalArgumentException("Invalid key: " + keyAsString); + } + return phoneMetadataFileNamePrefix + key; + } + + private boolean isAlphanumeric(String key) { + if (key == null || key.length() == 0) { + return false; + } + // String#length doesn't actually return the number of + // code points in the String, it returns the number + // of char values. + int size = key.length(); + for (int charIdx = 0; charIdx < size; ) { + final int codePoint = key.codePointAt(charIdx); + if (!Character.isLetterOrDigit(codePoint)) { + return false; + } + charIdx += Character.charCount(codePoint); + } + return true; + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java new file mode 100644 index 0000000000..70db06df03 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** + * A source of phone metadata for non-geographical entities. + * + *

Non-geographical entities are phone number ranges that have a country calling code, but either + * do not belong to an actual country (some international services), or belong to a region which has + * a different country calling code from the country it is part of. Examples of such ranges are + * those starting with: + * + *

    + *
  • 800 - country code assigned to the Universal International Freephone Service + *
  • 808 - country code assigned to the International Shared Cost Service + *
  • 870 - country code assigned to the Pitcairn Islands + *
  • ... + *
+ */ +public interface NonGeographicalEntityMetadataSource { + + /** + * Gets phone metadata for a non-geographical entity. + * + * @param countryCallingCode the country calling code. + * @return the phone metadata for that entity, or null if there is none. + * @throws IllegalArgumentException if provided {@code countryCallingCode} does not belong to a + * non-geographical entity + */ + PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java new file mode 100644 index 0000000000..c3d16887fb --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * Abstraction responsible for inferring the metadata file name. + * + *

Two implementations are available: + * + *

    + *
  • {@link SingleFileModeFileNameProvider} for single-file metadata. + *
  • {@link MultiFileModeFileNameProvider} for multi-file metadata. + *
+ */ +public interface PhoneMetadataFileNameProvider { + + /** + * Returns phone metadata file path for the given key. Assumes that key.toString() is + * well-defined. + */ + String getFor(Object key); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java new file mode 100644 index 0000000000..3cf15c206a --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; + +/** + * A source of phone metadata split by geographical regions. + */ +public interface RegionMetadataSource { + + /** + * Returns phone metadata for provided geographical region. + * + *

The {@code regionCode} must be different from {@link + * GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES}, which has a special meaning and is used to + * mark non-geographical regions (see {@link NonGeographicalEntityMetadataSource} for more + * information). + * + * @return the phone metadata for provided {@code regionCode}, or null if there is none. + * @throws IllegalArgumentException if provided {@code regionCode} is {@link + * GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES} + */ + PhoneMetadata getMetadataForRegion(String regionCode); +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java new file mode 100644 index 0000000000..0078dd9454 --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link RegionMetadataSource} guarded by {@link MetadataBootstrappingGuard} + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class RegionMetadataSourceImpl implements RegionMetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard> + bootstrappingGuard; + + public RegionMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard> bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public RegionMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, MapBackedMetadataContainer.byRegionCode())); + } + + @Override + public PhoneMetadata getMetadataForRegion(String regionCode) { + if (!GeoEntityUtility.isGeoEntity(regionCode)) { + throw new IllegalArgumentException(regionCode + " region code is a non-geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(regionCode)) + .getMetadataBy(regionCode); + } +} diff --git a/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java new file mode 100644 index 0000000000..1d3d1eb81b --- /dev/null +++ b/tools/java/java-build/target/classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * {@link PhoneMetadataFileNameProvider} implementation that returns the same metadata file name for + * each key + */ +public final class SingleFileModeFileNameProvider implements PhoneMetadataFileNameProvider { + + private final String phoneMetadataFileName; + + public SingleFileModeFileNameProvider(String phoneMetadataFileName) { + this.phoneMetadataFileName = phoneMetadataFileName; + } + + @Override + public String getFor(Object key) { + return phoneMetadataFileName; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java new file mode 100644 index 0000000000..3975c2d3a0 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AlternateFormatsCountryCodeSet.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.HashSet; +import java.util.Set; + +public class AlternateFormatsCountryCodeSet { + // A set of all country codes for which data is available. + public static Set getCountryCodeSet() { + // The capacity is set to 61 as there are 46 different entries, + // and this offers a load factor of roughly 0.75. + Set countryCodeSet = new HashSet(61); + + countryCodeSet.add(7); + countryCodeSet.add(27); + countryCodeSet.add(30); + countryCodeSet.add(31); + countryCodeSet.add(34); + countryCodeSet.add(36); + countryCodeSet.add(39); + countryCodeSet.add(43); + countryCodeSet.add(44); + countryCodeSet.add(49); + countryCodeSet.add(52); + countryCodeSet.add(54); + countryCodeSet.add(55); + countryCodeSet.add(58); + countryCodeSet.add(61); + countryCodeSet.add(62); + countryCodeSet.add(64); + countryCodeSet.add(66); + countryCodeSet.add(81); + countryCodeSet.add(84); + countryCodeSet.add(90); + countryCodeSet.add(91); + countryCodeSet.add(94); + countryCodeSet.add(95); + countryCodeSet.add(255); + countryCodeSet.add(350); + countryCodeSet.add(351); + countryCodeSet.add(352); + countryCodeSet.add(358); + countryCodeSet.add(359); + countryCodeSet.add(372); + countryCodeSet.add(373); + countryCodeSet.add(380); + countryCodeSet.add(381); + countryCodeSet.add(385); + countryCodeSet.add(505); + countryCodeSet.add(506); + countryCodeSet.add(595); + countryCodeSet.add(675); + countryCodeSet.add(676); + countryCodeSet.add(679); + countryCodeSet.add(855); + countryCodeSet.add(856); + countryCodeSet.add(971); + countryCodeSet.add(972); + countryCodeSet.add(995); + + return countryCodeSet; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java new file mode 100644 index 0000000000..be11be57ea --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/AsYouTypeFormatter.java @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.RegexCache; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A formatter which formats phone numbers as they are entered. + * + *

An AsYouTypeFormatter can be created by invoking + * {@link PhoneNumberUtil#getAsYouTypeFormatter}. After that, digits can be added by invoking + * {@link #inputDigit} on the formatter instance, and the partially formatted phone number will be + * returned each time a digit is added. {@link #clear} can be invoked before formatting a new + * number. + * + *

See the unittests for more details on how the formatter is to be used. + * + * @author Shaopeng Jia + */ +public class AsYouTypeFormatter { + private String currentOutput = ""; + private StringBuilder formattingTemplate = new StringBuilder(); + // The pattern from numberFormat that is currently used to create formattingTemplate. + private String currentFormattingPattern = ""; + private StringBuilder accruedInput = new StringBuilder(); + private StringBuilder accruedInputWithoutFormatting = new StringBuilder(); + // This indicates whether AsYouTypeFormatter is currently doing the formatting. + private boolean ableToFormat = true; + // Set to true when users enter their own formatting. AsYouTypeFormatter will do no formatting at + // all when this is set to true. + private boolean inputHasFormatting = false; + // This is set to true when we know the user is entering a full national significant number, since + // we have either detected a national prefix or an international dialing prefix. When this is + // true, we will no longer use local number formatting patterns. + private boolean isCompleteNumber = false; + private boolean isExpectingCountryCallingCode = false; + private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); + private String defaultCountry; + + // Character used when appropriate to separate a prefix, such as a long NDD or a country calling + // code, from the national number. + private static final char SEPARATOR_BEFORE_NATIONAL_NUMBER = ' '; + private static final PhoneMetadata EMPTY_METADATA = + PhoneMetadata.newBuilder().setId("").setInternationalPrefix("NA").build(); + private PhoneMetadata defaultMetadata; + private PhoneMetadata currentMetadata; + + // A pattern that is used to determine if a numberFormat under availableFormats is eligible to be + // used by the AYTF. It is eligible when the format element under numberFormat contains groups of + // the dollar sign followed by a single digit, separated by valid phone number punctuation. This + // prevents invalid punctuation (such as the star sign in Israeli star numbers) getting into the + // output of the AYTF. We require that the first group is present in the output pattern to ensure + // no data is lost while formatting; when we format as you type, this should always be the case. + private static final Pattern ELIGIBLE_FORMAT_PATTERN = + Pattern.compile("[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*" + + "\\$1" + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*(\\$\\d" + + "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]*)*"); + // A set of characters that, if found in a national prefix formatting rules, are an indicator to + // us that we should separate the national prefix from the number when formatting. + private static final Pattern NATIONAL_PREFIX_SEPARATORS_PATTERN = Pattern.compile("[- ]"); + + // This is the minimum length of national number accrued that is required to trigger the + // formatter. The first element of the leadingDigitsPattern of each numberFormat contains a + // regular expression that matches up to this number of digits. + private static final int MIN_LEADING_DIGITS_LENGTH = 3; + + // The digits that have not been entered yet will be represented by a \u2008, the punctuation + // space. + private static final String DIGIT_PLACEHOLDER = "\u2008"; + private static final Pattern DIGIT_PATTERN = Pattern.compile(DIGIT_PLACEHOLDER); + private int lastMatchPosition = 0; + // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as + // found in the original sequence of characters the user entered. + private int originalPosition = 0; + // The position of a digit upon which inputDigitAndRememberPosition is most recently invoked, as + // found in accruedInputWithoutFormatting. + private int positionToRemember = 0; + // This contains anything that has been entered so far preceding the national significant number, + // and it is formatted (e.g. with space inserted). For example, this can contain IDD, country + // code, and/or NDD, etc. + private StringBuilder prefixBeforeNationalNumber = new StringBuilder(); + private boolean shouldAddSpaceAfterNationalPrefix = false; + // This contains the national prefix that has been extracted. It contains only digits without + // formatting. + private String extractedNationalPrefix = ""; + private StringBuilder nationalNumber = new StringBuilder(); + private List possibleFormats = new ArrayList(); + + // A cache for frequently used country-specific regular expressions. + private RegexCache regexCache = new RegexCache(64); + + /** + * Constructs an as-you-type formatter. Should be obtained from {@link + * PhoneNumberUtil#getAsYouTypeFormatter}. + * + * @param regionCode the country/region where the phone number is being entered + */ + AsYouTypeFormatter(String regionCode) { + defaultCountry = regionCode; + currentMetadata = getMetadataForRegion(defaultCountry); + defaultMetadata = currentMetadata; + } + + // The metadata needed by this class is the same for all regions sharing the same country calling + // code. Therefore, we return the metadata for "main" region for this country calling code. + private PhoneMetadata getMetadataForRegion(String regionCode) { + int countryCallingCode = phoneUtil.getCountryCodeForRegion(regionCode); + String mainCountry = phoneUtil.getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadata = phoneUtil.getMetadataForRegion(mainCountry); + if (metadata != null) { + return metadata; + } + // Set to a default instance of the metadata. This allows us to function with an incorrect + // region code, even if formatting only works for numbers specified with "+". + return EMPTY_METADATA; + } + + // Returns true if a new template is created as opposed to reusing the existing template. + private boolean maybeCreateNewTemplate() { + // When there are multiple available formats, the formatter uses the first format where a + // formatting template could be created. + Iterator it = possibleFormats.iterator(); + while (it.hasNext()) { + NumberFormat numberFormat = it.next(); + String pattern = numberFormat.getPattern(); + if (currentFormattingPattern.equals(pattern)) { + return false; + } + if (createFormattingTemplate(numberFormat)) { + currentFormattingPattern = pattern; + shouldAddSpaceAfterNationalPrefix = + NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher( + numberFormat.getNationalPrefixFormattingRule()).find(); + // With a new formatting template, the matched position using the old template needs to be + // reset. + lastMatchPosition = 0; + return true; + } else { // Remove the current number format from possibleFormats. + it.remove(); + } + } + ableToFormat = false; + return false; + } + + private void getAvailableFormats(String leadingDigits) { + // First decide whether we should use international or national number rules. + boolean isInternationalNumber = isCompleteNumber && extractedNationalPrefix.length() == 0; + List formatList = + (isInternationalNumber && currentMetadata.getIntlNumberFormatCount() > 0) + ? currentMetadata.getIntlNumberFormatList() + : currentMetadata.getNumberFormatList(); + for (NumberFormat format : formatList) { + // Discard a few formats that we know are not relevant based on the presence of the national + // prefix. + if (extractedNationalPrefix.length() > 0 + && PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + format.getNationalPrefixFormattingRule()) + && !format.getNationalPrefixOptionalWhenFormatting() + && !format.hasDomesticCarrierCodeFormattingRule()) { + // If it is a national number that had a national prefix, any rules that aren't valid with a + // national prefix should be excluded. A rule that has a carrier-code formatting rule is + // kept since the national prefix might actually be an extracted carrier code - we don't + // distinguish between these when extracting it in the AYTF. + continue; + } else if (extractedNationalPrefix.length() == 0 + && !isCompleteNumber + && !PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + format.getNationalPrefixFormattingRule()) + && !format.getNationalPrefixOptionalWhenFormatting()) { + // This number was entered without a national prefix, and this formatting rule requires one, + // so we discard it. + continue; + } + if (ELIGIBLE_FORMAT_PATTERN.matcher(format.getFormat()).matches()) { + possibleFormats.add(format); + } + } + narrowDownPossibleFormats(leadingDigits); + } + + private void narrowDownPossibleFormats(String leadingDigits) { + int indexOfLeadingDigitsPattern = leadingDigits.length() - MIN_LEADING_DIGITS_LENGTH; + Iterator it = possibleFormats.iterator(); + while (it.hasNext()) { + NumberFormat format = it.next(); + if (format.getLeadingDigitsPatternCount() == 0) { + // Keep everything that isn't restricted by leading digits. + continue; + } + int lastLeadingDigitsPattern = + Math.min(indexOfLeadingDigitsPattern, format.getLeadingDigitsPatternCount() - 1); + Pattern leadingDigitsPattern = regexCache.getPatternForRegex( + format.getLeadingDigitsPattern(lastLeadingDigitsPattern)); + Matcher m = leadingDigitsPattern.matcher(leadingDigits); + if (!m.lookingAt()) { + it.remove(); + } + } + } + + private boolean createFormattingTemplate(NumberFormat format) { + String numberPattern = format.getPattern(); + formattingTemplate.setLength(0); + String tempTemplate = getFormattingTemplate(numberPattern, format.getFormat()); + if (tempTemplate.length() > 0) { + formattingTemplate.append(tempTemplate); + return true; + } + return false; + } + + // Gets a formatting template which can be used to efficiently format a partial number where + // digits are added one by one. + private String getFormattingTemplate(String numberPattern, String numberFormat) { + // Creates a phone number consisting only of the digit 9 that matches the + // numberPattern by applying the pattern to the longestPhoneNumber string. + String longestPhoneNumber = "999999999999999"; + Matcher m = regexCache.getPatternForRegex(numberPattern).matcher(longestPhoneNumber); + m.find(); // this will always succeed + String aPhoneNumber = m.group(); + // No formatting template can be created if the number of digits entered so far is longer than + // the maximum the current formatting rule can accommodate. + if (aPhoneNumber.length() < nationalNumber.length()) { + return ""; + } + // Formats the number according to numberFormat + String template = aPhoneNumber.replaceAll(numberPattern, numberFormat); + // Replaces each digit with character DIGIT_PLACEHOLDER + template = template.replaceAll("9", DIGIT_PLACEHOLDER); + return template; + } + + /** + * Clears the internal state of the formatter, so it can be reused. + */ + public void clear() { + currentOutput = ""; + accruedInput.setLength(0); + accruedInputWithoutFormatting.setLength(0); + formattingTemplate.setLength(0); + lastMatchPosition = 0; + currentFormattingPattern = ""; + prefixBeforeNationalNumber.setLength(0); + extractedNationalPrefix = ""; + nationalNumber.setLength(0); + ableToFormat = true; + inputHasFormatting = false; + positionToRemember = 0; + originalPosition = 0; + isCompleteNumber = false; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + shouldAddSpaceAfterNationalPrefix = false; + if (!currentMetadata.equals(defaultMetadata)) { + currentMetadata = getMetadataForRegion(defaultCountry); + } + } + + /** + * Formats a phone number on-the-fly as each digit is entered. + * + * @param nextChar the most recently entered digit of a phone number. Formatting characters are + * allowed, but as soon as they are encountered this method formats the number as entered and + * not "as you type" anymore. Full width digits and Arabic-indic digits are allowed, and will + * be shown as they are. + * @return the partially formatted phone number. + */ + public String inputDigit(char nextChar) { + currentOutput = inputDigitWithOptionToRememberPosition(nextChar, false); + return currentOutput; + } + + /** + * Same as {@link #inputDigit}, but remembers the position where {@code nextChar} is inserted, so + * that it can be retrieved later by using {@link #getRememberedPosition}. The remembered + * position will be automatically adjusted if additional formatting characters are later + * inserted/removed in front of {@code nextChar}. + */ + public String inputDigitAndRememberPosition(char nextChar) { + currentOutput = inputDigitWithOptionToRememberPosition(nextChar, true); + return currentOutput; + } + + @SuppressWarnings("fallthrough") + private String inputDigitWithOptionToRememberPosition(char nextChar, boolean rememberPosition) { + accruedInput.append(nextChar); + if (rememberPosition) { + originalPosition = accruedInput.length(); + } + // We do formatting on-the-fly only when each character entered is either a digit, or a plus + // sign (accepted at the start of the number only). + if (!isDigitOrLeadingPlusSign(nextChar)) { + ableToFormat = false; + inputHasFormatting = true; + } else { + nextChar = normalizeAndAccrueDigitsAndPlusSign(nextChar, rememberPosition); + } + if (!ableToFormat) { + // When we are unable to format because of reasons other than that formatting chars have been + // entered, it can be due to really long IDDs or NDDs. If that is the case, we might be able + // to do formatting again after extracting them. + if (inputHasFormatting) { + return accruedInput.toString(); + } else if (attemptToExtractIdd()) { + if (attemptToExtractCountryCallingCode()) { + return attemptToChoosePatternWithPrefixExtracted(); + } + } else if (ableToExtractLongerNdd()) { + // Add an additional space to separate long NDD and national significant number for + // readability. We don't set shouldAddSpaceAfterNationalPrefix to true, since we don't want + // this to change later when we choose formatting templates. + prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + return attemptToChoosePatternWithPrefixExtracted(); + } + return accruedInput.toString(); + } + + // We start to attempt to format only when at least MIN_LEADING_DIGITS_LENGTH digits (the plus + // sign is counted as a digit as well for this purpose) have been entered. + switch (accruedInputWithoutFormatting.length()) { + case 0: + case 1: + case 2: + return accruedInput.toString(); + case 3: + if (attemptToExtractIdd()) { + isExpectingCountryCallingCode = true; + } else { // No IDD or plus sign is found, might be entering in national format. + extractedNationalPrefix = removeNationalPrefixFromNationalNumber(); + return attemptToChooseFormattingPattern(); + } + // fall through + default: + if (isExpectingCountryCallingCode) { + if (attemptToExtractCountryCallingCode()) { + isExpectingCountryCallingCode = false; + } + return prefixBeforeNationalNumber + nationalNumber.toString(); + } + if (possibleFormats.size() > 0) { // The formatting patterns are already chosen. + String tempNationalNumber = inputDigitHelper(nextChar); + // See if the accrued digits can be formatted properly already. If not, use the results + // from inputDigitHelper, which does formatting based on the formatting pattern chosen. + String formattedNumber = attemptToFormatAccruedDigits(); + if (formattedNumber.length() > 0) { + return formattedNumber; + } + narrowDownPossibleFormats(nationalNumber.toString()); + if (maybeCreateNewTemplate()) { + return inputAccruedNationalNumber(); + } + return ableToFormat + ? appendNationalNumber(tempNationalNumber) + : accruedInput.toString(); + } else { + return attemptToChooseFormattingPattern(); + } + } + } + + private String attemptToChoosePatternWithPrefixExtracted() { + ableToFormat = true; + isExpectingCountryCallingCode = false; + possibleFormats.clear(); + lastMatchPosition = 0; + formattingTemplate.setLength(0); + currentFormattingPattern = ""; + return attemptToChooseFormattingPattern(); + } + + // @VisibleForTesting + String getExtractedNationalPrefix() { + return extractedNationalPrefix; + } + + // Some national prefixes are a substring of others. If extracting the shorter NDD doesn't result + // in a number we can format, we try to see if we can extract a longer version here. + private boolean ableToExtractLongerNdd() { + if (extractedNationalPrefix.length() > 0) { + // Put the extracted NDD back to the national number before attempting to extract a new NDD. + nationalNumber.insert(0, extractedNationalPrefix); + // Remove the previously extracted NDD from prefixBeforeNationalNumber. We cannot simply set + // it to empty string because people sometimes incorrectly enter national prefix after the + // country code, e.g. +44 (0)20-1234-5678. + int indexOfPreviousNdd = prefixBeforeNationalNumber.lastIndexOf(extractedNationalPrefix); + prefixBeforeNationalNumber.setLength(indexOfPreviousNdd); + } + return !extractedNationalPrefix.equals(removeNationalPrefixFromNationalNumber()); + } + + private boolean isDigitOrLeadingPlusSign(char nextChar) { + return Character.isDigit(nextChar) + || (accruedInput.length() == 1 + && PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(Character.toString(nextChar)).matches()); + } + + /** + * Checks to see if there is an exact pattern match for these digits. If so, we should use this + * instead of any other formatting template whose leadingDigitsPattern also matches the input. + */ + String attemptToFormatAccruedDigits() { + for (NumberFormat numberFormat : possibleFormats) { + Matcher m = regexCache.getPatternForRegex(numberFormat.getPattern()).matcher(nationalNumber); + if (m.matches()) { + shouldAddSpaceAfterNationalPrefix = + NATIONAL_PREFIX_SEPARATORS_PATTERN.matcher( + numberFormat.getNationalPrefixFormattingRule()).find(); + String formattedNumber = m.replaceAll(numberFormat.getFormat()); + // Check that we did not remove nor add any extra digits when we matched + // this formatting pattern. This usually happens after we entered the last + // digit during AYTF. Eg: In case of MX, we swallow mobile token (1) when + // formatted but AYTF should retain all the number entered and not change + // in order to match a format (of same leading digits and length) display + // in that way. + String fullOutput = appendNationalNumber(formattedNumber); + String formattedNumberDigitsOnly = PhoneNumberUtil.normalizeDiallableCharsOnly(fullOutput); + if (formattedNumberDigitsOnly.contentEquals(accruedInputWithoutFormatting)) { + // If it's the same (i.e entered number and format is same), then it's + // safe to return this in formatted number as nothing is lost / added. + return fullOutput; + } + } + } + return ""; + } + + /** + * Returns the current position in the partially formatted phone number of the character which was + * previously passed in as the parameter of {@link #inputDigitAndRememberPosition}. + */ + public int getRememberedPosition() { + if (!ableToFormat) { + return originalPosition; + } + int accruedInputIndex = 0; + int currentOutputIndex = 0; + while (accruedInputIndex < positionToRemember && currentOutputIndex < currentOutput.length()) { + if (accruedInputWithoutFormatting.charAt(accruedInputIndex) + == currentOutput.charAt(currentOutputIndex)) { + accruedInputIndex++; + } + currentOutputIndex++; + } + return currentOutputIndex; + } + + /** + * Combines the national number with any prefix (IDD/+ and country code or national prefix) that + * was collected. A space will be inserted between them if the current formatting template + * indicates this to be suitable. + */ + private String appendNationalNumber(String nationalNumber) { + int prefixBeforeNationalNumberLength = prefixBeforeNationalNumber.length(); + if (shouldAddSpaceAfterNationalPrefix && prefixBeforeNationalNumberLength > 0 + && prefixBeforeNationalNumber.charAt(prefixBeforeNationalNumberLength - 1) + != SEPARATOR_BEFORE_NATIONAL_NUMBER) { + // We want to add a space after the national prefix if the national prefix formatting rule + // indicates that this would normally be done, with the exception of the case where we already + // appended a space because the NDD was surprisingly long. + return new String(prefixBeforeNationalNumber) + SEPARATOR_BEFORE_NATIONAL_NUMBER + + nationalNumber; + } else { + return prefixBeforeNationalNumber + nationalNumber; + } + } + + /** + * 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 at least MIN_LEADING_DIGITS_LENGTH digits of national + // number (excluding national prefix) have been entered. + if (nationalNumber.length() >= MIN_LEADING_DIGITS_LENGTH) { + + getAvailableFormats(nationalNumber.toString()); + // See if the accrued digits can be formatted properly already. + String formattedNumber = attemptToFormatAccruedDigits(); + if (formattedNumber.length() > 0) { + return formattedNumber; + } + return maybeCreateNewTemplate() ? inputAccruedNationalNumber() : accruedInput.toString(); + } else { + return appendNationalNumber(nationalNumber.toString()); + } + } + + /** + * Invokes inputDigitHelper on each digit of the national number accrued, and returns a formatted + * string in the end. + */ + private String inputAccruedNationalNumber() { + int lengthOfNationalNumber = nationalNumber.length(); + if (lengthOfNationalNumber > 0) { + String tempNationalNumber = ""; + for (int i = 0; i < lengthOfNationalNumber; i++) { + tempNationalNumber = inputDigitHelper(nationalNumber.charAt(i)); + } + return ableToFormat ? appendNationalNumber(tempNationalNumber) : accruedInput.toString(); + } else { + return prefixBeforeNationalNumber.toString(); + } + } + + /** + * Returns true if the current country is a NANPA country and the national number begins with + * the national prefix. + */ + private boolean isNanpaNumberWithNationalPrefix() { + // For NANPA numbers beginning with 1[2-9], treat the 1 as the national prefix. The reason is + // that national significant numbers in NANPA always start with [2-9] after the national prefix. + // Numbers beginning with 1[01] can only be short/emergency numbers, which don't need the + // national prefix. + return (currentMetadata.getCountryCode() == 1) && (nationalNumber.charAt(0) == '1') + && (nationalNumber.charAt(1) != '0') && (nationalNumber.charAt(1) != '1'); + } + + // Returns the national prefix extracted, or an empty string if it is not present. + private String removeNationalPrefixFromNationalNumber() { + int startOfNationalNumber = 0; + if (isNanpaNumberWithNationalPrefix()) { + startOfNationalNumber = 1; + prefixBeforeNationalNumber.append('1').append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + isCompleteNumber = true; + } else if (currentMetadata.hasNationalPrefixForParsing()) { + Pattern nationalPrefixForParsing = + regexCache.getPatternForRegex(currentMetadata.getNationalPrefixForParsing()); + Matcher m = nationalPrefixForParsing.matcher(nationalNumber); + // Since some national prefix patterns are entirely optional, check that a national prefix + // could actually be extracted. + if (m.lookingAt() && m.end() > 0) { + // When the national prefix is detected, we use international formatting rules instead of + // national ones, because national formatting rules could contain local formatting rules + // for numbers entered without area code. + isCompleteNumber = true; + startOfNationalNumber = m.end(); + prefixBeforeNationalNumber.append(nationalNumber.substring(0, startOfNationalNumber)); + } + } + String nationalPrefix = nationalNumber.substring(0, startOfNationalNumber); + nationalNumber.delete(0, startOfNationalNumber); + return nationalPrefix; + } + + /** + * Extracts IDD and plus sign to prefixBeforeNationalNumber when they are available, and places + * the remaining input into nationalNumber. + * + * @return true when accruedInputWithoutFormatting begins with the plus sign or valid IDD for + * defaultCountry. + */ + private boolean attemptToExtractIdd() { + Pattern internationalPrefix = + regexCache.getPatternForRegex("\\" + PhoneNumberUtil.PLUS_SIGN + "|" + + currentMetadata.getInternationalPrefix()); + Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting); + if (iddMatcher.lookingAt()) { + isCompleteNumber = true; + int startOfCountryCallingCode = iddMatcher.end(); + nationalNumber.setLength(0); + nationalNumber.append(accruedInputWithoutFormatting.substring(startOfCountryCallingCode)); + prefixBeforeNationalNumber.setLength(0); + prefixBeforeNationalNumber.append( + accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode)); + if (accruedInputWithoutFormatting.charAt(0) != PhoneNumberUtil.PLUS_SIGN) { + prefixBeforeNationalNumber.append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + } + return true; + } + return false; + } + + /** + * Extracts the country calling code from the beginning of nationalNumber to + * prefixBeforeNationalNumber when they are available, and places the remaining input into + * nationalNumber. + * + * @return true when a valid country calling code can be found. + */ + private boolean attemptToExtractCountryCallingCode() { + if (nationalNumber.length() == 0) { + return false; + } + StringBuilder numberWithoutCountryCallingCode = new StringBuilder(); + int countryCode = phoneUtil.extractCountryCode(nationalNumber, numberWithoutCountryCallingCode); + if (countryCode == 0) { + return false; + } + nationalNumber.setLength(0); + nationalNumber.append(numberWithoutCountryCallingCode); + String newRegionCode = phoneUtil.getRegionCodeForCountryCode(countryCode); + if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(newRegionCode)) { + currentMetadata = phoneUtil.getMetadataForNonGeographicalRegion(countryCode); + } else if (!newRegionCode.equals(defaultCountry)) { + currentMetadata = getMetadataForRegion(newRegionCode); + } + String countryCodeString = Integer.toString(countryCode); + prefixBeforeNationalNumber.append(countryCodeString).append(SEPARATOR_BEFORE_NATIONAL_NUMBER); + // When we have successfully extracted the IDD, the previously extracted NDD should be cleared + // because it is no longer valid. + extractedNationalPrefix = ""; + return true; + } + + // Accrues digits and the plus sign to accruedInputWithoutFormatting for later use. If nextChar + // contains a digit in non-ASCII format (e.g. the full-width version of digits), it is first + // normalized to the ASCII version. The return value is nextChar itself, or its normalized + // version, if nextChar is a digit in non-ASCII format. This method assumes its input is either a + // digit or the plus sign. + private char normalizeAndAccrueDigitsAndPlusSign(char nextChar, boolean rememberPosition) { + char normalizedChar; + if (nextChar == PhoneNumberUtil.PLUS_SIGN) { + normalizedChar = nextChar; + accruedInputWithoutFormatting.append(nextChar); + } else { + int radix = 10; + normalizedChar = Character.forDigit(Character.digit(nextChar, radix), radix); + accruedInputWithoutFormatting.append(normalizedChar); + nationalNumber.append(normalizedChar); + } + if (rememberPosition) { + positionToRemember = accruedInputWithoutFormatting.length(); + } + return normalizedChar; + } + + private String inputDigitHelper(char nextChar) { + // Note that formattingTemplate is not guaranteed to have a value, it could be empty, e.g. + // when the next digit is entered after extracting an IDD or NDD. + Matcher digitMatcher = DIGIT_PATTERN.matcher(formattingTemplate); + if (digitMatcher.find(lastMatchPosition)) { + String tempTemplate = digitMatcher.replaceFirst(Character.toString(nextChar)); + formattingTemplate.replace(0, tempTemplate.length(), tempTemplate); + lastMatchPosition = digitMatcher.start(); + return formattingTemplate.substring(0, lastMatchPosition + 1); + } else { + if (possibleFormats.size() == 1) { + // More digits are entered than we could handle, and there are no other valid patterns to + // try. + ableToFormat = false; + } // else, we just reset the formatting pattern. + currentFormattingPattern = ""; + return accruedInput.toString(); + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java new file mode 100644 index 0000000000..06571d15f0 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMap.java @@ -0,0 +1,942 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CountryCodeToRegionCodeMap { + // A mapping from a country code to the region codes which denote the + // country/region represented by that country code. In the case of multiple + // countries sharing a calling code, such as the NANPA countries, the one + // indicated with "isMainCountryForCode" in the metadata should be first. + public static Map> getCountryCodeToRegionCodeMap() { + // The capacity is set to 286 as there are 215 different entries, + // and this offers a load factor of roughly 0.75. + Map> countryCodeToRegionCodeMap = + new HashMap>(286); + + ArrayList listWithRegionCode; + + listWithRegionCode = new ArrayList(25); + listWithRegionCode.add("US"); + listWithRegionCode.add("AG"); + listWithRegionCode.add("AI"); + listWithRegionCode.add("AS"); + listWithRegionCode.add("BB"); + listWithRegionCode.add("BM"); + listWithRegionCode.add("BS"); + listWithRegionCode.add("CA"); + listWithRegionCode.add("DM"); + listWithRegionCode.add("DO"); + listWithRegionCode.add("GD"); + listWithRegionCode.add("GU"); + listWithRegionCode.add("JM"); + listWithRegionCode.add("KN"); + listWithRegionCode.add("KY"); + listWithRegionCode.add("LC"); + listWithRegionCode.add("MP"); + listWithRegionCode.add("MS"); + listWithRegionCode.add("PR"); + listWithRegionCode.add("SX"); + listWithRegionCode.add("TC"); + listWithRegionCode.add("TT"); + listWithRegionCode.add("VC"); + listWithRegionCode.add("VG"); + listWithRegionCode.add("VI"); + countryCodeToRegionCodeMap.put(1, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("RU"); + listWithRegionCode.add("KZ"); + countryCodeToRegionCodeMap.put(7, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EG"); + countryCodeToRegionCodeMap.put(20, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZA"); + countryCodeToRegionCodeMap.put(27, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GR"); + countryCodeToRegionCodeMap.put(30, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NL"); + countryCodeToRegionCodeMap.put(31, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BE"); + countryCodeToRegionCodeMap.put(32, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FR"); + countryCodeToRegionCodeMap.put(33, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ES"); + countryCodeToRegionCodeMap.put(34, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HU"); + countryCodeToRegionCodeMap.put(36, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("IT"); + listWithRegionCode.add("VA"); + countryCodeToRegionCodeMap.put(39, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RO"); + countryCodeToRegionCodeMap.put(40, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CH"); + countryCodeToRegionCodeMap.put(41, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AT"); + countryCodeToRegionCodeMap.put(43, listWithRegionCode); + + listWithRegionCode = new ArrayList(4); + listWithRegionCode.add("GB"); + listWithRegionCode.add("GG"); + listWithRegionCode.add("IM"); + listWithRegionCode.add("JE"); + countryCodeToRegionCodeMap.put(44, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DK"); + countryCodeToRegionCodeMap.put(45, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SE"); + countryCodeToRegionCodeMap.put(46, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("NO"); + listWithRegionCode.add("SJ"); + countryCodeToRegionCodeMap.put(47, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PL"); + countryCodeToRegionCodeMap.put(48, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DE"); + countryCodeToRegionCodeMap.put(49, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PE"); + countryCodeToRegionCodeMap.put(51, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MX"); + countryCodeToRegionCodeMap.put(52, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CU"); + countryCodeToRegionCodeMap.put(53, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AR"); + countryCodeToRegionCodeMap.put(54, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BR"); + countryCodeToRegionCodeMap.put(55, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CL"); + countryCodeToRegionCodeMap.put(56, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CO"); + countryCodeToRegionCodeMap.put(57, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VE"); + countryCodeToRegionCodeMap.put(58, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MY"); + countryCodeToRegionCodeMap.put(60, listWithRegionCode); + + listWithRegionCode = new ArrayList(3); + listWithRegionCode.add("AU"); + listWithRegionCode.add("CC"); + listWithRegionCode.add("CX"); + countryCodeToRegionCodeMap.put(61, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ID"); + countryCodeToRegionCodeMap.put(62, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PH"); + countryCodeToRegionCodeMap.put(63, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NZ"); + countryCodeToRegionCodeMap.put(64, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SG"); + countryCodeToRegionCodeMap.put(65, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TH"); + countryCodeToRegionCodeMap.put(66, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("JP"); + countryCodeToRegionCodeMap.put(81, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KR"); + countryCodeToRegionCodeMap.put(82, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VN"); + countryCodeToRegionCodeMap.put(84, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CN"); + countryCodeToRegionCodeMap.put(86, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TR"); + countryCodeToRegionCodeMap.put(90, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IN"); + countryCodeToRegionCodeMap.put(91, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PK"); + countryCodeToRegionCodeMap.put(92, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AF"); + countryCodeToRegionCodeMap.put(93, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LK"); + countryCodeToRegionCodeMap.put(94, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MM"); + countryCodeToRegionCodeMap.put(95, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IR"); + countryCodeToRegionCodeMap.put(98, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SS"); + countryCodeToRegionCodeMap.put(211, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("MA"); + listWithRegionCode.add("EH"); + countryCodeToRegionCodeMap.put(212, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DZ"); + countryCodeToRegionCodeMap.put(213, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TN"); + countryCodeToRegionCodeMap.put(216, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LY"); + countryCodeToRegionCodeMap.put(218, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GM"); + countryCodeToRegionCodeMap.put(220, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SN"); + countryCodeToRegionCodeMap.put(221, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MR"); + countryCodeToRegionCodeMap.put(222, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ML"); + countryCodeToRegionCodeMap.put(223, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GN"); + countryCodeToRegionCodeMap.put(224, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CI"); + countryCodeToRegionCodeMap.put(225, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BF"); + countryCodeToRegionCodeMap.put(226, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NE"); + countryCodeToRegionCodeMap.put(227, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TG"); + countryCodeToRegionCodeMap.put(228, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BJ"); + countryCodeToRegionCodeMap.put(229, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MU"); + countryCodeToRegionCodeMap.put(230, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LR"); + countryCodeToRegionCodeMap.put(231, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SL"); + countryCodeToRegionCodeMap.put(232, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GH"); + countryCodeToRegionCodeMap.put(233, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NG"); + countryCodeToRegionCodeMap.put(234, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TD"); + countryCodeToRegionCodeMap.put(235, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CF"); + countryCodeToRegionCodeMap.put(236, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CM"); + countryCodeToRegionCodeMap.put(237, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CV"); + countryCodeToRegionCodeMap.put(238, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ST"); + countryCodeToRegionCodeMap.put(239, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GQ"); + countryCodeToRegionCodeMap.put(240, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GA"); + countryCodeToRegionCodeMap.put(241, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CG"); + countryCodeToRegionCodeMap.put(242, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CD"); + countryCodeToRegionCodeMap.put(243, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AO"); + countryCodeToRegionCodeMap.put(244, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GW"); + countryCodeToRegionCodeMap.put(245, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IO"); + countryCodeToRegionCodeMap.put(246, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AC"); + countryCodeToRegionCodeMap.put(247, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SC"); + countryCodeToRegionCodeMap.put(248, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SD"); + countryCodeToRegionCodeMap.put(249, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RW"); + countryCodeToRegionCodeMap.put(250, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ET"); + countryCodeToRegionCodeMap.put(251, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SO"); + countryCodeToRegionCodeMap.put(252, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("DJ"); + countryCodeToRegionCodeMap.put(253, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KE"); + countryCodeToRegionCodeMap.put(254, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TZ"); + countryCodeToRegionCodeMap.put(255, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UG"); + countryCodeToRegionCodeMap.put(256, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BI"); + countryCodeToRegionCodeMap.put(257, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MZ"); + countryCodeToRegionCodeMap.put(258, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZM"); + countryCodeToRegionCodeMap.put(260, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MG"); + countryCodeToRegionCodeMap.put(261, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("RE"); + listWithRegionCode.add("YT"); + countryCodeToRegionCodeMap.put(262, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ZW"); + countryCodeToRegionCodeMap.put(263, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NA"); + countryCodeToRegionCodeMap.put(264, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MW"); + countryCodeToRegionCodeMap.put(265, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LS"); + countryCodeToRegionCodeMap.put(266, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BW"); + countryCodeToRegionCodeMap.put(267, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SZ"); + countryCodeToRegionCodeMap.put(268, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KM"); + countryCodeToRegionCodeMap.put(269, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("SH"); + listWithRegionCode.add("TA"); + countryCodeToRegionCodeMap.put(290, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ER"); + countryCodeToRegionCodeMap.put(291, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AW"); + countryCodeToRegionCodeMap.put(297, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FO"); + countryCodeToRegionCodeMap.put(298, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GL"); + countryCodeToRegionCodeMap.put(299, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GI"); + countryCodeToRegionCodeMap.put(350, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PT"); + countryCodeToRegionCodeMap.put(351, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LU"); + countryCodeToRegionCodeMap.put(352, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IE"); + countryCodeToRegionCodeMap.put(353, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IS"); + countryCodeToRegionCodeMap.put(354, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AL"); + countryCodeToRegionCodeMap.put(355, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MT"); + countryCodeToRegionCodeMap.put(356, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CY"); + countryCodeToRegionCodeMap.put(357, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("FI"); + listWithRegionCode.add("AX"); + countryCodeToRegionCodeMap.put(358, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BG"); + countryCodeToRegionCodeMap.put(359, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LT"); + countryCodeToRegionCodeMap.put(370, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LV"); + countryCodeToRegionCodeMap.put(371, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EE"); + countryCodeToRegionCodeMap.put(372, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MD"); + countryCodeToRegionCodeMap.put(373, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AM"); + countryCodeToRegionCodeMap.put(374, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BY"); + countryCodeToRegionCodeMap.put(375, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AD"); + countryCodeToRegionCodeMap.put(376, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MC"); + countryCodeToRegionCodeMap.put(377, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SM"); + countryCodeToRegionCodeMap.put(378, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UA"); + countryCodeToRegionCodeMap.put(380, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("RS"); + countryCodeToRegionCodeMap.put(381, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("ME"); + countryCodeToRegionCodeMap.put(382, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("XK"); + countryCodeToRegionCodeMap.put(383, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HR"); + countryCodeToRegionCodeMap.put(385, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SI"); + countryCodeToRegionCodeMap.put(386, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BA"); + countryCodeToRegionCodeMap.put(387, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MK"); + countryCodeToRegionCodeMap.put(389, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CZ"); + countryCodeToRegionCodeMap.put(420, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SK"); + countryCodeToRegionCodeMap.put(421, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LI"); + countryCodeToRegionCodeMap.put(423, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FK"); + countryCodeToRegionCodeMap.put(500, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BZ"); + countryCodeToRegionCodeMap.put(501, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GT"); + countryCodeToRegionCodeMap.put(502, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SV"); + countryCodeToRegionCodeMap.put(503, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HN"); + countryCodeToRegionCodeMap.put(504, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NI"); + countryCodeToRegionCodeMap.put(505, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CR"); + countryCodeToRegionCodeMap.put(506, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PA"); + countryCodeToRegionCodeMap.put(507, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PM"); + countryCodeToRegionCodeMap.put(508, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HT"); + countryCodeToRegionCodeMap.put(509, listWithRegionCode); + + listWithRegionCode = new ArrayList(3); + listWithRegionCode.add("GP"); + listWithRegionCode.add("BL"); + listWithRegionCode.add("MF"); + countryCodeToRegionCodeMap.put(590, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BO"); + countryCodeToRegionCodeMap.put(591, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GY"); + countryCodeToRegionCodeMap.put(592, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("EC"); + countryCodeToRegionCodeMap.put(593, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GF"); + countryCodeToRegionCodeMap.put(594, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PY"); + countryCodeToRegionCodeMap.put(595, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MQ"); + countryCodeToRegionCodeMap.put(596, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SR"); + countryCodeToRegionCodeMap.put(597, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UY"); + countryCodeToRegionCodeMap.put(598, listWithRegionCode); + + listWithRegionCode = new ArrayList(2); + listWithRegionCode.add("CW"); + listWithRegionCode.add("BQ"); + countryCodeToRegionCodeMap.put(599, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TL"); + countryCodeToRegionCodeMap.put(670, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NF"); + countryCodeToRegionCodeMap.put(672, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BN"); + countryCodeToRegionCodeMap.put(673, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NR"); + countryCodeToRegionCodeMap.put(674, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PG"); + countryCodeToRegionCodeMap.put(675, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TO"); + countryCodeToRegionCodeMap.put(676, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SB"); + countryCodeToRegionCodeMap.put(677, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("VU"); + countryCodeToRegionCodeMap.put(678, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FJ"); + countryCodeToRegionCodeMap.put(679, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PW"); + countryCodeToRegionCodeMap.put(680, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("WF"); + countryCodeToRegionCodeMap.put(681, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("CK"); + countryCodeToRegionCodeMap.put(682, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NU"); + countryCodeToRegionCodeMap.put(683, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("WS"); + countryCodeToRegionCodeMap.put(685, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KI"); + countryCodeToRegionCodeMap.put(686, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NC"); + countryCodeToRegionCodeMap.put(687, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TV"); + countryCodeToRegionCodeMap.put(688, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PF"); + countryCodeToRegionCodeMap.put(689, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TK"); + countryCodeToRegionCodeMap.put(690, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("FM"); + countryCodeToRegionCodeMap.put(691, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MH"); + countryCodeToRegionCodeMap.put(692, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(800, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(808, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KP"); + countryCodeToRegionCodeMap.put(850, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("HK"); + countryCodeToRegionCodeMap.put(852, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MO"); + countryCodeToRegionCodeMap.put(853, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KH"); + countryCodeToRegionCodeMap.put(855, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LA"); + countryCodeToRegionCodeMap.put(856, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(870, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(878, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BD"); + countryCodeToRegionCodeMap.put(880, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(881, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(882, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(883, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TW"); + countryCodeToRegionCodeMap.put(886, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(888, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MV"); + countryCodeToRegionCodeMap.put(960, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("LB"); + countryCodeToRegionCodeMap.put(961, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("JO"); + countryCodeToRegionCodeMap.put(962, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SY"); + countryCodeToRegionCodeMap.put(963, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IQ"); + countryCodeToRegionCodeMap.put(964, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KW"); + countryCodeToRegionCodeMap.put(965, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("SA"); + countryCodeToRegionCodeMap.put(966, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("YE"); + countryCodeToRegionCodeMap.put(967, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("OM"); + countryCodeToRegionCodeMap.put(968, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("PS"); + countryCodeToRegionCodeMap.put(970, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AE"); + countryCodeToRegionCodeMap.put(971, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("IL"); + countryCodeToRegionCodeMap.put(972, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BH"); + countryCodeToRegionCodeMap.put(973, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("QA"); + countryCodeToRegionCodeMap.put(974, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("BT"); + countryCodeToRegionCodeMap.put(975, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("MN"); + countryCodeToRegionCodeMap.put(976, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("NP"); + countryCodeToRegionCodeMap.put(977, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("001"); + countryCodeToRegionCodeMap.put(979, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TJ"); + countryCodeToRegionCodeMap.put(992, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("TM"); + countryCodeToRegionCodeMap.put(993, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("AZ"); + countryCodeToRegionCodeMap.put(994, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("GE"); + countryCodeToRegionCodeMap.put(995, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("KG"); + countryCodeToRegionCodeMap.put(996, listWithRegionCode); + + listWithRegionCode = new ArrayList(1); + listWithRegionCode.add("UZ"); + countryCodeToRegionCodeMap.put(998, listWithRegionCode); + + return countryCodeToRegionCodeMap; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MetadataLoader.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MetadataLoader.java new file mode 100644 index 0000000000..44fa0dc445 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MetadataLoader.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import java.io.InputStream; + +/** + * Interface for clients to specify a customized phone metadata loader, useful for Android apps to + * load Android resources since the library loads Java resources by default, e.g. with + * + * AssetManager. Note that implementation owners have the responsibility to ensure this is + * thread-safe. + */ +public interface MetadataLoader { + /** + * Returns an input stream corresponding to the metadata to load. This method may be called + * concurrently so implementations must be thread-safe. + * + * @param metadataFileName file name (including path) of metadata to load. File path is an + * absolute class path like /com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto + * @return the input stream for the metadata file. The library will close this stream + * after it is done. Return null in case the metadata file could not be found + */ + public InputStream loadMetadata(String metadataFileName); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MissingMetadataException.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MissingMetadataException.java new file mode 100644 index 0000000000..c2a8544ca3 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/MissingMetadataException.java @@ -0,0 +1,9 @@ +package com.google.i18n.phonenumbers; + +/** Exception class for cases when expected metadata cannot be found. */ +public final class MissingMetadataException extends IllegalStateException { + + public MissingMetadataException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/NumberParseException.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/NumberParseException.java new file mode 100644 index 0000000000..ef3dfa11b8 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/NumberParseException.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +/** + * Generic exception class for errors encountered when parsing phone numbers. + */ +@SuppressWarnings("serial") +public class NumberParseException extends Exception { + + /** + * The reason that a string could not be interpreted as a phone number. + */ + public enum ErrorType { + /** + * The country code supplied did not belong to a supported country or non-geographical entity. + */ + INVALID_COUNTRY_CODE, + /** + * This indicates the string passed is not a valid number. Either the string had less than 3 + * digits in it or had an invalid phone-context parameter. More specifically, the number failed + * to match the regular expression VALID_PHONE_NUMBER, RFC3966_GLOBAL_NUMBER_DIGITS, or + * RFC3966_DOMAINNAME in PhoneNumberUtil.java. + */ + NOT_A_NUMBER, + /** + * This indicates the string started with an international dialing prefix, but after this was + * stripped from the number, had less digits than any valid phone number (including country + * code) could have. + */ + TOO_SHORT_AFTER_IDD, + /** + * This indicates the string, after any country code has been stripped, had less digits than any + * valid phone number could have. + */ + TOO_SHORT_NSN, + /** + * This indicates the string had more digits than any valid phone number could have. + */ + TOO_LONG, + } + + private ErrorType errorType; + private String message; + + public NumberParseException(ErrorType errorType, String message) { + super(message); + this.message = message; + this.errorType = errorType; + } + + /** + * Returns the error type of the exception that has been thrown. + */ + public ErrorType getErrorType() { + return errorType; + } + + @Override + public String toString() { + return "Error type: " + errorType + ". " + message; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java new file mode 100644 index 0000000000..de95eac96d --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatch.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import java.util.Arrays; + +/** + * The immutable match of a phone number within a piece of text. Matches may be found using + * {@link PhoneNumberUtil#findNumbers}. + * + *

A match consists of the {@linkplain #number() phone number} as well as the + * {@linkplain #start() start} and {@linkplain #end() end} offsets of the corresponding subsequence + * of the searched text. Use {@link #rawString()} to obtain a copy of the matched subsequence. + * + *

The following annotated example clarifies the relationship between the searched text, the + * match offsets, and the parsed number: + + *

+ * CharSequence text = "Call me at +1 425 882-8080 for details.";
+ * String country = "US";
+ * PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ *
+ * // Find the first phone number match:
+ * PhoneNumberMatch m = util.findNumbers(text, country).iterator().next();
+ *
+ * // rawString() contains the phone number as it appears in the text.
+ * "+1 425 882-8080".equals(m.rawString());
+ *
+ * // start() and end() define the range of the matched subsequence.
+ * CharSequence subsequence = text.subSequence(m.start(), m.end());
+ * "+1 425 882-8080".contentEquals(subsequence);
+ *
+ * // number() returns the the same result as PhoneNumberUtil.{@link PhoneNumberUtil#parse parse()}
+ * // invoked on rawString().
+ * util.parse(m.rawString(), country).equals(m.number());
+ * 
+ */ +public final class PhoneNumberMatch { + /** The start index into the text. */ + private final int start; + /** The raw substring matched. */ + private final String rawString; + /** The matched phone number. */ + private final PhoneNumber number; + + /** + * Creates a new match. + * + * @param start the start index into the target text + * @param rawString the matched substring of the target text + * @param number the matched phone number + */ + PhoneNumberMatch(int start, String rawString, PhoneNumber number) { + if (start < 0) { + throw new IllegalArgumentException("Start index must be >= 0."); + } + if (rawString == null || number == null) { + throw new NullPointerException(); + } + this.start = start; + this.rawString = rawString; + this.number = number; + } + + /** Returns the phone number matched by the receiver. */ + public PhoneNumber number() { + return number; + } + + /** Returns the start index of the matched phone number within the searched text. */ + public int start() { + return start; + } + + /** Returns the exclusive end index of the matched phone number within the searched text. */ + public int end() { + return start + rawString.length(); + } + + /** Returns the raw string matched as a phone number in the searched text. */ + public String rawString() { + return rawString; + } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[]{start, rawString, number}); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PhoneNumberMatch)) { + return false; + } + PhoneNumberMatch other = (PhoneNumberMatch) obj; + return rawString.equals(other.rawString) && (start == other.start) + && number.equals(other.number); + } + + @Override + public String toString() { + return "PhoneNumberMatch [" + start() + "," + end() + ") " + rawString; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java new file mode 100644 index 0000000000..b812551db0 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberMatcher.java @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2011 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.PhoneNumberUtil.Leniency; +import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType; +import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.internal.RegexCache; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import java.lang.Character.UnicodeBlock; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A stateful class that finds and extracts telephone numbers from {@linkplain CharSequence text}. + * Instances can be created using the {@linkplain PhoneNumberUtil#findNumbers factory methods} in + * {@link PhoneNumberUtil}. + * + *

Vanity numbers (phone numbers using alphabetic digits such as 1-800-SIX-FLAGS are + * not found. + * + *

This class is not thread-safe. + */ +final class PhoneNumberMatcher implements Iterator { + /** + * The phone number pattern used by {@link #find}, similar to + * {@code PhoneNumberUtil.VALID_PHONE_NUMBER}, but with the following differences: + *

    + *
  • All captures are limited in order to place an upper bound to the text matched by the + * pattern. + *
      + *
    • Leading punctuation / plus signs are limited. + *
    • Consecutive occurrences of punctuation are limited. + *
    • Number of digits is limited. + *
    + *
  • No whitespace is allowed at the start or end. + *
  • No alpha digits (vanity numbers such as 1-800-SIX-FLAGS) are currently supported. + *
+ */ + private static final Pattern PATTERN; + /** + * Matches strings that look like publication pages. Example: + *
Computing Complete Answers to Queries in the Presence of Limited Access Patterns.
+   * Chen Li. VLDB J. 12(3): 211-227 (2003).
+ * + * The string "211-227 (2003)" is not a telephone number. + */ + private static final Pattern PUB_PAGES = Pattern.compile("\\d{1,5}-+\\d{1,5}\\s{0,4}\\(\\d{1,4}"); + + /** + * Matches strings that look like dates using "/" as a separator. Examples: 3/10/2011, 31/10/96 or + * 08/31/95. + */ + private static final Pattern SLASH_SEPARATED_DATES = + Pattern.compile("(?:(?:[0-3]?\\d/[01]?\\d)|(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}"); + + /** + * Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does not include the + * trailing ":\d\d" -- that is covered by TIME_STAMPS_SUFFIX. + */ + private static final Pattern TIME_STAMPS = + Pattern.compile("[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d +[0-2]\\d$"); + private static final Pattern TIME_STAMPS_SUFFIX = Pattern.compile(":[0-5]\\d"); + + /** + * Pattern to check that brackets match. Opening brackets should be closed within a phone number. + * This also checks that there is something inside the brackets. Having no brackets at all is also + * fine. + */ + private static final Pattern MATCHING_BRACKETS; + + /** + * Patterns used to extract phone numbers from a larger phone-number-like pattern. These are + * ordered according to specificity. For example, white-space is last since that is frequently + * used in numbers, not just to separate two numbers. We have separate patterns since we don't + * want to break up the phone-number-like text on more than one different kind of symbol at one + * time, although symbols of the same type (e.g. space) can be safely grouped together. + * + * Note that if there is a match, we will always check any text found up to the first match as + * well. + */ + private static final Pattern[] INNER_MATCHES = { + // Breaks on the slash - e.g. "651-234-2345/332-445-1234" + Pattern.compile("/+(.*)"), + // Note that the bracket here is inside the capturing group, since we consider it part of the + // phone number. Will match a pattern like "(650) 223 3345 (754) 223 3321". + Pattern.compile("(\\([^(]*)"), + // Breaks on a hyphen - e.g. "12345 - 332-445-1234 is my number." + // We require a space on either side of the hyphen for it to be considered a separator. + Pattern.compile("(?:\\p{Z}-|-\\p{Z})\\p{Z}*(.+)"), + // Various types of wide hyphens. Note we have decided not to enforce a space here, since it's + // possible that it's supposed to be used to break two numbers without spaces, and we haven't + // seen many instances of it used within a number. + Pattern.compile("[\u2012-\u2015\uFF0D]\\p{Z}*(.+)"), + // Breaks on a full stop - e.g. "12345. 332-445-1234 is my number." + Pattern.compile("\\.+\\p{Z}*([^.]+)"), + // Breaks on space - e.g. "3324451234 8002341234" + Pattern.compile("\\p{Z}+(\\P{Z}+)") + }; + + /** + * Punctuation that may be at the start of a phone number - brackets and plus signs. + */ + private static final Pattern LEAD_CLASS; + + static { + /* Builds the MATCHING_BRACKETS and PATTERN regular expressions. The building blocks below exist + * to make the pattern more easily understood. */ + + String openingParens = "(\\[\uFF08\uFF3B"; + String closingParens = ")\\]\uFF09\uFF3D"; + String nonParens = "[^" + openingParens + closingParens + "]"; + + /* Limit on the number of pairs of brackets in a phone number. */ + String bracketPairLimit = limit(0, 3); + /* + * An opening bracket at the beginning may not be closed, but subsequent ones should be. It's + * also possible that the leading bracket was dropped, so we shouldn't be surprised if we see a + * closing bracket first. We limit the sets of brackets in a phone number to four. + */ + MATCHING_BRACKETS = Pattern.compile( + "(?:[" + openingParens + "])?" + "(?:" + nonParens + "+" + "[" + closingParens + "])?" + + nonParens + "+" + + "(?:[" + openingParens + "]" + nonParens + "+[" + closingParens + "])" + bracketPairLimit + + nonParens + "*"); + + /* Limit on the number of leading (plus) characters. */ + String leadLimit = limit(0, 2); + /* Limit on the number of consecutive punctuation characters. */ + String punctuationLimit = limit(0, 4); + /* The maximum number of digits allowed in a digit-separated block. As we allow all digits in a + * single block, set high enough to accommodate the entire national number and the international + * country code. */ + int digitBlockLimit = + PhoneNumberUtil.MAX_LENGTH_FOR_NSN + PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE; + /* Limit on the number of blocks separated by punctuation. Uses digitBlockLimit since some + * formats use spaces to separate each digit. */ + String blockLimit = limit(0, digitBlockLimit); + + /* A punctuation sequence allowing white space. */ + String punctuation = "[" + PhoneNumberUtil.VALID_PUNCTUATION + "]" + punctuationLimit; + /* A digits block without punctuation. */ + String digitSequence = "\\p{Nd}" + limit(1, digitBlockLimit); + + String leadClassChars = openingParens + PhoneNumberUtil.PLUS_CHARS; + String leadClass = "[" + leadClassChars + "]"; + LEAD_CLASS = Pattern.compile(leadClass); + + /* Phone number pattern allowing optional punctuation. */ + PATTERN = Pattern.compile( + "(?:" + leadClass + punctuation + ")" + leadLimit + + digitSequence + "(?:" + punctuation + digitSequence + ")" + blockLimit + + "(?:" + PhoneNumberUtil.EXTN_PATTERNS_FOR_MATCHING + ")?", + PhoneNumberUtil.REGEX_FLAGS); + } + + /** Returns a regular expression quantifier with an upper and lower limit. */ + private static String limit(int lower, int upper) { + if ((lower < 0) || (upper <= 0) || (upper < lower)) { + throw new IllegalArgumentException(); + } + return "{" + lower + "," + upper + "}"; + } + + /** The potential states of a PhoneNumberMatcher. */ + private enum State { + NOT_READY, READY, DONE + } + + /** The phone number utility. */ + private final PhoneNumberUtil phoneUtil; + /** The text searched for phone numbers. */ + private final CharSequence text; + /** + * The region (country) to assume for phone numbers without an international prefix, possibly + * null. + */ + private final String preferredRegion; + /** The degree of validation requested. */ + private final Leniency leniency; + /** The maximum number of retries after matching an invalid number. */ + private long maxTries; + + /** The iteration tristate. */ + private State state = State.NOT_READY; + /** The last successful match, null unless in {@link State#READY}. */ + private PhoneNumberMatch lastMatch = null; + /** The next index to start searching at. Undefined in {@link State#DONE}. */ + private int searchIndex = 0; + + // A cache for frequently used country-specific regular expressions. Set to 32 to cover ~2-3 + // countries being used for the same doc with ~10 patterns for each country. Some pages will have + // a lot more countries in use, but typically fewer numbers for each so expanding the cache for + // that use-case won't have a lot of benefit. + private final RegexCache regexCache = new RegexCache(32); + + /** + * Creates a new instance. See the factory methods in {@link PhoneNumberUtil} on how to obtain a + * new instance. + * + * @param util the phone number util to use + * @param text the character sequence that we will search, null for no text + * @param country the country to assume for phone numbers not written in international format + * (with a leading plus, or with the international dialing prefix of the specified region). + * May be null or "ZZ" if only numbers with a leading plus should be + * considered. + * @param leniency the leniency to use when evaluating candidate phone numbers + * @param maxTries the maximum number of invalid numbers to try before giving up on the text. + * This is to cover degenerate cases where the text has a lot of false positives in it. Must + * be {@code >= 0}. + */ + PhoneNumberMatcher(PhoneNumberUtil util, CharSequence text, String country, Leniency leniency, + long maxTries) { + + if ((util == null) || (leniency == null)) { + throw new NullPointerException(); + } + if (maxTries < 0) { + throw new IllegalArgumentException(); + } + this.phoneUtil = util; + this.text = (text != null) ? text : ""; + this.preferredRegion = country; + this.leniency = leniency; + this.maxTries = maxTries; + } + + /** + * Attempts to find the next subsequence in the searched sequence on or after {@code searchIndex} + * that represents a phone number. Returns the next match, null if none was found. + * + * @param index the search index to start searching at + * @return the phone number match found, null if none can be found + */ + private PhoneNumberMatch find(int index) { + Matcher matcher = PATTERN.matcher(text); + while ((maxTries > 0) && matcher.find(index)) { + int start = matcher.start(); + CharSequence candidate = text.subSequence(start, matcher.end()); + + // Check for extra numbers at the end. + // TODO: This is the place to start when trying to support extraction of multiple phone number + // from split notations (+41 79 123 45 67 / 68). + candidate = trimAfterFirstMatch(PhoneNumberUtil.SECOND_NUMBER_START_PATTERN, candidate); + + PhoneNumberMatch match = extractMatch(candidate, start); + if (match != null) { + return match; + } + + index = start + candidate.length(); + maxTries--; + } + + return null; + } + + /** + * Trims away any characters after the first match of {@code pattern} in {@code candidate}, + * returning the trimmed version. + */ + private static CharSequence trimAfterFirstMatch(Pattern pattern, CharSequence candidate) { + Matcher trailingCharsMatcher = pattern.matcher(candidate); + if (trailingCharsMatcher.find()) { + candidate = candidate.subSequence(0, trailingCharsMatcher.start()); + } + return candidate; + } + + /** + * Helper method to determine if a character is a Latin-script letter or not. For our purposes, + * combining marks should also return true since we assume they have been added to a preceding + * Latin character. + */ + // @VisibleForTesting + static boolean isLatinLetter(char letter) { + // Combining marks are a subset of non-spacing-mark. + if (!Character.isLetter(letter) && Character.getType(letter) != Character.NON_SPACING_MARK) { + return false; + } + UnicodeBlock block = UnicodeBlock.of(letter); + return block.equals(UnicodeBlock.BASIC_LATIN) + || block.equals(UnicodeBlock.LATIN_1_SUPPLEMENT) + || block.equals(UnicodeBlock.LATIN_EXTENDED_A) + || block.equals(UnicodeBlock.LATIN_EXTENDED_ADDITIONAL) + || block.equals(UnicodeBlock.LATIN_EXTENDED_B) + || block.equals(UnicodeBlock.COMBINING_DIACRITICAL_MARKS); + } + + private static boolean isInvalidPunctuationSymbol(char character) { + return character == '%' || Character.getType(character) == Character.CURRENCY_SYMBOL; + } + + /** + * Attempts to extract a match from a {@code candidate} character sequence. + * + * @param candidate the candidate text that might contain a phone number + * @param offset the offset of {@code candidate} within {@link #text} + * @return the match found, null if none can be found + */ + private PhoneNumberMatch extractMatch(CharSequence candidate, int offset) { + // Skip a match that is more likely to be a date. + if (SLASH_SEPARATED_DATES.matcher(candidate).find()) { + return null; + } + + // Skip potential time-stamps. + if (TIME_STAMPS.matcher(candidate).find()) { + String followingText = text.toString().substring(offset + candidate.length()); + if (TIME_STAMPS_SUFFIX.matcher(followingText).lookingAt()) { + return null; + } + } + + // Try to come up with a valid match given the entire candidate. + PhoneNumberMatch match = parseAndVerify(candidate, offset); + if (match != null) { + return match; + } + + // If that failed, try to find an "inner match" - there might be a phone number within this + // candidate. + return extractInnerMatch(candidate, offset); + } + + /** + * Attempts to extract a match from {@code candidate} if the whole candidate does not qualify as a + * match. + * + * @param candidate the candidate text that might contain a phone number + * @param offset the current offset of {@code candidate} within {@link #text} + * @return the match found, null if none can be found + */ + private PhoneNumberMatch extractInnerMatch(CharSequence candidate, int offset) { + for (Pattern possibleInnerMatch : INNER_MATCHES) { + Matcher groupMatcher = possibleInnerMatch.matcher(candidate); + boolean isFirstMatch = true; + while (groupMatcher.find() && maxTries > 0) { + if (isFirstMatch) { + // We should handle any group before this one too. + CharSequence group = trimAfterFirstMatch( + PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, + candidate.subSequence(0, groupMatcher.start())); + PhoneNumberMatch match = parseAndVerify(group, offset); + if (match != null) { + return match; + } + maxTries--; + isFirstMatch = false; + } + CharSequence group = trimAfterFirstMatch( + PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN, groupMatcher.group(1)); + PhoneNumberMatch match = parseAndVerify(group, offset + groupMatcher.start(1)); + if (match != null) { + return match; + } + maxTries--; + } + } + return null; + } + + /** + * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and + * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a + * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null. + * + * @param candidate the candidate match + * @param offset the offset of {@code candidate} within {@link #text} + * @return the parsed and validated phone number match, or null + */ + private PhoneNumberMatch parseAndVerify(CharSequence candidate, int offset) { + try { + // Check the candidate doesn't contain any formatting which would indicate that it really + // isn't a phone number. + if (!MATCHING_BRACKETS.matcher(candidate).matches() || PUB_PAGES.matcher(candidate).find()) { + return null; + } + + // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded + // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def. + if (leniency.compareTo(Leniency.VALID) >= 0) { + // If the candidate is not at the start of the text, and does not start with phone-number + // punctuation, check the previous character. + if (offset > 0 && !LEAD_CLASS.matcher(candidate).lookingAt()) { + char previousChar = text.charAt(offset - 1); + // We return null if it is a latin letter or an invalid punctuation symbol. + if (isInvalidPunctuationSymbol(previousChar) || isLatinLetter(previousChar)) { + return null; + } + } + int lastCharIndex = offset + candidate.length(); + if (lastCharIndex < text.length()) { + char nextChar = text.charAt(lastCharIndex); + if (isInvalidPunctuationSymbol(nextChar) || isLatinLetter(nextChar)) { + return null; + } + } + } + + PhoneNumber number = phoneUtil.parseAndKeepRawInput(candidate, preferredRegion); + + if (leniency.verify(number, candidate, phoneUtil, this)) { + // We used parseAndKeepRawInput to create this number, but for now we don't return the extra + // values parsed. TODO: stop clearing all values here and switch all users over + // to using rawInput() rather than the rawString() of PhoneNumberMatch. + number.clearCountryCodeSource(); + number.clearRawInput(); + number.clearPreferredDomesticCarrierCode(); + return new PhoneNumberMatch(offset, candidate.toString(), number); + } + } catch (NumberParseException e) { + // ignore and continue + } + return null; + } + + /** + * Small helper interface such that the number groups can be checked according to different + * criteria, both for our default way of performing formatting and for any alternate formats we + * may want to check. + */ + interface NumberGroupingChecker { + /** + * Returns true if the groups of digits found in our candidate phone number match our + * expectations. + * + * @param number the original number we found when parsing + * @param normalizedCandidate the candidate number, normalized to only contain ASCII digits, + * but with non-digits (spaces etc) retained + * @param expectedNumberGroups the groups of digits that we would expect to see if we + * formatted this number + */ + boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, String[] expectedNumberGroups); + } + + static boolean allNumberGroupsRemainGrouped(PhoneNumberUtil util, + PhoneNumber number, + StringBuilder normalizedCandidate, + String[] formattedNumberGroups) { + int fromIndex = 0; + if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + // First skip the country code if the normalized candidate contained it. + String countryCode = Integer.toString(number.getCountryCode()); + fromIndex = normalizedCandidate.indexOf(countryCode) + countryCode.length(); + } + // Check each group of consecutive digits are not broken into separate groupings in the + // {@code normalizedCandidate} string. + for (int i = 0; i < formattedNumberGroups.length; i++) { + // Fails if the substring of {@code normalizedCandidate} starting from {@code fromIndex} + // doesn't contain the consecutive digits in formattedNumberGroups[i]. + fromIndex = normalizedCandidate.indexOf(formattedNumberGroups[i], fromIndex); + if (fromIndex < 0) { + return false; + } + // Moves {@code fromIndex} forward. + fromIndex += formattedNumberGroups[i].length(); + if (i == 0 && fromIndex < normalizedCandidate.length()) { + // We are at the position right after the NDC. We get the region used for formatting + // information based on the country code in the phone number, rather than the number itself, + // as we do not need to distinguish between different countries with the same country + // calling code and this is faster. + String region = util.getRegionCodeForCountryCode(number.getCountryCode()); + if (util.getNddPrefixForRegion(region, true) != null + && Character.isDigit(normalizedCandidate.charAt(fromIndex))) { + // This means there is no formatting symbol after the NDC. In this case, we only + // accept the number if there is no formatting symbol at all in the number, except + // for extensions. This is only important for countries with national prefixes. + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + return normalizedCandidate.substring(fromIndex - formattedNumberGroups[i].length()) + .startsWith(nationalSignificantNumber); + } + } + } + // The check here makes sure that we haven't mistakenly already used the extension to + // match the last group of the subscriber number. Note the extension cannot have + // formatting in-between digits. + return normalizedCandidate.substring(fromIndex).contains(number.getExtension()); + } + + static boolean allNumberGroupsAreExactlyPresent(PhoneNumberUtil util, + PhoneNumber number, + StringBuilder normalizedCandidate, + String[] formattedNumberGroups) { + String[] candidateGroups = + PhoneNumberUtil.NON_DIGITS_PATTERN.split(normalizedCandidate.toString()); + // Set this to the last group, skipping it if the number has an extension. + int candidateNumberGroupIndex = + number.hasExtension() ? candidateGroups.length - 2 : candidateGroups.length - 1; + // First we check if the national significant number is formatted as a block. + // We use contains and not equals, since the national significant number may be present with + // a prefix such as a national number prefix, or the country code itself. + if (candidateGroups.length == 1 + || candidateGroups[candidateNumberGroupIndex].contains( + util.getNationalSignificantNumber(number))) { + return true; + } + // Starting from the end, go through in reverse, excluding the first group, and check the + // candidate and number groups are the same. + for (int formattedNumberGroupIndex = (formattedNumberGroups.length - 1); + formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0; + formattedNumberGroupIndex--, candidateNumberGroupIndex--) { + if (!candidateGroups[candidateNumberGroupIndex].equals( + formattedNumberGroups[formattedNumberGroupIndex])) { + return false; + } + } + // Now check the first group. There may be a national prefix at the start, so we only check + // that the candidate group ends with the formatted number group. + return (candidateNumberGroupIndex >= 0 + && candidateGroups[candidateNumberGroupIndex].endsWith(formattedNumberGroups[0])); + } + + /** + * Helper method to get the national-number part of a number, formatted without any national + * prefix, and return it as a set of digit blocks that would be formatted together following + * standard formatting rules. + */ + private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number) { + // This will be in the format +CC-DG1-DG2-DGX;ext=EXT where DG1..DGX represents groups of + // digits. + String rfc3966Format = util.format(number, PhoneNumberFormat.RFC3966); + // We remove the extension part from the formatted string before splitting it into different + // groups. + int endIndex = rfc3966Format.indexOf(';'); + if (endIndex < 0) { + endIndex = rfc3966Format.length(); + } + // The country-code will have a '-' following it. + int startIndex = rfc3966Format.indexOf('-') + 1; + return rfc3966Format.substring(startIndex, endIndex).split("-"); + } + + /** + * Helper method to get the national-number part of a number, formatted without any national + * prefix, and return it as a set of digit blocks that should be formatted together according to + * the formatting pattern passed in. + */ + private static String[] getNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number, + NumberFormat formattingPattern) { + // If a format is provided, we format the NSN only, and split that according to the separator. + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + return util.formatNsnUsingPattern(nationalSignificantNumber, + formattingPattern, PhoneNumberFormat.RFC3966).split("-"); + } + + boolean checkNumberGroupingIsValid( + PhoneNumber number, CharSequence candidate, PhoneNumberUtil util, + NumberGroupingChecker checker) { + StringBuilder normalizedCandidate = + PhoneNumberUtil.normalizeDigits(candidate, true /* keep non-digits */); + String[] formattedNumberGroups = getNationalNumberGroups(util, number); + if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { + return true; + } + // If this didn't pass, see if there are any alternate formats that match, and try them instead. + PhoneMetadata alternateFormats = + DefaultMetadataDependenciesProvider.getInstance() + .getAlternateFormatsMetadataSource() + .getFormattingMetadataForCountryCallingCode(number.getCountryCode()); + String nationalSignificantNumber = util.getNationalSignificantNumber(number); + if (alternateFormats != null) { + for (NumberFormat alternateFormat : alternateFormats.getNumberFormatList()) { + if (alternateFormat.getLeadingDigitsPatternCount() > 0) { + // There is only one leading digits pattern for alternate formats. + Pattern pattern = + regexCache.getPatternForRegex(alternateFormat.getLeadingDigitsPattern(0)); + if (!pattern.matcher(nationalSignificantNumber).lookingAt()) { + // Leading digits don't match; try another one. + continue; + } + } + formattedNumberGroups = getNationalNumberGroups(util, number, alternateFormat); + if (checker.checkGroups(util, number, normalizedCandidate, formattedNumberGroups)) { + return true; + } + } + } + return false; + } + + static boolean containsMoreThanOneSlashInNationalNumber(PhoneNumber number, String candidate) { + int firstSlashInBodyIndex = candidate.indexOf('/'); + if (firstSlashInBodyIndex < 0) { + // No slashes, this is okay. + return false; + } + // Now look for a second one. + int secondSlashInBodyIndex = candidate.indexOf('/', firstSlashInBodyIndex + 1); + if (secondSlashInBodyIndex < 0) { + // Only one slash, this is okay. + return false; + } + + // If the first slash is after the country calling code, this is permitted. + boolean candidateHasCountryCode = + (number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN + || number.getCountryCodeSource() == CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); + if (candidateHasCountryCode + && PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(0, firstSlashInBodyIndex)) + .equals(Integer.toString(number.getCountryCode()))) { + // Any more slashes and this is illegal. + return candidate.substring(secondSlashInBodyIndex + 1).contains("/"); + } + return true; + } + + static boolean containsOnlyValidXChars( + PhoneNumber number, String candidate, PhoneNumberUtil util) { + // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the + // national significant number or (2) an extension sign, in which case they always precede the + // extension number. We assume a carrier code is more than 1 digit, so the first case has to + // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x' + // or 'X'. We ignore the character if it appears as the last character of the string. + for (int index = 0; index < candidate.length() - 1; index++) { + char charAtIndex = candidate.charAt(index); + if (charAtIndex == 'x' || charAtIndex == 'X') { + char charAtNextIndex = candidate.charAt(index + 1); + if (charAtNextIndex == 'x' || charAtNextIndex == 'X') { + // This is the carrier code case, in which the 'X's always precede the national + // significant number. + index++; + if (util.isNumberMatch(number, candidate.substring(index)) != MatchType.NSN_MATCH) { + return false; + } + // This is the extension sign case, in which the 'x' or 'X' should always precede the + // extension number. + } else if (!PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(index)).equals( + number.getExtension())) { + return false; + } + } + } + return true; + } + + static boolean isNationalPrefixPresentIfRequired(PhoneNumber number, PhoneNumberUtil util) { + // First, check how we deduced the country code. If it was written in international format, then + // the national prefix is not required. + if (number.getCountryCodeSource() != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + return true; + } + String phoneNumberRegion = + util.getRegionCodeForCountryCode(number.getCountryCode()); + PhoneMetadata metadata = util.getMetadataForRegion(phoneNumberRegion); + if (metadata == null) { + return true; + } + // Check if a national prefix should be present when formatting this number. + String nationalNumber = util.getNationalSignificantNumber(number); + NumberFormat formatRule = + util.chooseFormattingPatternForNumber(metadata.getNumberFormatList(), nationalNumber); + // To do this, we check that a national prefix formatting rule was present and that it wasn't + // just the first-group symbol ($1) with punctuation. + if ((formatRule != null) && formatRule.getNationalPrefixFormattingRule().length() > 0) { + if (formatRule.getNationalPrefixOptionalWhenFormatting()) { + // The national-prefix is optional in these cases, so we don't need to check if it was + // present. + return true; + } + if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly( + formatRule.getNationalPrefixFormattingRule())) { + // National Prefix not needed for this number. + return true; + } + // Normalize the remainder. + String rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput()); + StringBuilder rawInput = new StringBuilder(rawInputCopy); + // Check if we found a national prefix and/or carrier code at the start of the raw input, and + // return the result. + return util.maybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null); + } + return true; + } + + @Override + public boolean hasNext() { + if (state == State.NOT_READY) { + lastMatch = find(searchIndex); + if (lastMatch == null) { + state = State.DONE; + } else { + searchIndex = lastMatch.end(); + state = State.READY; + } + } + return state == State.READY; + } + + @Override + public PhoneNumberMatch next() { + // Check the state and find the next match as a side-effect if necessary. + if (!hasNext()) { + throw new NoSuchElementException(); + } + + // Don't retain that memory any longer than necessary. + PhoneNumberMatch result = lastMatch; + lastMatch = null; + state = State.NOT_READY; + return result; + } + + /** + * Always throws {@link UnsupportedOperationException} as removal is not supported. + */ + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java new file mode 100644 index 0000000000..fd8f1a3067 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -0,0 +1,3683 @@ +/* + * Copyright (C) 2009 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; +import com.google.i18n.phonenumbers.internal.MatcherApi; +import com.google.i18n.phonenumbers.internal.RegexBasedMatcher; +import com.google.i18n.phonenumbers.internal.RegexCache; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.MetadataSource; +import com.google.i18n.phonenumbers.metadata.source.MetadataSourceImpl; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility for international phone numbers. Functionality includes formatting, parsing and + * validation. + * + *

If you use this library, and want to be notified about important changes, please sign up to + * our mailing list. + * + * NOTE: A lot of methods in this class require Region Code strings. These must be provided using + * CLDR two-letter region-code format. These should be in upper-case. The list of the codes + * can be found here: + * http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html + */ +public class PhoneNumberUtil { + private static final Logger logger = Logger.getLogger(PhoneNumberUtil.class.getName()); + + /** Flags to use when compiling regular expressions for phone numbers. */ + static final int REGEX_FLAGS = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; + // The minimum and maximum length of the national significant number. + private static final int MIN_LENGTH_FOR_NSN = 2; + // The ITU says the maximum length should be 15, but we have found longer numbers in Germany. + static final int MAX_LENGTH_FOR_NSN = 17; + // The maximum length of the country calling code. + static final int MAX_LENGTH_COUNTRY_CODE = 3; + // We don't allow input strings for parsing to be longer than 250 chars. This prevents malicious + // input from overflowing the regular-expression engine. + private static final int MAX_INPUT_STRING_LENGTH = 250; + + // Region-code for the unknown region. + private static final String UNKNOWN_REGION = "ZZ"; + + private static final int NANPA_COUNTRY_CODE = 1; + + // Map of country calling codes that use a mobile token before the area code. One example of when + // this is relevant is when determining the length of the national destination code, which should + // be the length of the area code plus the length of the mobile token. + private static final Map MOBILE_TOKEN_MAPPINGS; + + // Set of country codes that have geographically assigned mobile numbers (see GEO_MOBILE_COUNTRIES + // below) which are not based on *area codes*. For example, in China mobile numbers start with a + // carrier indicator, and beyond that are geographically assigned: this carrier indicator is not + // considered to be an area code. + private static final Set GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES; + + // Set of country codes that doesn't have national prefix, but it has area codes. + private static final Set COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES; + + // Set of country calling codes that have geographically assigned mobile numbers. This may not be + // complete; we add calling codes case by case, as we find geographical mobile numbers or hear + // from user reports. Note that countries like the US, where we can't distinguish between + // fixed-line or mobile numbers, are not listed here, since we consider FIXED_LINE_OR_MOBILE to be + // a possibly geographically-related type anyway (like FIXED_LINE). + private static final Set GEO_MOBILE_COUNTRIES; + + // The PLUS_SIGN signifies the international prefix. + static final char PLUS_SIGN = '+'; + + private static final char STAR_SIGN = '*'; + + private static final String RFC3966_EXTN_PREFIX = ";ext="; + private static final String RFC3966_PREFIX = "tel:"; + private static final String RFC3966_PHONE_CONTEXT = ";phone-context="; + private static final String RFC3966_ISDN_SUBADDRESS = ";isub="; + + // A map that contains characters that are essential when dialling. That means any of the + // characters in this map must not be removed from a number when dialling, otherwise the call + // will not reach the intended destination. + private static final Map DIALLABLE_CHAR_MAPPINGS; + + // Only upper-case variants of alpha characters are stored. + private static final Map ALPHA_MAPPINGS; + + // For performance reasons, amalgamate both into one map. + private static final Map ALPHA_PHONE_MAPPINGS; + + // Separate map of all symbols that we wish to retain when formatting alpha numbers. This + // includes digits, ASCII letters and number grouping symbols such as "-" and " ". + private static final Map ALL_PLUS_NUMBER_GROUPING_SYMBOLS; + + static { + HashMap mobileTokenMap = new HashMap<>(); + mobileTokenMap.put(54, "9"); + MOBILE_TOKEN_MAPPINGS = Collections.unmodifiableMap(mobileTokenMap); + + HashSet geoMobileCountriesWithoutMobileAreaCodes = new HashSet<>(); + geoMobileCountriesWithoutMobileAreaCodes.add(86); // China + GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES = + Collections.unmodifiableSet(geoMobileCountriesWithoutMobileAreaCodes); + + HashSet countriesWithoutNationalPrefixWithAreaCodes = new HashSet<>(); + countriesWithoutNationalPrefixWithAreaCodes.add(52); // Mexico + COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES = + Collections.unmodifiableSet(countriesWithoutNationalPrefixWithAreaCodes); + + HashSet geoMobileCountries = new HashSet<>(); + geoMobileCountries.add(52); // Mexico + geoMobileCountries.add(54); // Argentina + geoMobileCountries.add(55); // Brazil + geoMobileCountries.add(62); // Indonesia: some prefixes only (fixed CMDA wireless) + geoMobileCountries.addAll(geoMobileCountriesWithoutMobileAreaCodes); + GEO_MOBILE_COUNTRIES = Collections.unmodifiableSet(geoMobileCountries); + + // Simple ASCII digits map used to populate ALPHA_PHONE_MAPPINGS and + // ALL_PLUS_NUMBER_GROUPING_SYMBOLS. + HashMap asciiDigitMappings = new HashMap<>(); + asciiDigitMappings.put('0', '0'); + asciiDigitMappings.put('1', '1'); + asciiDigitMappings.put('2', '2'); + asciiDigitMappings.put('3', '3'); + asciiDigitMappings.put('4', '4'); + asciiDigitMappings.put('5', '5'); + asciiDigitMappings.put('6', '6'); + asciiDigitMappings.put('7', '7'); + asciiDigitMappings.put('8', '8'); + asciiDigitMappings.put('9', '9'); + + HashMap alphaMap = new HashMap<>(40); + alphaMap.put('A', '2'); + alphaMap.put('B', '2'); + alphaMap.put('C', '2'); + alphaMap.put('D', '3'); + alphaMap.put('E', '3'); + alphaMap.put('F', '3'); + alphaMap.put('G', '4'); + alphaMap.put('H', '4'); + alphaMap.put('I', '4'); + alphaMap.put('J', '5'); + alphaMap.put('K', '5'); + alphaMap.put('L', '5'); + alphaMap.put('M', '6'); + alphaMap.put('N', '6'); + alphaMap.put('O', '6'); + alphaMap.put('P', '7'); + alphaMap.put('Q', '7'); + alphaMap.put('R', '7'); + alphaMap.put('S', '7'); + alphaMap.put('T', '8'); + alphaMap.put('U', '8'); + alphaMap.put('V', '8'); + alphaMap.put('W', '9'); + alphaMap.put('X', '9'); + alphaMap.put('Y', '9'); + alphaMap.put('Z', '9'); + ALPHA_MAPPINGS = Collections.unmodifiableMap(alphaMap); + + HashMap combinedMap = new HashMap<>(100); + combinedMap.putAll(ALPHA_MAPPINGS); + combinedMap.putAll(asciiDigitMappings); + ALPHA_PHONE_MAPPINGS = Collections.unmodifiableMap(combinedMap); + + HashMap diallableCharMap = new HashMap<>(); + diallableCharMap.putAll(asciiDigitMappings); + diallableCharMap.put(PLUS_SIGN, PLUS_SIGN); + diallableCharMap.put('*', '*'); + diallableCharMap.put('#', '#'); + DIALLABLE_CHAR_MAPPINGS = Collections.unmodifiableMap(diallableCharMap); + + HashMap allPlusNumberGroupings = new HashMap<>(); + // Put (lower letter -> upper letter) and (upper letter -> upper letter) mappings. + for (char c : ALPHA_MAPPINGS.keySet()) { + allPlusNumberGroupings.put(Character.toLowerCase(c), c); + allPlusNumberGroupings.put(c, c); + } + allPlusNumberGroupings.putAll(asciiDigitMappings); + // Put grouping symbols. + allPlusNumberGroupings.put('-', '-'); + allPlusNumberGroupings.put('\uFF0D', '-'); + allPlusNumberGroupings.put('\u2010', '-'); + allPlusNumberGroupings.put('\u2011', '-'); + allPlusNumberGroupings.put('\u2012', '-'); + allPlusNumberGroupings.put('\u2013', '-'); + allPlusNumberGroupings.put('\u2014', '-'); + allPlusNumberGroupings.put('\u2015', '-'); + allPlusNumberGroupings.put('\u2212', '-'); + allPlusNumberGroupings.put('/', '/'); + allPlusNumberGroupings.put('\uFF0F', '/'); + allPlusNumberGroupings.put(' ', ' '); + allPlusNumberGroupings.put('\u3000', ' '); + allPlusNumberGroupings.put('\u2060', ' '); + allPlusNumberGroupings.put('.', '.'); + allPlusNumberGroupings.put('\uFF0E', '.'); + ALL_PLUS_NUMBER_GROUPING_SYMBOLS = Collections.unmodifiableMap(allPlusNumberGroupings); + } + + // Pattern that makes it easy to distinguish whether a region has a single international dialing + // prefix or not. If a region has a single international prefix (e.g. 011 in USA), it will be + // represented as a string that contains a sequence of ASCII digits, and possibly a tilde, which + // signals waiting for the tone. If there are multiple available international prefixes in a + // region, they will be represented as a regex string that always contains one or more characters + // that are not ASCII digits or a tilde. + private static final Pattern SINGLE_INTERNATIONAL_PREFIX = + Pattern.compile("[\\d]+(?:[~\u2053\u223C\uFF5E][\\d]+)?"); + + // Regular expression of acceptable punctuation found in phone numbers, used to find numbers in + // text and to decide what is a viable phone number. This excludes diallable characters. + // This consists of dash characters, white space characters, full stops, slashes, + // square brackets, parentheses and tildes. It also includes the letter 'x' as that is found as a + // placeholder for carrier information in some phone numbers. Full-width variants are also + // present. + static final String VALID_PUNCTUATION = "-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F " + + "\u00A0\u00AD\u200B\u2060\u3000()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E"; + + private static final String DIGITS = "\\p{Nd}"; + // We accept alpha characters in phone numbers, ASCII only, upper and lower case. + private static final String VALID_ALPHA = + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()).replaceAll("[, \\[\\]]", "") + + Arrays.toString(ALPHA_MAPPINGS.keySet().toArray()) + .toLowerCase().replaceAll("[, \\[\\]]", ""); + static final String PLUS_CHARS = "+\uFF0B"; + static final Pattern PLUS_CHARS_PATTERN = Pattern.compile("[" + PLUS_CHARS + "]+"); + private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[" + VALID_PUNCTUATION + "]+"); + private static final Pattern CAPTURING_DIGIT_PATTERN = Pattern.compile("(" + DIGITS + ")"); + + // Regular expression of acceptable characters that may start a phone number for the purposes of + // parsing. This allows us to strip away meaningless prefixes to phone numbers that may be + // mistakenly given to us. This consists of digits, the plus symbol and arabic-indic digits. This + // does not contain alpha characters, although they may be used later in the number. It also does + // not include other punctuation, as this will be stripped later during parsing and is of no + // information value when parsing a number. + private static final String VALID_START_CHAR = "[" + PLUS_CHARS + DIGITS + "]"; + private static final Pattern VALID_START_CHAR_PATTERN = Pattern.compile(VALID_START_CHAR); + + // Regular expression of characters typically used to start a second phone number for the purposes + // of parsing. This allows us to strip off parts of the number that are actually the start of + // another number, such as for: (530) 583-6985 x302/x2303 -> the second extension here makes this + // actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second + // extension so that the first number is parsed correctly. + private static final String SECOND_NUMBER_START = "[\\\\/] *x"; + static final Pattern SECOND_NUMBER_START_PATTERN = Pattern.compile(SECOND_NUMBER_START); + + // Regular expression of trailing characters that we want to remove. We remove all characters that + // are not alpha or numerical characters. The hash character is retained here, as it may signify + // the previous block was an extension. + private static final String UNWANTED_END_CHARS = "[[\\P{N}&&\\P{L}]&&[^#]]+$"; + static final Pattern UNWANTED_END_CHAR_PATTERN = Pattern.compile(UNWANTED_END_CHARS); + + // We use this pattern to check if the phone number has at least three letters in it - if so, then + // we treat it as a number where some phone-number digits are represented by letters. + private static final Pattern VALID_ALPHA_PHONE_PATTERN = Pattern.compile("(?:.*?[A-Za-z]){3}.*"); + + // Regular expression of viable phone numbers. This is location independent. Checks we have at + // least three leading digits, and only valid punctuation, alpha characters and + // digits in the phone number. Does not include extension data. + // The symbol 'x' is allowed here as valid punctuation since it is often used as a placeholder for + // carrier codes, for example in Brazilian phone numbers. We also allow multiple "+" characters at + // the start. + // Corresponds to the following: + // [digits]{minLengthNsn}| + // plus_sign*(([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])* + // + // The first reg-ex is to allow short numbers (two digits long) to be parsed if they are entered + // as "15" etc, but only if there is no punctuation in them. The second expression restricts the + // number of digits to three or more, but then allows them to be in international form, and to + // have alpha-characters and punctuation. + // + // Note VALID_PUNCTUATION starts with a -, so must be the first in the range. + private static final String VALID_PHONE_NUMBER = + DIGITS + "{" + MIN_LENGTH_FOR_NSN + "}" + "|" + + "[" + PLUS_CHARS + "]*+(?:[" + VALID_PUNCTUATION + STAR_SIGN + "]*" + DIGITS + "){3,}[" + + VALID_PUNCTUATION + STAR_SIGN + VALID_ALPHA + DIGITS + "]*"; + + // Default extension prefix to use when formatting. This will be put in front of any extension + // component of the number, after the main national number is formatted. For example, if you wish + // the default extension formatting to be " extn: 3456", then you should specify " extn: " here + // as the default extension prefix. This can be overridden by region-specific preferences. + private static final String DEFAULT_EXTN_PREFIX = " ext. "; + + // Regexp of all possible ways to write extensions, for use when parsing. This will be run as a + // case-insensitive regexp match. Wide character versions are also provided after each ASCII + // version. + private static final String EXTN_PATTERNS_FOR_PARSING = createExtnPattern(true); + static final String EXTN_PATTERNS_FOR_MATCHING = createExtnPattern(false); + + // Regular expression of valid global-number-digits for the phone-context parameter, following the + // syntax defined in RFC3966. + private static final String RFC3966_VISUAL_SEPARATOR = "[\\-\\.\\(\\)]?"; + private static final String RFC3966_PHONE_DIGIT = + "(" + DIGITS + "|" + RFC3966_VISUAL_SEPARATOR + ")"; + private static final String RFC3966_GLOBAL_NUMBER_DIGITS = + "^\\" + PLUS_SIGN + RFC3966_PHONE_DIGIT + "*" + DIGITS + RFC3966_PHONE_DIGIT + "*$"; + static final Pattern RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN = + Pattern.compile(RFC3966_GLOBAL_NUMBER_DIGITS); + + // Regular expression of valid domainname for the phone-context parameter, following the syntax + // defined in RFC3966. + private static final String ALPHANUM = VALID_ALPHA + DIGITS; + private static final String RFC3966_DOMAINLABEL = + "[" + ALPHANUM + "]+((\\-)*[" + ALPHANUM + "])*"; + private static final String RFC3966_TOPLABEL = + "[" + VALID_ALPHA + "]+((\\-)*[" + ALPHANUM + "])*"; + private static final String RFC3966_DOMAINNAME = + "^(" + RFC3966_DOMAINLABEL + "\\.)*" + RFC3966_TOPLABEL + "\\.?$"; + static final Pattern RFC3966_DOMAINNAME_PATTERN = Pattern.compile(RFC3966_DOMAINNAME); + + /** + * Helper method for constructing regular expressions for parsing. Creates an expression that + * captures up to maxLength digits. + */ + private static String extnDigits(int maxLength) { + return "(" + DIGITS + "{1," + maxLength + "})"; + } + + /** + * Helper initialiser method to create the regular-expression pattern to match extensions. + * Note that there are currently six capturing groups for the extension itself. If this number is + * changed, MaybeStripExtension needs to be updated. + */ + private static String createExtnPattern(boolean forParsing) { + // We cap the maximum length of an extension based on the ambiguity of the way the extension is + // prefixed. As per ITU, the officially allowed length for extensions is actually 40, but we + // don't support this since we haven't seen real examples and this introduces many false + // interpretations as the extension labels are not standardized. + int extLimitAfterExplicitLabel = 20; + int extLimitAfterLikelyLabel = 15; + int extLimitAfterAmbiguousChar = 9; + int extLimitWhenNotSure = 6; + + String possibleSeparatorsBetweenNumberAndExtLabel = "[ \u00A0\\t,]*"; + // Optional full stop (.) or colon, followed by zero or more spaces/tabs/commas. + String possibleCharsAfterExtLabel = "[:\\.\uFF0E]?[ \u00A0\\t,-]*"; + String optionalExtnSuffix = "#?"; + + // Here the extension is called out in more explicit way, i.e mentioning it obvious patterns + // like "ext.". Canonical-equivalence doesn't seem to be an option with Android java, so we + // allow two options for representing the accented o - the character itself, and one in the + // unicode decomposed form with the combining acute accent. + String explicitExtLabels = + "(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|\u0434\u043E\u0431|anexo)"; + // One-character symbols that can be used to indicate an extension, and less commonly used + // or more ambiguous extension labels. + String ambiguousExtLabels = "(?:[x\uFF58#\uFF03~\uFF5E]|int|\uFF49\uFF4E\uFF54)"; + // When extension is not separated clearly. + String ambiguousSeparator = "[- ]+"; + + String rfcExtn = RFC3966_EXTN_PREFIX + extnDigits(extLimitAfterExplicitLabel); + String explicitExtn = possibleSeparatorsBetweenNumberAndExtLabel + explicitExtLabels + + possibleCharsAfterExtLabel + extnDigits(extLimitAfterExplicitLabel) + + optionalExtnSuffix; + String ambiguousExtn = possibleSeparatorsBetweenNumberAndExtLabel + ambiguousExtLabels + + possibleCharsAfterExtLabel + extnDigits(extLimitAfterAmbiguousChar) + optionalExtnSuffix; + String americanStyleExtnWithSuffix = ambiguousSeparator + extnDigits(extLimitWhenNotSure) + "#"; + + // The first regular expression covers RFC 3966 format, where the extension is added using + // ";ext=". The second more generic where extension is mentioned with explicit labels like + // "ext:". In both the above cases we allow more numbers in extension than any other extension + // labels. The third one captures when single character extension labels or less commonly used + // labels are used. In such cases we capture fewer extension digits in order to reduce the + // chance of falsely interpreting two numbers beside each other as a number + extension. The + // fourth one covers the special case of American numbers where the extension is written with a + // hash at the end, such as "- 503#". + String extensionPattern = + rfcExtn + "|" + + explicitExtn + "|" + + ambiguousExtn + "|" + + americanStyleExtnWithSuffix; + // Additional pattern that is supported when parsing extensions, not when matching. + if (forParsing) { + // This is same as possibleSeparatorsBetweenNumberAndExtLabel, but not matching comma as + // extension label may have it. + String possibleSeparatorsNumberExtLabelNoComma = "[ \u00A0\\t]*"; + // ",," is commonly used for auto dialling the extension when connected. First comma is matched + // through possibleSeparatorsBetweenNumberAndExtLabel, so we do not repeat it here. Semi-colon + // works in Iphone and Android also to pop up a button with the extension number following. + String autoDiallingAndExtLabelsFound = "(?:,{2}|;)"; + + String autoDiallingExtn = possibleSeparatorsNumberExtLabelNoComma + + autoDiallingAndExtLabelsFound + possibleCharsAfterExtLabel + + extnDigits(extLimitAfterLikelyLabel) + optionalExtnSuffix; + String onlyCommasExtn = possibleSeparatorsNumberExtLabelNoComma + + "(?:,)+" + possibleCharsAfterExtLabel + extnDigits(extLimitAfterAmbiguousChar) + + optionalExtnSuffix; + // Here the first pattern is exclusively for extension autodialling formats which are used + // when dialling and in this case we accept longer extensions. However, the second pattern + // is more liberal on the number of commas that acts as extension labels, so we have a strict + // cap on the number of digits in such extensions. + return extensionPattern + "|" + + autoDiallingExtn + "|" + + onlyCommasExtn; + } + return extensionPattern; + } + + // Regexp of all known extension prefixes used by different regions followed by 1 or more valid + // digits, for use when parsing. + private static final Pattern EXTN_PATTERN = + Pattern.compile("(?:" + EXTN_PATTERNS_FOR_PARSING + ")$", REGEX_FLAGS); + + // We append optionally the extension pattern to the end here, as a valid phone number may + // have an extension prefix appended, followed by 1 or more digits. + private static final Pattern VALID_PHONE_NUMBER_PATTERN = + Pattern.compile(VALID_PHONE_NUMBER + "(?:" + EXTN_PATTERNS_FOR_PARSING + ")?", REGEX_FLAGS); + + static final Pattern NON_DIGITS_PATTERN = Pattern.compile("(\\D+)"); + + // The FIRST_GROUP_PATTERN was originally set to $1 but there are some countries for which the + // first group is not used in the national pattern (e.g. Argentina) so the $1 group does not match + // correctly. Therefore, we use \d, so that the first group actually used in the pattern will be + // matched. + private static final Pattern FIRST_GROUP_PATTERN = Pattern.compile("(\\$\\d)"); + // Constants used in the formatting rules to represent the national prefix, first group and + // carrier code respectively. + private static final String NP_STRING = "$NP"; + private static final String FG_STRING = "$FG"; + private static final String CC_STRING = "$CC"; + + // A pattern that is used to determine if the national prefix formatting rule has the first group + // only, i.e., does not start with the national prefix. Note that the pattern explicitly allows + // for unbalanced parentheses. + private static final Pattern FIRST_GROUP_ONLY_PREFIX_PATTERN = Pattern.compile("\\(?\\$1\\)?"); + + private static PhoneNumberUtil instance = null; + + public static final String REGION_CODE_FOR_NON_GEO_ENTITY = "001"; + + /** + * INTERNATIONAL and NATIONAL formats are consistent with the definition in ITU-T Recommendation + * E.123. However we follow local conventions such as using '-' instead of whitespace as + * separators. For example, the number of the Google Switzerland office will be written as + * "+41 44 668 1800" in INTERNATIONAL format, and as "044 668 1800" in NATIONAL format. E164 + * format is as per INTERNATIONAL format but with no formatting applied, e.g. "+41446681800". + * RFC3966 is as per INTERNATIONAL format, but with all spaces and other separating symbols + * replaced with a hyphen, and with any phone number extension appended with ";ext=". It also + * will have a prefix of "tel:" added, e.g. "tel:+41-44-668-1800". + * + * Note: If you are considering storing the number in a neutral format, you are highly advised to + * use the PhoneNumber class. + */ + public enum PhoneNumberFormat { + E164, + INTERNATIONAL, + NATIONAL, + RFC3966 + } + + /** + * Type of phone numbers. + */ + public enum PhoneNumberType { + FIXED_LINE, + MOBILE, + // In some regions (e.g. the USA), it is impossible to distinguish between fixed-line and + // mobile numbers by looking at the phone number itself. + FIXED_LINE_OR_MOBILE, + // Freephone lines + TOLL_FREE, + PREMIUM_RATE, + // The cost of this call is shared between the caller and the recipient, and is hence typically + // less than PREMIUM_RATE calls. See // http://en.wikipedia.org/wiki/Shared_Cost_Service for + // more information. + SHARED_COST, + // Voice over IP numbers. This includes TSoIP (Telephony Service over IP). + VOIP, + // A personal number is associated with a particular person, and may be routed to either a + // MOBILE or FIXED_LINE number. Some more information can be found here: + // http://en.wikipedia.org/wiki/Personal_Numbers + PERSONAL_NUMBER, + PAGER, + // Used for "Universal Access Numbers" or "Company Numbers". They may be further routed to + // specific offices, but allow one number to be used for a company. + UAN, + // Used for "Voice Mail Access Numbers". + VOICEMAIL, + // A phone number is of type UNKNOWN when it does not fit any of the known patterns for a + // specific region. + UNKNOWN + } + + /** + * Types of phone number matches. See detailed description beside the isNumberMatch() method. + */ + public enum MatchType { + NOT_A_NUMBER, + NO_MATCH, + SHORT_NSN_MATCH, + NSN_MATCH, + EXACT_MATCH, + } + + /** + * Possible outcomes when testing if a PhoneNumber is possible. + */ + public enum ValidationResult { + /** The number length matches that of valid numbers for this region. */ + IS_POSSIBLE, + /** + * The number length matches that of local numbers for this region only (i.e. numbers that may + * be able to be dialled within an area, but do not have all the information to be dialled from + * anywhere inside or outside the country). + */ + IS_POSSIBLE_LOCAL_ONLY, + /** The number has an invalid country calling code. */ + INVALID_COUNTRY_CODE, + /** The number is shorter than all valid numbers for this region. */ + TOO_SHORT, + /** + * The number is longer than the shortest valid numbers for this region, shorter than the + * longest valid numbers for this region, and does not itself have a number length that matches + * valid numbers for this region. This can also be returned in the case where + * isPossibleNumberForTypeWithReason was called, and there are no numbers of this type at all + * for this region. + */ + INVALID_LENGTH, + /** The number is longer than all valid numbers for this region. */ + TOO_LONG, + } + + /** + * Leniency when {@linkplain PhoneNumberUtil#findNumbers finding} potential phone numbers in text + * segments. The levels here are ordered in increasing strictness. + */ + public enum Leniency { + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber) + * possible}, but not necessarily {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}. + */ + POSSIBLE { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + return util.isPossibleNumber(number); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isPossibleNumber(PhoneNumber) + * possible} and {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid}. Numbers written + * in national format must have their national-prefix present if it is usually written for a + * number of this type. + */ + VALID { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidate.toString(), util)) { + return false; + } + return PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and + * are grouped in a possible way for this locale. For example, a US number written as + * "65 02 53 00 00" and "650253 0000" are not accepted at this leniency level, whereas + * "650 253 0000", "650 2530000" or "6502530000" are. + * Numbers with more than one '/' symbol in the national significant number are also dropped at + * this level. + *

+ * Warning: This level might result in lower coverage especially for regions outside of country + * code "+1". If you are not sure about which level to use, email the discussion group + * libphonenumber-discuss@googlegroups.com. + */ + STRICT_GROUPING { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + String candidateString = candidate.toString(); + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + return matcher.checkNumberGroupingIsValid( + number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() { + @Override + public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, + String[] expectedNumberGroups) { + return PhoneNumberMatcher.allNumberGroupsRemainGrouped( + util, number, normalizedCandidate, expectedNumberGroups); + } + }); + } + }, + /** + * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and + * are grouped in the same way that we would have formatted it, or as a single block. For + * example, a US number written as "650 2530000" is not accepted at this leniency level, whereas + * "650 253 0000" or "6502530000" are. + * Numbers with more than one '/' symbol are also dropped at this level. + *

+ * Warning: This level might result in lower coverage especially for regions outside of country + * code "+1". If you are not sure about which level to use, email the discussion group + * libphonenumber-discuss@googlegroups.com. + */ + EXACT_GROUPING { + @Override + boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher) { + String candidateString = candidate.toString(); + if (!util.isValidNumber(number) + || !PhoneNumberMatcher.containsOnlyValidXChars(number, candidateString, util) + || PhoneNumberMatcher.containsMoreThanOneSlashInNationalNumber(number, candidateString) + || !PhoneNumberMatcher.isNationalPrefixPresentIfRequired(number, util)) { + return false; + } + return matcher.checkNumberGroupingIsValid( + number, candidate, util, new PhoneNumberMatcher.NumberGroupingChecker() { + @Override + public boolean checkGroups(PhoneNumberUtil util, PhoneNumber number, + StringBuilder normalizedCandidate, + String[] expectedNumberGroups) { + return PhoneNumberMatcher.allNumberGroupsAreExactlyPresent( + util, number, normalizedCandidate, expectedNumberGroups); + } + }); + } + }; + + /** Returns true if {@code number} is a verified number according to this leniency. */ + abstract boolean verify( + PhoneNumber number, + CharSequence candidate, + PhoneNumberUtil util, + PhoneNumberMatcher matcher); + } + + // A source of metadata for different regions. + private final MetadataSource metadataSource; + + // A mapping from a country calling code to the region codes which denote the region represented + // by that country calling code. In the case of multiple regions sharing a calling code, such as + // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be + // first. + private final Map> countryCallingCodeToRegionCodeMap; + + // An API for validation checking. + private final MatcherApi matcherApi = RegexBasedMatcher.create(); + + // The set of regions that share country calling code 1. + // There are roughly 26 regions. + // We set the initial capacity of the HashSet to 35 to offer a load factor of roughly 0.75. + private final Set nanpaRegions = new HashSet<>(35); + + // A cache for frequently used region-specific regular expressions. + // The initial capacity is set to 100 as this seems to be an optimal value for Android, based on + // performance measurements. + private final RegexCache regexCache = new RegexCache(100); + + // The set of regions the library supports. + // There are roughly 240 of them and we set the initial capacity of the HashSet to 320 to offer a + // load factor of roughly 0.75. + private final Set supportedRegions = new HashSet<>(320); + + // The set of country calling codes that map to the non-geo entity region ("001"). This set + // currently contains < 12 elements so the default capacity of 16 (load factor=0.75) is fine. + private final Set countryCodesForNonGeographicalRegion = new HashSet<>(); + + /** + * This class implements a singleton, the constructor is only visible to facilitate testing. + */ + // @VisibleForTesting + PhoneNumberUtil(MetadataSource metadataSource, + Map> countryCallingCodeToRegionCodeMap) { + this.metadataSource = metadataSource; + this.countryCallingCodeToRegionCodeMap = countryCallingCodeToRegionCodeMap; + for (Map.Entry> entry : countryCallingCodeToRegionCodeMap.entrySet()) { + List regionCodes = entry.getValue(); + // We can assume that if the country calling code maps to the non-geo entity region code then + // that's the only region code it maps to. + if (regionCodes.size() == 1 && REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCodes.get(0))) { + // This is the subset of all country codes that map to the non-geo entity region code. + countryCodesForNonGeographicalRegion.add(entry.getKey()); + } else { + // The supported regions set does not include the "001" non-geo entity region code. + supportedRegions.addAll(regionCodes); + } + } + // If the non-geo entity still got added to the set of supported regions it must be because + // there are entries that list the non-geo entity alongside normal regions (which is wrong). + // If we discover this, remove the non-geo entity from the set of supported regions and log. + if (supportedRegions.remove(REGION_CODE_FOR_NON_GEO_ENTITY)) { + logger.log(Level.WARNING, "invalid metadata (country calling code was mapped to the non-geo " + + "entity as well as specific region(s))"); + } + nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE)); + } + + /** + * Attempts to extract a possible number from the string passed in. This currently strips all + * leading characters that cannot be used to start a phone number. Characters that can be used to + * start a phone number are defined in the VALID_START_CHAR_PATTERN. If none of these characters + * are found in the number passed in, an empty string is returned. This function also attempts to + * strip off any alternative extensions or endings if two or more are present, such as in the case + * of: (530) 583-6985 x302/x2303. The second extension here makes this actually two phone numbers, + * (530) 583-6985 x302 and (530) 583-6985 x2303. We remove the second extension so that the first + * number is parsed correctly. + * + * @param number the string that might contain a phone number + * @return the number, stripped of any non-phone-number prefix (such as "Tel:") or an empty + * string if no character used to start phone numbers (such as + or any digit) is found in the + * number + */ + static CharSequence extractPossibleNumber(CharSequence number) { + Matcher m = VALID_START_CHAR_PATTERN.matcher(number); + if (m.find()) { + number = number.subSequence(m.start(), number.length()); + // Remove trailing non-alpha non-numerical characters. + Matcher trailingCharsMatcher = UNWANTED_END_CHAR_PATTERN.matcher(number); + if (trailingCharsMatcher.find()) { + number = number.subSequence(0, trailingCharsMatcher.start()); + } + // Check for extra numbers at the end. + Matcher secondNumber = SECOND_NUMBER_START_PATTERN.matcher(number); + if (secondNumber.find()) { + number = number.subSequence(0, secondNumber.start()); + } + return number; + } else { + return ""; + } + } + + /** + * Checks to see if the string of characters could possibly be a phone number at all. At the + * moment, checks to see that the string begins with at least 2 digits, ignoring any punctuation + * commonly found in phone numbers. + * This method does not require the number to be normalized in advance - but does assume that + * leading non-number symbols have been removed, such as by the method extractPossibleNumber. + * + * @param number string to be checked for viability as a phone number + * @return true if the number could be a phone number of some sort, otherwise false + */ + // @VisibleForTesting + static boolean isViablePhoneNumber(CharSequence number) { + if (number.length() < MIN_LENGTH_FOR_NSN) { + return false; + } + Matcher m = VALID_PHONE_NUMBER_PATTERN.matcher(number); + return m.matches(); + } + + /** + * Normalizes a string of characters representing a phone number. This performs the following + * conversions: + * - Punctuation is stripped. + * For ALPHA/VANITY numbers: + * - Letters are converted to their numeric representation on a telephone keypad. The keypad + * used here is the one defined in ITU Recommendation E.161. This is only done if there are 3 + * or more letters in the number, to lessen the risk that such letters are typos. + * For other numbers: + * - Wide-ascii digits are converted to normal ASCII (European) digits. + * - Arabic-Indic numerals are converted to European numerals. + * - Spurious alpha characters are stripped. + * + * @param number a StringBuilder of characters representing a phone number that will be + * normalized in place + */ + static StringBuilder normalize(StringBuilder number) { + Matcher m = VALID_ALPHA_PHONE_PATTERN.matcher(number); + if (m.matches()) { + number.replace(0, number.length(), normalizeHelper(number, ALPHA_PHONE_MAPPINGS, true)); + } else { + number.replace(0, number.length(), normalizeDigitsOnly(number)); + } + return number; + } + + /** + * Normalizes a string of characters representing a phone number. This converts wide-ascii and + * arabic-indic numerals to European numerals, and strips punctuation and alpha characters. + * + * @param number a string of characters representing a phone number + * @return the normalized string version of the phone number + */ + public static String normalizeDigitsOnly(CharSequence number) { + return normalizeDigits(number, false /* strip non-digits */).toString(); + } + + static StringBuilder normalizeDigits(CharSequence number, boolean keepNonDigits) { + StringBuilder normalizedDigits = new StringBuilder(number.length()); + for (int i = 0; i < number.length(); i++) { + char c = number.charAt(i); + int digit = Character.digit(c, 10); + if (digit != -1) { + normalizedDigits.append(digit); + } else if (keepNonDigits) { + normalizedDigits.append(c); + } + } + return normalizedDigits; + } + + /** + * Normalizes a string of characters representing a phone number. This strips all characters which + * are not diallable on a mobile phone keypad (including all non-ASCII digits). + * + * @param number a string of characters representing a phone number + * @return the normalized string version of the phone number + */ + public static String normalizeDiallableCharsOnly(CharSequence number) { + return normalizeHelper(number, DIALLABLE_CHAR_MAPPINGS, true /* remove non matches */); + } + + /** + * Converts all alpha characters in a number to their respective digits on a keypad, but retains + * existing formatting. + */ + public static String convertAlphaCharactersInNumber(CharSequence number) { + return normalizeHelper(number, ALPHA_PHONE_MAPPINGS, false); + } + + /** + * Gets the length of the geographical area code from the + * PhoneNumber object passed in, so that clients could use it + * to split a national significant number into geographical area code and subscriber number. It + * works in such a way that the resultant subscriber number should be diallable, at least on some + * devices. An example of how this could be used: + * + *

{@code
+   * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+   * PhoneNumber number = phoneUtil.parse("16502530000", "US");
+   * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+   * String areaCode;
+   * String subscriberNumber;
+   *
+   * int areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
+   * if (areaCodeLength > 0) {
+   *   areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
+   *   subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
+   * } else {
+   *   areaCode = "";
+   *   subscriberNumber = nationalSignificantNumber;
+   * }
+   * }
+ * + * N.B.: area code is a very ambiguous concept, so the I18N team generally recommends against + * using it for most purposes, but recommends using the more general {@code national_number} + * instead. Read the following carefully before deciding to use this method: + *
    + *
  • geographical area codes change over time, and this method honors those changes; + * therefore, it doesn't guarantee the stability of the result it produces. + *
  • subscriber numbers may not be diallable from all devices (notably mobile devices, which + * typically requires the full national_number to be dialled in most regions). + *
  • most non-geographical numbers have no area codes, including numbers from non-geographical + * entities + *
  • some geographical numbers have no area codes. + *
+ * @param number the PhoneNumber object for which clients + * want to know the length of the area code + * @return the length of area code of the PhoneNumber object + * passed in + */ + public int getLengthOfGeographicalAreaCode(PhoneNumber number) { + PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number)); + if (metadata == null) { + return 0; + } + + PhoneNumberType type = getNumberType(number); + int countryCallingCode = number.getCountryCode(); + // If a country doesn't use a national prefix, and this number doesn't have an Italian leading + // zero, we assume it is a closed dialling plan with no area codes. + // Note:this is our general assumption, but there are exceptions which are tracked in + // COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES. + if (!metadata.hasNationalPrefix() && !number.isItalianLeadingZero() + && !COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES.contains(countryCallingCode)) { + return 0; + } + + if (type == PhoneNumberType.MOBILE + // Note this is a rough heuristic; it doesn't cover Indonesia well, for example, where area + // codes are present for some mobile phones but not for others. We have no better way of + // representing this in the metadata at this point. + && GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES.contains(countryCallingCode)) { + return 0; + } + + if (!isNumberGeographical(type, countryCallingCode)) { + return 0; + } + + return getLengthOfNationalDestinationCode(number); + } + + /** + * Gets the length of the national destination code (NDC) from the + * PhoneNumber object passed in, so that clients could use it + * to split a national significant number into NDC and subscriber number. The NDC of a phone + * number is normally the first group of digit(s) right after the country calling code when the + * number is formatted in the international format, if there is a subscriber number part that + * follows. + * + * N.B.: similar to an area code, not all numbers have an NDC! + * + * An example of how this could be used: + * + *
{@code
+   * PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+   * PhoneNumber number = phoneUtil.parse("18002530000", "US");
+   * String nationalSignificantNumber = phoneUtil.getNationalSignificantNumber(number);
+   * String nationalDestinationCode;
+   * String subscriberNumber;
+   *
+   * int nationalDestinationCodeLength = phoneUtil.getLengthOfNationalDestinationCode(number);
+   * if (nationalDestinationCodeLength > 0) {
+   *   nationalDestinationCode = nationalSignificantNumber.substring(0,
+   *       nationalDestinationCodeLength);
+   *   subscriberNumber = nationalSignificantNumber.substring(nationalDestinationCodeLength);
+   * } else {
+   *   nationalDestinationCode = "";
+   *   subscriberNumber = nationalSignificantNumber;
+   * }
+   * }
+ * + * Refer to the unittests to see the difference between this function and + * {@link #getLengthOfGeographicalAreaCode}. + * + * @param number the PhoneNumber object for which clients + * want to know the length of the NDC + * @return the length of NDC of the PhoneNumber object + * passed in, which could be zero + */ + public int getLengthOfNationalDestinationCode(PhoneNumber number) { + PhoneNumber copiedProto; + if (number.hasExtension()) { + // We don't want to alter the proto given to us, but we don't want to include the extension + // when we format it, so we copy it and clear the extension here. + copiedProto = new PhoneNumber(); + copiedProto.mergeFrom(number); + copiedProto.clearExtension(); + } else { + copiedProto = number; + } + + String nationalSignificantNumber = format(copiedProto, + PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); + String[] numberGroups = NON_DIGITS_PATTERN.split(nationalSignificantNumber); + // The pattern will start with "+COUNTRY_CODE " so the first group will always be the empty + // string (before the + symbol) and the second group will be the country calling code. The third + // group will be area code if it is not the last group. + if (numberGroups.length <= 3) { + return 0; + } + + if (getNumberType(number) == PhoneNumberType.MOBILE) { + // For example Argentinian mobile numbers, when formatted in the international format, are in + // the form of +54 9 NDC XXXX.... As a result, we take the length of the third group (NDC) and + // add the length of the second group (which is the mobile token), which also forms part of + // the national significant number. This assumes that the mobile token is always formatted + // separately from the rest of the phone number. + String mobileToken = getCountryMobileToken(number.getCountryCode()); + if (!mobileToken.equals("")) { + return numberGroups[2].length() + numberGroups[3].length(); + } + } + return numberGroups[2].length(); + } + + /** + * Returns the mobile token for the provided country calling code if it has one, otherwise + * returns an empty string. A mobile token is a number inserted before the area code when dialing + * a mobile number from that country from abroad. + * + * @param countryCallingCode the country calling code for which we want the mobile token + * @return the mobile token, as a string, for the given country calling code + */ + public static String getCountryMobileToken(int countryCallingCode) { + if (MOBILE_TOKEN_MAPPINGS.containsKey(countryCallingCode)) { + return MOBILE_TOKEN_MAPPINGS.get(countryCallingCode); + } + return ""; + } + + /** + * Normalizes a string of characters representing a phone number by replacing all characters found + * in the accompanying map with the values therein, and stripping all other characters if + * removeNonMatches is true. + * + * @param number a string of characters representing a phone number + * @param normalizationReplacements a mapping of characters to what they should be replaced by in + * the normalized version of the phone number + * @param removeNonMatches indicates whether characters that are not able to be replaced should + * be stripped from the number. If this is false, they will be left unchanged in the number. + * @return the normalized string version of the phone number + */ + private static String normalizeHelper(CharSequence number, + Map normalizationReplacements, + boolean removeNonMatches) { + StringBuilder normalizedNumber = new StringBuilder(number.length()); + for (int i = 0; i < number.length(); i++) { + char character = number.charAt(i); + Character newDigit = normalizationReplacements.get(Character.toUpperCase(character)); + if (newDigit != null) { + normalizedNumber.append(newDigit); + } else if (!removeNonMatches) { + normalizedNumber.append(character); + } + // If neither of the above are true, we remove this character. + } + return normalizedNumber.toString(); + } + + /** + * Sets or resets the PhoneNumberUtil singleton instance. If set to null, the next call to + * {@code getInstance()} will load (and return) the default instance. + */ + // @VisibleForTesting + static synchronized void setInstance(PhoneNumberUtil util) { + instance = util; + } + + /** + * Returns all regions the library has metadata for. + * + * @return an unordered set of the two-letter region codes for every geographical region the + * library supports + */ + public Set getSupportedRegions() { + return Collections.unmodifiableSet(supportedRegions); + } + + /** + * Returns all global network calling codes the library has metadata for. + * + * @return an unordered set of the country calling codes for every non-geographical entity the + * library supports + */ + public Set getSupportedGlobalNetworkCallingCodes() { + return Collections.unmodifiableSet(countryCodesForNonGeographicalRegion); + } + + /** + * Returns all country calling codes the library has metadata for, covering both non-geographical + * entities (global network calling codes) and those used for geographical entities. This could be + * used to populate a drop-down box of country calling codes for a phone-number widget, for + * instance. + * + * @return an unordered set of the country calling codes for every geographical and + * non-geographical entity the library supports + */ + public Set getSupportedCallingCodes() { + return Collections.unmodifiableSet(countryCallingCodeToRegionCodeMap.keySet()); + } + + /** + * Returns true if there is any possible number data set for a particular PhoneNumberDesc. + */ + private static boolean descHasPossibleNumberData(PhoneNumberDesc desc) { + // If this is empty, it means numbers of this type inherit from the "general desc" -> the value + // "-1" means that no numbers exist for this type. + return desc.getPossibleLengthCount() != 1 || desc.getPossibleLength(0) != -1; + } + + // Note: descHasData must account for any of MetadataFilter's excludableChildFields potentially + // being absent from the metadata. It must check them all. For any changes in descHasData, ensure + // that all the excludableChildFields are still being checked. If your change is safe simply + // mention why during a review without needing to change MetadataFilter. + /** + * Returns true if there is any data set for a particular PhoneNumberDesc. + */ + private static boolean descHasData(PhoneNumberDesc desc) { + // Checking most properties since we don't know what's present, since a custom build may have + // stripped just one of them (e.g. liteBuild strips exampleNumber). We don't bother checking the + // possibleLengthsLocalOnly, since if this is the only thing that's present we don't really + // support the type at all: no type-specific methods will work with only this data. + return desc.hasExampleNumber() + || descHasPossibleNumberData(desc) + || desc.hasNationalNumberPattern(); + } + + /** + * Returns the types we have metadata for based on the PhoneMetadata object passed in, which must + * be non-null. + */ + private Set getSupportedTypesForMetadata(PhoneMetadata metadata) { + Set types = new TreeSet<>(); + for (PhoneNumberType type : PhoneNumberType.values()) { + if (type == PhoneNumberType.FIXED_LINE_OR_MOBILE || type == PhoneNumberType.UNKNOWN) { + // Never return FIXED_LINE_OR_MOBILE (it is a convenience type, and represents that a + // particular number type can't be determined) or UNKNOWN (the non-type). + continue; + } + if (descHasData(getNumberDescByType(metadata, type))) { + types.add(type); + } + } + return Collections.unmodifiableSet(types); + } + + /** + * Returns the types for a given region which the library has metadata for. Will not include + * FIXED_LINE_OR_MOBILE (if numbers in this region could be classified as FIXED_LINE_OR_MOBILE, + * both FIXED_LINE and MOBILE would be present) and UNKNOWN. + * + * No types will be returned for invalid or unknown region codes. + */ + public Set getSupportedTypesForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return Collections.unmodifiableSet(new TreeSet()); + } + PhoneMetadata metadata = getMetadataForRegion(regionCode); + return getSupportedTypesForMetadata(metadata); + } + + /** + * Returns the types for a country-code belonging to a non-geographical entity which the library + * has metadata for. Will not include FIXED_LINE_OR_MOBILE (if numbers for this non-geographical + * entity could be classified as FIXED_LINE_OR_MOBILE, both FIXED_LINE and MOBILE would be + * present) and UNKNOWN. + * + * No types will be returned for country calling codes that do not map to a known non-geographical + * entity. + */ + public Set getSupportedTypesForNonGeoEntity(int countryCallingCode) { + PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); + if (metadata == null) { + logger.log(Level.WARNING, "Unknown country calling code for a non-geographical entity " + + "provided: " + countryCallingCode); + return Collections.unmodifiableSet(new TreeSet()); + } + return getSupportedTypesForMetadata(metadata); + } + + /** + * Gets a {@link PhoneNumberUtil} instance to carry out international phone number formatting, + * parsing, or validation. The instance is loaded with all phone number metadata. + * + *

The {@link PhoneNumberUtil} is implemented as a singleton. Therefore, calling getInstance + * multiple times will only result in one instance being created. + * + * @return a PhoneNumberUtil instance + */ + public static synchronized PhoneNumberUtil getInstance() { + if (instance == null) { + MetadataLoader metadataLoader = DefaultMetadataDependenciesProvider.getInstance() + .getMetadataLoader(); + setInstance(createInstance(metadataLoader)); + } + return instance; + } + + /** + * Create a new {@link PhoneNumberUtil} instance to carry out international phone number + * formatting, parsing, or validation. The instance is loaded with all metadata by + * using the metadataLoader specified. + * + *

This method should only be used in the rare case in which you want to manage your own + * metadata loading. Calling this method multiple times is very expensive, as each time + * a new instance is created from scratch. When in doubt, use {@link #getInstance}. + * + * @param metadataLoader customized metadata loader. This should not be null + * @return a PhoneNumberUtil instance + */ + public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) { + if (metadataLoader == null) { + throw new IllegalArgumentException("metadataLoader could not be null."); + } + return createInstance(new MetadataSourceImpl( + DefaultMetadataDependenciesProvider.getInstance().getPhoneNumberMetadataFileNameProvider(), + metadataLoader, + DefaultMetadataDependenciesProvider.getInstance().getMetadataParser() + )); + } + + /** + * Create a new {@link PhoneNumberUtil} instance to carry out international phone number + * formatting, parsing, or validation. The instance is loaded with all metadata by + * using the metadataSource specified. + * + *

This method should only be used in the rare case in which you want to manage your own + * metadata loading. Calling this method multiple times is very expensive, as each time + * a new instance is created from scratch. When in doubt, use {@link #getInstance}. + * + * @param metadataSource customized metadata source. This should not be null + * @return a PhoneNumberUtil instance + */ + private static PhoneNumberUtil createInstance(MetadataSource metadataSource) { + if (metadataSource == null) { + throw new IllegalArgumentException("metadataSource could not be null."); + } + return new PhoneNumberUtil(metadataSource, + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap()); + } + + /** + * Helper function to check if the national prefix formatting rule has the first group only, i.e., + * does not start with the national prefix. + */ + static boolean formattingRuleHasFirstGroupOnly(String nationalPrefixFormattingRule) { + return nationalPrefixFormattingRule.length() == 0 + || FIRST_GROUP_ONLY_PREFIX_PATTERN.matcher(nationalPrefixFormattingRule).matches(); + } + + /** + * Tests whether a phone number has a geographical association. It checks if the number is + * associated with a certain region in the country to which it belongs. Note that this doesn't + * verify if the number is actually in use. + */ + public boolean isNumberGeographical(PhoneNumber phoneNumber) { + return isNumberGeographical(getNumberType(phoneNumber), phoneNumber.getCountryCode()); + } + + /** + * Overload of isNumberGeographical(PhoneNumber), since calculating the phone number type is + * expensive; if we have already done this, we don't want to do it again. + */ + public boolean isNumberGeographical(PhoneNumberType phoneNumberType, int countryCallingCode) { + return phoneNumberType == PhoneNumberType.FIXED_LINE + || phoneNumberType == PhoneNumberType.FIXED_LINE_OR_MOBILE + || (GEO_MOBILE_COUNTRIES.contains(countryCallingCode) + && phoneNumberType == PhoneNumberType.MOBILE); + } + + /** + * Helper function to check region code is not unknown or null. + */ + private boolean isValidRegionCode(String regionCode) { + return regionCode != null && supportedRegions.contains(regionCode); + } + + /** + * Helper function to check the country calling code is valid. + */ + private boolean hasValidCountryCallingCode(int countryCallingCode) { + return countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode); + } + + /** + * Formats a phone number in the specified format using default rules. Note that this does not + * promise to produce a phone number that the user can dial from where they are - although we do + * format in either 'national' or 'international' format depending on what the client asks for, we + * do not currently support a more abbreviated format, such as for users in the same "area" who + * could potentially dial the number without area code. Note that if the phone number has a + * country calling code of 0 or an otherwise invalid country calling code, we cannot work out + * which formatting rules to apply so we return the national significant number with no formatting + * applied. + * + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into + * @return the formatted phone number + */ + public String format(PhoneNumber number, PhoneNumberFormat numberFormat) { + if (number.getNationalNumber() == 0) { + // Unparseable numbers that kept their raw input just use that. + // This is the only case where a number can be formatted as E164 without a + // leading '+' symbol (but the original number wasn't parseable anyway). + String rawInput = number.getRawInput(); + if (rawInput.length() > 0 || !number.hasCountryCode()) { + return rawInput; + } + } + StringBuilder formattedNumber = new StringBuilder(20); + format(number, numberFormat, formattedNumber); + return formattedNumber.toString(); + } + + /** + * Same as {@link #format(PhoneNumber, PhoneNumberFormat)}, but accepts a mutable StringBuilder as + * a parameter to decrease object creation when invoked many times. + */ + public void format(PhoneNumber number, PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + // Clear the StringBuilder first. + formattedNumber.setLength(0); + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + + if (numberFormat == PhoneNumberFormat.E164) { + // Early exit for E164 case (even if the country calling code is invalid) since no formatting + // of the national number needs to be applied. Extensions are not formatted. + formattedNumber.append(nationalSignificantNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.E164, + formattedNumber); + return; + } + if (!hasValidCountryCallingCode(countryCallingCode)) { + formattedNumber.append(nationalSignificantNumber); + return; + } + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid (which means that the + // region code cannot be ZZ and must be one of our supported region codes). + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, numberFormat)); + maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber); + } + + /** + * Formats a phone number in the specified format using client-defined formatting rules. Note that + * if the phone number has a country calling code of zero or an otherwise invalid country calling + * code, we cannot work out things like whether there should be a national prefix applied, or how + * to format extensions, so we return the national significant number with no formatting applied. + * + * @param number the phone number to be formatted + * @param numberFormat the format the phone number should be formatted into + * @param userDefinedFormats formatting rules specified by clients + * @return the formatted phone number + */ + public String formatByPattern(PhoneNumber number, + PhoneNumberFormat numberFormat, + List userDefinedFormats) { + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + + StringBuilder formattedNumber = new StringBuilder(20); + + NumberFormat formattingPattern = + chooseFormattingPatternForNumber(userDefinedFormats, nationalSignificantNumber); + if (formattingPattern == null) { + // If no pattern above is matched, we format the number as a whole. + formattedNumber.append(nationalSignificantNumber); + } else { + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); + // Before we do a replacement of the national prefix pattern $NP with the national prefix, we + // need to copy the rule so that subsequent replacements for different numbers have the + // appropriate national prefix. + numFormatCopy.mergeFrom(formattingPattern); + String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule(); + if (nationalPrefixFormattingRule.length() > 0) { + String nationalPrefix = metadata.getNationalPrefix(); + if (nationalPrefix.length() > 0) { + // Replace $NP with national prefix and $FG with the first group ($1). + nationalPrefixFormattingRule = + nationalPrefixFormattingRule.replace(NP_STRING, nationalPrefix); + nationalPrefixFormattingRule = nationalPrefixFormattingRule.replace(FG_STRING, "$1"); + numFormatCopy.setNationalPrefixFormattingRule(nationalPrefixFormattingRule); + } else { + // We don't want to have a rule for how to format the national prefix if there isn't one. + numFormatCopy.clearNationalPrefixFormattingRule(); + } + } + formattedNumber.append( + formatNsnUsingPattern(nationalSignificantNumber, numFormatCopy.build(), numberFormat)); + } + maybeAppendFormattedExtension(number, metadata, numberFormat, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, numberFormat, formattedNumber); + return formattedNumber.toString(); + } + + /** + * Formats a phone number in national format for dialing using the carrier as specified in the + * {@code carrierCode}. The {@code carrierCode} will always be used regardless of whether the + * phone number already has a preferred domestic carrier code stored. If {@code carrierCode} + * contains an empty string, returns the number in national format without any carrier code. + * + * @param number the phone number to be formatted + * @param carrierCode the carrier selection code to be used + * @return the formatted phone number in national format for dialing using the carrier as + * specified in the {@code carrierCode} + */ + public String formatNationalNumberWithCarrierCode(PhoneNumber number, CharSequence carrierCode) { + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + + // Note getRegionCodeForCountryCode() is used because formatting information for regions which + // share a country calling code is contained by only one region for performance reasons. For + // example, for NANPA regions it will be contained in the metadata for US. + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + + StringBuilder formattedNumber = new StringBuilder(20); + formattedNumber.append(formatNsn(nationalSignificantNumber, metadata, + PhoneNumberFormat.NATIONAL, carrierCode)); + maybeAppendFormattedExtension(number, metadata, PhoneNumberFormat.NATIONAL, formattedNumber); + prefixNumberWithCountryCallingCode(countryCallingCode, PhoneNumberFormat.NATIONAL, + formattedNumber); + return formattedNumber.toString(); + } + + private PhoneMetadata getMetadataForRegionOrCallingCode( + int countryCallingCode, String regionCode) { + return REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + ? getMetadataForNonGeographicalRegion(countryCallingCode) + : getMetadataForRegion(regionCode); + } + + /** + * Formats a phone number in national format for dialing using the carrier as specified in the + * preferredDomesticCarrierCode field of the PhoneNumber object passed in. If that is missing, + * use the {@code fallbackCarrierCode} passed in instead. If there is no + * {@code preferredDomesticCarrierCode}, and the {@code fallbackCarrierCode} contains an empty + * string, return the number in national format without any carrier code. + * + *

Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier code passed in + * should take precedence over the number's {@code preferredDomesticCarrierCode} when formatting. + * + * @param number the phone number to be formatted + * @param fallbackCarrierCode the carrier selection code to be used, if none is found in the + * phone number itself + * @return the formatted phone number in national format for dialing using the number's + * {@code preferredDomesticCarrierCode}, or the {@code fallbackCarrierCode} passed in if + * none is found + */ + public String formatNationalNumberWithPreferredCarrierCode(PhoneNumber number, + CharSequence fallbackCarrierCode) { + return formatNationalNumberWithCarrierCode(number, + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + number.getPreferredDomesticCarrierCode().length() > 0 + ? number.getPreferredDomesticCarrierCode() + : fallbackCarrierCode); + } + + /** + * Returns a number formatted in such a way that it can be dialed from a mobile phone in a + * specific region. If the number cannot be reached from the region (e.g. some countries block + * toll-free numbers from being called outside of the country), the method returns an empty + * string. + * + * @param number the phone number to be formatted + * @param regionCallingFrom the region where the call is being placed + * @param withFormatting whether the number should be returned with formatting symbols, such as + * spaces and dashes. + * @return the formatted phone number + */ + public String formatNumberForMobileDialing(PhoneNumber number, String regionCallingFrom, + boolean withFormatting) { + int countryCallingCode = number.getCountryCode(); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return number.hasRawInput() ? number.getRawInput() : ""; + } + + String formattedNumber = ""; + // Clear the extension, as that part cannot normally be dialed together with the main number. + PhoneNumber numberNoExt = new PhoneNumber().mergeFrom(number).clearExtension(); + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + PhoneNumberType numberType = getNumberType(numberNoExt); + boolean isValidNumber = (numberType != PhoneNumberType.UNKNOWN); + if (regionCallingFrom.equals(regionCode)) { + boolean isFixedLineOrMobile = + (numberType == PhoneNumberType.FIXED_LINE) || (numberType == PhoneNumberType.MOBILE) + || (numberType == PhoneNumberType.FIXED_LINE_OR_MOBILE); + // Carrier codes may be needed in some countries. We handle this here. + if (regionCode.equals("BR") && isFixedLineOrMobile) { + // Historically, we set this to an empty string when parsing with raw input if none was + // found in the input string. However, this doesn't result in a number we can dial. For this + // reason, we treat the empty string the same as if it isn't set at all. + formattedNumber = numberNoExt.getPreferredDomesticCarrierCode().length() > 0 + ? formattedNumber = formatNationalNumberWithPreferredCarrierCode(numberNoExt, "") + // Brazilian fixed line and mobile numbers need to be dialed with a carrier code when + // called within Brazil. Without that, most of the carriers won't connect the call. + // Because of that, we return an empty string here. + : ""; + } else if (countryCallingCode == NANPA_COUNTRY_CODE) { + // For NANPA countries, we output international format for numbers that can be dialed + // internationally, since that always works, except for numbers which might potentially be + // short numbers, which are always dialled in national format. + PhoneMetadata regionMetadata = getMetadataForRegion(regionCallingFrom); + if (canBeInternationallyDialled(numberNoExt) + && testNumberLength(getNationalSignificantNumber(numberNoExt), regionMetadata) + != ValidationResult.TOO_SHORT) { + formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); + } else { + formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); + } + } else { + // For non-geographical countries, and Mexican, Chilean, and Uzbek fixed line and mobile + // numbers, we output international format for numbers that can be dialed internationally as + // that always works. + if ((regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITY) + // MX fixed line and mobile numbers should always be formatted in international format, + // even when dialed within MX. For national format to work, a carrier code needs to be + // used, and the correct carrier code depends on if the caller and callee are from the + // same local area. It is trickier to get that to work correctly than using + // international format, which is tested to work fine on all carriers. + // CL fixed line numbers need the national prefix when dialing in the national format, + // but don't have it when used for display. The reverse is true for mobile numbers. As + // a result, we output them in the international format to make it work. + // UZ mobile and fixed-line numbers have to be formatted in international format or + // prefixed with special codes like 03, 04 (for fixed-line) and 05 (for mobile) for + // dialling successfully from mobile devices. As we do not have complete information on + // special codes and to be consistent with formatting across all phone types we return + // the number in international format here. + || ((regionCode.equals("MX") || regionCode.equals("CL") + || regionCode.equals("UZ")) && isFixedLineOrMobile)) + && canBeInternationallyDialled(numberNoExt)) { + formattedNumber = format(numberNoExt, PhoneNumberFormat.INTERNATIONAL); + } else { + formattedNumber = format(numberNoExt, PhoneNumberFormat.NATIONAL); + } + } + } else if (isValidNumber && canBeInternationallyDialled(numberNoExt)) { + // We assume that short numbers are not diallable from outside their region, so if a number + // is not a valid regular length phone number, we treat it as if it cannot be internationally + // dialled. + return withFormatting ? format(numberNoExt, PhoneNumberFormat.INTERNATIONAL) + : format(numberNoExt, PhoneNumberFormat.E164); + } + return withFormatting ? formattedNumber + : normalizeDiallableCharsOnly(formattedNumber); + } + + /** + * Formats a phone number for out-of-country dialing purposes. If no regionCallingFrom is + * supplied, we format the number in its INTERNATIONAL format. If the country calling code is the + * same as that of the region where the number is from, then NATIONAL formatting will be applied. + * + *

If the number itself has a country calling code of zero or an otherwise invalid country + * calling code, then we return the number with no formatting applied. + * + *

Note this function takes care of the case for calling inside of NANPA and between Russia and + * Kazakhstan (who share the same country calling code). In those cases, no international prefix + * is used. For regions which have multiple international prefixes, the number in its + * INTERNATIONAL format will be returned instead. + * + * @param number the phone number to be formatted + * @param regionCallingFrom the region where the call is being placed + * @return the formatted phone number + */ + public String formatOutOfCountryCallingNumber(PhoneNumber number, + String regionCallingFrom) { + if (!isValidRegionCode(regionCallingFrom)) { + logger.log(Level.WARNING, + "Trying to format number from invalid region " + + regionCallingFrom + + ". International formatting applied."); + return format(number, PhoneNumberFormat.INTERNATIONAL); + } + int countryCallingCode = number.getCountryCode(); + String nationalSignificantNumber = getNationalSignificantNumber(number); + if (!hasValidCountryCallingCode(countryCallingCode)) { + return nationalSignificantNumber; + } + if (countryCallingCode == NANPA_COUNTRY_CODE) { + if (isNANPACountry(regionCallingFrom)) { + // For NANPA regions, return the national format for these regions but prefix it with the + // country calling code. + return countryCallingCode + " " + format(number, PhoneNumberFormat.NATIONAL); + } + } else if (countryCallingCode == getCountryCodeForValidRegion(regionCallingFrom)) { + // If regions share a country calling code, the country calling code need not be dialled. + // This also applies when dialling within a region, so this if clause covers both these cases. + // Technically this is the case for dialling from La Reunion to other overseas departments of + // France (French Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover this + // edge case for now and for those cases return the version including country calling code. + // Details here: http://www.petitfute.com/voyage/225-info-pratiques-reunion + return format(number, PhoneNumberFormat.NATIONAL); + } + // Metadata cannot be null because we checked 'isValidRegionCode()' above. + PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom); + String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix(); + + // In general, if there is a preferred international prefix, use that. Otherwise, for regions + // that have multiple international prefixes, the international format of the number is + // returned since we would not know which one to use. + String internationalPrefixForFormatting = ""; + if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) { + internationalPrefixForFormatting = + metadataForRegionCallingFrom.getPreferredInternationalPrefix(); + } else if (SINGLE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches()) { + internationalPrefixForFormatting = internationalPrefix; + } + + String regionCode = getRegionCodeForCountryCode(countryCallingCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadataForRegion = + getMetadataForRegionOrCallingCode(countryCallingCode, regionCode); + String formattedNationalNumber = + formatNsn(nationalSignificantNumber, metadataForRegion, PhoneNumberFormat.INTERNATIONAL); + StringBuilder formattedNumber = new StringBuilder(formattedNationalNumber); + maybeAppendFormattedExtension(number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + prefixNumberWithCountryCallingCode(countryCallingCode, + PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + } + return formattedNumber.toString(); + } + + /** + * Formats a phone number using the original phone number format (e.g. INTERNATIONAL or NATIONAL) + * that the number is parsed from, provided that the number has been parsed with {@link + * parseAndKeepRawInput}. Otherwise the number will be formatted in NATIONAL format. + * + *

The original format is embedded in the country_code_source field of the PhoneNumber object + * passed in, which is only set when parsing keeps the raw input. When we don't have a formatting + * pattern for the number, the method falls back to returning the raw input. + * + *

Note this method guarantees no digit will be inserted, removed or modified as a result of + * formatting. + * + * @param number the phone number that needs to be formatted in its original number format + * @param regionCallingFrom the region whose IDD needs to be prefixed if the original number has + * one + * @return the formatted phone number in its original number format + */ + public String formatInOriginalFormat(PhoneNumber number, String regionCallingFrom) { + NumberFormat formatRule = chooseFormattingPatternForNumber(number); + if (number.hasRawInput() && formatRule == null) { + // We check if we have the formatting pattern because without that, we might format the number + // as a group without national prefix. + return number.getRawInput(); + } + if (!number.hasCountryCodeSource()) { + return format(number, PhoneNumberFormat.NATIONAL); + } + String formattedNumber; + switch (number.getCountryCodeSource()) { + case FROM_NUMBER_WITH_PLUS_SIGN: + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL); + break; + case FROM_NUMBER_WITH_IDD: + formattedNumber = formatOutOfCountryCallingNumber(number, regionCallingFrom); + break; + case FROM_NUMBER_WITHOUT_PLUS_SIGN: + formattedNumber = format(number, PhoneNumberFormat.INTERNATIONAL).substring(1); + break; + case FROM_DEFAULT_COUNTRY: + // Fall-through to default case. + default: + String regionCode = getRegionCodeForCountryCode(number.getCountryCode()); + // We strip non-digits from the NDD here, and from the raw input later, so that we can + // compare them easily. + String nationalPrefix = getNddPrefixForRegion(regionCode, true /* strip non-digits */); + String nationalFormat = format(number, PhoneNumberFormat.NATIONAL); + if (nationalPrefix == null || nationalPrefix.length() == 0) { + // If the region doesn't have a national prefix at all, we can safely return the national + // format without worrying about a national prefix being added. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we check if the original number was entered with a national prefix. + if (rawInputContainsNationalPrefix( + number.getRawInput(), nationalPrefix, regionCode)) { + // If so, we can safely return the national format. + formattedNumber = nationalFormat; + break; + } + // The format rule could still be null here if the national number was 0 and there was no + // raw input (this should not be possible for numbers generated by the phonenumber library + // as they would also not have a country calling code and we would have exited earlier). + if (formatRule == null) { + formattedNumber = nationalFormat; + break; + } + // When the format we apply to this number doesn't contain national prefix, we can just + // return the national format. + // TODO: Refactor the code below with the code in + // isNationalPrefixPresentIfRequired. + String candidateNationalPrefixRule = formatRule.getNationalPrefixFormattingRule(); + // We assume that the first-group symbol will never be _before_ the national prefix. + int indexOfFirstGroup = candidateNationalPrefixRule.indexOf("$1"); + if (indexOfFirstGroup <= 0) { + formattedNumber = nationalFormat; + break; + } + candidateNationalPrefixRule = + candidateNationalPrefixRule.substring(0, indexOfFirstGroup); + candidateNationalPrefixRule = normalizeDigitsOnly(candidateNationalPrefixRule); + if (candidateNationalPrefixRule.length() == 0) { + // National prefix not used when formatting this number. + formattedNumber = nationalFormat; + break; + } + // Otherwise, we need to remove the national prefix from our output. + NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); + numFormatCopy.mergeFrom(formatRule); + numFormatCopy.clearNationalPrefixFormattingRule(); + List numberFormats = new ArrayList<>(1); + numberFormats.add(numFormatCopy.build()); + formattedNumber = formatByPattern(number, PhoneNumberFormat.NATIONAL, numberFormats); + break; + } + String rawInput = number.getRawInput(); + // If no digit is inserted/removed/modified as a result of our formatting, we return the + // formatted phone number; otherwise we return the raw input the user entered. + if (formattedNumber != null && rawInput.length() > 0) { + String normalizedFormattedNumber = normalizeDiallableCharsOnly(formattedNumber); + String normalizedRawInput = normalizeDiallableCharsOnly(rawInput); + if (!normalizedFormattedNumber.equals(normalizedRawInput)) { + formattedNumber = rawInput; + } + } + return formattedNumber; + } + + // Check if rawInput, which is assumed to be in the national format, has a national prefix. The + // national prefix is assumed to be in digits-only form. + private boolean rawInputContainsNationalPrefix(String rawInput, String nationalPrefix, + String regionCode) { + String normalizedNationalNumber = normalizeDigitsOnly(rawInput); + if (normalizedNationalNumber.startsWith(nationalPrefix)) { + try { + // Some Japanese numbers (e.g. 00777123) might be mistaken to contain the national prefix + // when written without it (e.g. 0777123) if we just do prefix matching. To tackle that, we + // check the validity of the number if the assumed national prefix is removed (777123 won't + // be valid in Japan). + return isValidNumber( + parse(normalizedNationalNumber.substring(nationalPrefix.length()), regionCode)); + } catch (NumberParseException e) { + return false; + } + } + return false; + } + + private NumberFormat chooseFormattingPatternForNumber(PhoneNumber number) { + int countryCallingCode = number.getCountryCode(); + String phoneNumberRegion = getRegionCodeForCountryCode(countryCallingCode); + PhoneMetadata metadata = + getMetadataForRegionOrCallingCode(countryCallingCode, phoneNumberRegion); + if (metadata == null) { + return null; + } + String nationalNumber = getNationalSignificantNumber(number); + return chooseFormattingPatternForNumber(metadata.getNumberFormatList(), nationalNumber); + } + + NumberFormat chooseFormattingPatternForNumber(List availableFormats, + String nationalNumber) { + for (NumberFormat numFormat : availableFormats) { + int size = numFormat.getLeadingDigitsPatternCount(); + if (size == 0 || regexCache.getPatternForRegex( + // We always use the last leading_digits_pattern, as it is the most detailed. + numFormat.getLeadingDigitsPattern(size - 1)).matcher(nationalNumber).lookingAt()) { + Matcher m = regexCache.getPatternForRegex(numFormat.getPattern()).matcher(nationalNumber); + if (m.matches()) { + return numFormat; + } + } + } + return null; + } + + /** + * Formats a phone number for out-of-country dialing purposes. + * + * Note that in this version, if the number was entered originally using alpha characters and + * this version of the number is stored in raw_input, this representation of the number will be + * used rather than the digit representation. Grouping information, as specified by characters + * such as "-" and " ", will be retained. + * + *

Caveats:

+ *
    + *
  • This will not produce good results if the country calling code is both present in the raw + * input _and_ is the start of the national number. This is not a problem in the regions + * which typically use alpha numbers. + *
  • This will also not produce good results if the raw input has any grouping information + * within the first three digits of the national number, and if the function needs to strip + * preceding digits/words in the raw input before these digits. Normally people group the + * first three digits together so this is not a huge problem - and will be fixed if it + * proves to be so. + *
+ * + * @param number the phone number that needs to be formatted + * @param regionCallingFrom the region where the call is being placed + * @return the formatted phone number + */ + public String formatOutOfCountryKeepingAlphaChars(PhoneNumber number, + String regionCallingFrom) { + String rawInput = number.getRawInput(); + // If there is no raw input, then we can't keep alpha characters because there aren't any. + // In this case, we return formatOutOfCountryCallingNumber. + if (rawInput.length() == 0) { + return formatOutOfCountryCallingNumber(number, regionCallingFrom); + } + int countryCode = number.getCountryCode(); + if (!hasValidCountryCallingCode(countryCode)) { + return rawInput; + } + // Strip any prefix such as country calling code, IDD, that was present. We do this by comparing + // the number in raw_input with the parsed number. + // To do this, first we normalize punctuation. We retain number grouping symbols such as " " + // only. + rawInput = normalizeHelper(rawInput, ALL_PLUS_NUMBER_GROUPING_SYMBOLS, true); + // Now we trim everything before the first three digits in the parsed number. We choose three + // because all valid alpha numbers have 3 digits at the start - if it does not, then we don't + // trim anything at all. Similarly, if the national number was less than three digits, we don't + // trim anything at all. + String nationalNumber = getNationalSignificantNumber(number); + if (nationalNumber.length() > 3) { + int firstNationalNumberDigit = rawInput.indexOf(nationalNumber.substring(0, 3)); + if (firstNationalNumberDigit != -1) { + rawInput = rawInput.substring(firstNationalNumberDigit); + } + } + PhoneMetadata metadataForRegionCallingFrom = getMetadataForRegion(regionCallingFrom); + if (countryCode == NANPA_COUNTRY_CODE) { + if (isNANPACountry(regionCallingFrom)) { + return countryCode + " " + rawInput; + } + } else if (metadataForRegionCallingFrom != null + && countryCode == getCountryCodeForValidRegion(regionCallingFrom)) { + NumberFormat formattingPattern = + chooseFormattingPatternForNumber(metadataForRegionCallingFrom.getNumberFormatList(), + nationalNumber); + if (formattingPattern == null) { + // If no pattern above is matched, we format the original input. + return rawInput; + } + NumberFormat.Builder newFormat = NumberFormat.newBuilder(); + newFormat.mergeFrom(formattingPattern); + // The first group is the first group of digits that the user wrote together. + newFormat.setPattern("(\\d+)(.*)"); + // Here we just concatenate them back together after the national prefix has been fixed. + newFormat.setFormat("$1$2"); + // Now we format using this pattern instead of the default pattern, but with the national + // prefix prefixed if necessary. + // This will not work in the cases where the pattern (and not the leading digits) decide + // whether a national prefix needs to be used, since we have overridden the pattern to match + // anything, but that is not the case in the metadata to date. + return formatNsnUsingPattern(rawInput, newFormat.build(), PhoneNumberFormat.NATIONAL); + } + String internationalPrefixForFormatting = ""; + // If an unsupported region-calling-from is entered, or a country with multiple international + // prefixes, the international format of the number is returned, unless there is a preferred + // international prefix. + if (metadataForRegionCallingFrom != null) { + String internationalPrefix = metadataForRegionCallingFrom.getInternationalPrefix(); + internationalPrefixForFormatting = + SINGLE_INTERNATIONAL_PREFIX.matcher(internationalPrefix).matches() + ? internationalPrefix + : metadataForRegionCallingFrom.getPreferredInternationalPrefix(); + } + StringBuilder formattedNumber = new StringBuilder(rawInput); + String regionCode = getRegionCodeForCountryCode(countryCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadataForRegion = getMetadataForRegionOrCallingCode(countryCode, regionCode); + // Strip any extension + maybeStripExtension(formattedNumber); + // Append the formatted extension + maybeAppendFormattedExtension( + number, metadataForRegion, PhoneNumberFormat.INTERNATIONAL, formattedNumber); + if (internationalPrefixForFormatting.length() > 0) { + formattedNumber.insert(0, " ").insert(0, countryCode).insert(0, " ") + .insert(0, internationalPrefixForFormatting); + } else { + // Invalid region entered as country-calling-from (so no metadata was found for it) or the + // region chosen has multiple international dialling prefixes. + if (!isValidRegionCode(regionCallingFrom)) { + logger.log(Level.WARNING, + "Trying to format number from invalid region " + + regionCallingFrom + + ". International formatting applied."); + } + prefixNumberWithCountryCallingCode(countryCode, + PhoneNumberFormat.INTERNATIONAL, + formattedNumber); + } + return formattedNumber.toString(); + } + + /** + * Gets the national significant number of a phone number. Note a national significant number + * doesn't contain a national prefix or any formatting. + * + * @param number the phone number for which the national significant number is needed + * @return the national significant number of the PhoneNumber object passed in + */ + public String getNationalSignificantNumber(PhoneNumber number) { + // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix. + StringBuilder nationalNumber = new StringBuilder(); + if (number.isItalianLeadingZero() && number.getNumberOfLeadingZeros() > 0) { + char[] zeros = new char[number.getNumberOfLeadingZeros()]; + Arrays.fill(zeros, '0'); + nationalNumber.append(new String(zeros)); + } + nationalNumber.append(number.getNationalNumber()); + return nationalNumber.toString(); + } + + /** + * A helper function that is used by format and formatByPattern. + */ + private void prefixNumberWithCountryCallingCode(int countryCallingCode, + PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + switch (numberFormat) { + case E164: + formattedNumber.insert(0, countryCallingCode).insert(0, PLUS_SIGN); + return; + case INTERNATIONAL: + formattedNumber.insert(0, " ").insert(0, countryCallingCode).insert(0, PLUS_SIGN); + return; + case RFC3966: + formattedNumber.insert(0, "-").insert(0, countryCallingCode).insert(0, PLUS_SIGN) + .insert(0, RFC3966_PREFIX); + return; + case NATIONAL: + default: + return; + } + } + + // Simple wrapper of formatNsn for the common case of no carrier code. + private String formatNsn(String number, PhoneMetadata metadata, PhoneNumberFormat numberFormat) { + return formatNsn(number, metadata, numberFormat, null); + } + + // Note in some regions, the national number can be written in two completely different ways + // depending on whether it forms part of the NATIONAL format or INTERNATIONAL format. The + // numberFormat parameter here is used to specify which format to use for those cases. If a + // carrierCode is specified, this will be inserted into the formatted string to replace $CC. + private String formatNsn(String number, + PhoneMetadata metadata, + PhoneNumberFormat numberFormat, + CharSequence carrierCode) { + List intlNumberFormats = metadata.getIntlNumberFormatList(); + // When the intlNumberFormats exists, we use that to format national number for the + // INTERNATIONAL format instead of using the numberDesc.numberFormats. + List availableFormats = + (intlNumberFormats.size() == 0 || numberFormat == PhoneNumberFormat.NATIONAL) + ? metadata.getNumberFormatList() + : metadata.getIntlNumberFormatList(); + NumberFormat formattingPattern = chooseFormattingPatternForNumber(availableFormats, number); + return (formattingPattern == null) + ? number + : formatNsnUsingPattern(number, formattingPattern, numberFormat, carrierCode); + } + + // Simple wrapper of formatNsnUsingPattern for the common case of no carrier code. + String formatNsnUsingPattern(String nationalNumber, + NumberFormat formattingPattern, + PhoneNumberFormat numberFormat) { + return formatNsnUsingPattern(nationalNumber, formattingPattern, numberFormat, null); + } + + // Note that carrierCode is optional - if null or an empty string, no carrier code replacement + // will take place. + private String formatNsnUsingPattern(String nationalNumber, + NumberFormat formattingPattern, + PhoneNumberFormat numberFormat, + CharSequence carrierCode) { + String numberFormatRule = formattingPattern.getFormat(); + Matcher m = + regexCache.getPatternForRegex(formattingPattern.getPattern()).matcher(nationalNumber); + String formattedNationalNumber = ""; + if (numberFormat == PhoneNumberFormat.NATIONAL + && carrierCode != null && carrierCode.length() > 0 + && formattingPattern.getDomesticCarrierCodeFormattingRule().length() > 0) { + // Replace the $CC in the formatting rule with the desired carrier code. + String carrierCodeFormattingRule = formattingPattern.getDomesticCarrierCodeFormattingRule(); + carrierCodeFormattingRule = carrierCodeFormattingRule.replace(CC_STRING, carrierCode); + // Now replace the $FG in the formatting rule with the first group and the carrier code + // combined in the appropriate way. + numberFormatRule = FIRST_GROUP_PATTERN.matcher(numberFormatRule) + .replaceFirst(carrierCodeFormattingRule); + formattedNationalNumber = m.replaceAll(numberFormatRule); + } else { + // Use the national prefix formatting rule instead. + String nationalPrefixFormattingRule = formattingPattern.getNationalPrefixFormattingRule(); + if (numberFormat == PhoneNumberFormat.NATIONAL + && nationalPrefixFormattingRule != null + && nationalPrefixFormattingRule.length() > 0) { + Matcher firstGroupMatcher = FIRST_GROUP_PATTERN.matcher(numberFormatRule); + formattedNationalNumber = + m.replaceAll(firstGroupMatcher.replaceFirst(nationalPrefixFormattingRule)); + } else { + formattedNationalNumber = m.replaceAll(numberFormatRule); + } + } + if (numberFormat == PhoneNumberFormat.RFC3966) { + // Strip any leading punctuation. + Matcher matcher = SEPARATOR_PATTERN.matcher(formattedNationalNumber); + if (matcher.lookingAt()) { + formattedNationalNumber = matcher.replaceFirst(""); + } + // Replace the rest with a dash between each number group. + formattedNationalNumber = matcher.reset(formattedNationalNumber).replaceAll("-"); + } + return formattedNationalNumber; + } + + /** + * Gets a valid number for the specified region. + * + * @param regionCode the region for which an example number is needed + * @return a valid fixed-line number for the specified region. Returns null when the metadata + * does not contain such information, or the region 001 is passed in. For 001 (representing + * non-geographical numbers), call {@link #getExampleNumberForNonGeoEntity} instead. + */ + public PhoneNumber getExampleNumber(String regionCode) { + return getExampleNumberForType(regionCode, PhoneNumberType.FIXED_LINE); + } + + /** + * Gets an invalid number for the specified region. This is useful for unit-testing purposes, + * where you want to test what will happen with an invalid number. Note that the number that is + * returned will always be able to be parsed and will have the correct country code. It may also + * be a valid *short* number/code for this region. Validity checking such numbers is handled with + * {@link com.google.i18n.phonenumbers.ShortNumberInfo}. + * + * @param regionCode the region for which an example number is needed + * @return an invalid number for the specified region. Returns null when an unsupported region or + * the region 001 (Earth) is passed in. + */ + public PhoneNumber getInvalidExampleNumber(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return null; + } + // We start off with a valid fixed-line number since every country supports this. Alternatively + // we could start with a different number type, since fixed-line numbers typically have a wide + // breadth of valid number lengths and we may have to make it very short before we get an + // invalid number. + PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), + PhoneNumberType.FIXED_LINE); + if (!desc.hasExampleNumber()) { + // This shouldn't happen; we have a test for this. + return null; + } + String exampleNumber = desc.getExampleNumber(); + // Try and make the number invalid. We do this by changing the length. We try reducing the + // length of the number, since currently no region has a number that is the same length as + // MIN_LENGTH_FOR_NSN. This is probably quicker than making the number longer, which is another + // alternative. We could also use the possible number pattern to extract the possible lengths of + // the number to make this faster, but this method is only for unit-testing so simplicity is + // preferred to performance. We don't want to return a number that can't be parsed, so we check + // the number is long enough. We try all possible lengths because phone number plans often have + // overlapping prefixes so the number 123456 might be valid as a fixed-line number, and 12345 as + // a mobile number. It would be faster to loop in a different order, but we prefer numbers that + // look closer to real numbers (and it gives us a variety of different lengths for the resulting + // phone numbers - otherwise they would all be MIN_LENGTH_FOR_NSN digits long.) + for (int phoneNumberLength = exampleNumber.length() - 1; + phoneNumberLength >= MIN_LENGTH_FOR_NSN; + phoneNumberLength--) { + String numberToTry = exampleNumber.substring(0, phoneNumberLength); + try { + PhoneNumber possiblyValidNumber = parse(numberToTry, regionCode); + if (!isValidNumber(possiblyValidNumber)) { + return possiblyValidNumber; + } + } catch (NumberParseException e) { + // Shouldn't happen: we have already checked the length, we know example numbers have + // only valid digits, and we know the region code is fine. + } + } + // We have a test to check that this doesn't happen for any of our supported regions. + return null; + } + + /** + * Gets a valid number for the specified region and number type. + * + * @param regionCode the region for which an example number is needed + * @param type the type of number that is needed + * @return a valid number for the specified region and type. Returns null when the metadata + * does not contain such information or if an invalid region or region 001 was entered. + * For 001 (representing non-geographical numbers), call + * {@link #getExampleNumberForNonGeoEntity} instead. + */ + public PhoneNumber getExampleNumberForType(String regionCode, PhoneNumberType type) { + // Check the region code is valid. + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return null; + } + PhoneNumberDesc desc = getNumberDescByType(getMetadataForRegion(regionCode), type); + try { + if (desc.hasExampleNumber()) { + return parse(desc.getExampleNumber(), regionCode); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + return null; + } + + /** + * Gets a valid number for the specified number type (it may belong to any country). + * + * @param type the type of number that is needed + * @return a valid number for the specified type. Returns null when the metadata + * does not contain such information. This should only happen when no numbers of this type are + * allocated anywhere in the world anymore. + */ + public PhoneNumber getExampleNumberForType(PhoneNumberType type) { + for (String regionCode : getSupportedRegions()) { + PhoneNumber exampleNumber = getExampleNumberForType(regionCode, type); + if (exampleNumber != null) { + return exampleNumber; + } + } + // If there wasn't an example number for a region, try the non-geographical entities. + for (int countryCallingCode : getSupportedGlobalNetworkCallingCodes()) { + PhoneNumberDesc desc = getNumberDescByType( + getMetadataForNonGeographicalRegion(countryCallingCode), type); + try { + if (desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + } + // There are no example numbers of this type for any country in the library. + return null; + } + + /** + * Gets a valid number for the specified country calling code for a non-geographical entity. + * + * @param countryCallingCode the country calling code for a non-geographical entity + * @return a valid number for the non-geographical entity. Returns null when the metadata + * does not contain such information, or the country calling code passed in does not belong + * to a non-geographical entity. + */ + public PhoneNumber getExampleNumberForNonGeoEntity(int countryCallingCode) { + PhoneMetadata metadata = getMetadataForNonGeographicalRegion(countryCallingCode); + if (metadata != null) { + // For geographical entities, fixed-line data is always present. However, for non-geographical + // entities, this is not the case, so we have to go through different types to find the + // example number. We don't check fixed-line or personal number since they aren't used by + // non-geographical entities (if this changes, a unit-test will catch this.) + for (PhoneNumberDesc desc : Arrays.asList(metadata.getMobile(), metadata.getTollFree(), + metadata.getSharedCost(), metadata.getVoip(), metadata.getVoicemail(), + metadata.getUan(), metadata.getPremiumRate())) { + try { + if (desc != null && desc.hasExampleNumber()) { + return parse("+" + countryCallingCode + desc.getExampleNumber(), UNKNOWN_REGION); + } + } catch (NumberParseException e) { + logger.log(Level.SEVERE, e.toString()); + } + } + } else { + logger.log(Level.WARNING, + "Invalid or unknown country calling code provided: " + countryCallingCode); + } + return null; + } + + /** + * Appends the formatted extension of a phone number to formattedNumber, if the phone number had + * an extension specified. + */ + private void maybeAppendFormattedExtension(PhoneNumber number, PhoneMetadata metadata, + PhoneNumberFormat numberFormat, + StringBuilder formattedNumber) { + if (number.hasExtension() && number.getExtension().length() > 0) { + if (numberFormat == PhoneNumberFormat.RFC3966) { + formattedNumber.append(RFC3966_EXTN_PREFIX).append(number.getExtension()); + } else { + if (metadata.hasPreferredExtnPrefix()) { + formattedNumber.append(metadata.getPreferredExtnPrefix()).append(number.getExtension()); + } else { + formattedNumber.append(DEFAULT_EXTN_PREFIX).append(number.getExtension()); + } + } + } + } + + PhoneNumberDesc getNumberDescByType(PhoneMetadata metadata, PhoneNumberType type) { + switch (type) { + case PREMIUM_RATE: + return metadata.getPremiumRate(); + case TOLL_FREE: + return metadata.getTollFree(); + case MOBILE: + return metadata.getMobile(); + case FIXED_LINE: + case FIXED_LINE_OR_MOBILE: + return metadata.getFixedLine(); + case SHARED_COST: + return metadata.getSharedCost(); + case VOIP: + return metadata.getVoip(); + case PERSONAL_NUMBER: + return metadata.getPersonalNumber(); + case PAGER: + return metadata.getPager(); + case UAN: + return metadata.getUan(); + case VOICEMAIL: + return metadata.getVoicemail(); + default: + return metadata.getGeneralDesc(); + } + } + + /** + * Gets the type of a valid phone number. + * + * @param number the phone number that we want to know the type + * @return the type of the phone number, or UNKNOWN if it is invalid + */ + public PhoneNumberType getNumberType(PhoneNumber number) { + String regionCode = getRegionCodeForNumber(number); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(number.getCountryCode(), regionCode); + if (metadata == null) { + return PhoneNumberType.UNKNOWN; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return getNumberTypeHelper(nationalSignificantNumber, metadata); + } + + private PhoneNumberType getNumberTypeHelper(String nationalNumber, PhoneMetadata metadata) { + if (!isNumberMatchingDesc(nationalNumber, metadata.getGeneralDesc())) { + return PhoneNumberType.UNKNOWN; + } + + if (isNumberMatchingDesc(nationalNumber, metadata.getPremiumRate())) { + return PhoneNumberType.PREMIUM_RATE; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getTollFree())) { + return PhoneNumberType.TOLL_FREE; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getSharedCost())) { + return PhoneNumberType.SHARED_COST; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getVoip())) { + return PhoneNumberType.VOIP; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getPersonalNumber())) { + return PhoneNumberType.PERSONAL_NUMBER; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getPager())) { + return PhoneNumberType.PAGER; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getUan())) { + return PhoneNumberType.UAN; + } + if (isNumberMatchingDesc(nationalNumber, metadata.getVoicemail())) { + return PhoneNumberType.VOICEMAIL; + } + + boolean isFixedLine = isNumberMatchingDesc(nationalNumber, metadata.getFixedLine()); + if (isFixedLine) { + if (metadata.getSameMobileAndFixedLinePattern()) { + return PhoneNumberType.FIXED_LINE_OR_MOBILE; + } else if (isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { + return PhoneNumberType.FIXED_LINE_OR_MOBILE; + } + return PhoneNumberType.FIXED_LINE; + } + // Otherwise, test to see if the number is mobile. Only do this if certain that the patterns for + // mobile and fixed line aren't the same. + if (!metadata.getSameMobileAndFixedLinePattern() + && isNumberMatchingDesc(nationalNumber, metadata.getMobile())) { + return PhoneNumberType.MOBILE; + } + return PhoneNumberType.UNKNOWN; + } + + /** + * Returns the metadata for the given region code or {@code null} if the region code is invalid or + * unknown. + * + * @throws MissingMetadataException if the region code is valid, but metadata cannot be found. + */ + PhoneMetadata getMetadataForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + return null; + } + PhoneMetadata phoneMetadata = metadataSource.getMetadataForRegion(regionCode); + ensureMetadataIsNonNull(phoneMetadata, "Missing metadata for region code " + regionCode); + return phoneMetadata; + } + + /** + * Returns the metadata for the given country calling code or {@code null} if the country calling + * code is invalid or unknown. + * + * @throws MissingMetadataException if the country calling code is valid, but metadata cannot be + * found. + */ + PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { + if (!countryCodesForNonGeographicalRegion.contains(countryCallingCode)) { + return null; + } + PhoneMetadata phoneMetadata = metadataSource.getMetadataForNonGeographicalRegion( + countryCallingCode); + ensureMetadataIsNonNull(phoneMetadata, + "Missing metadata for country code " + countryCallingCode); + return phoneMetadata; + } + + private static void ensureMetadataIsNonNull(PhoneMetadata phoneMetadata, String message) { + if (phoneMetadata == null) { + throw new MissingMetadataException(message); + } + } + + boolean isNumberMatchingDesc(String nationalNumber, PhoneNumberDesc numberDesc) { + // Check if any possible number lengths are present; if so, we use them to avoid checking the + // validation pattern if they don't match. If they are absent, this means they match the general + // description, which we have already checked before checking a specific number type. + int actualLength = nationalNumber.length(); + List possibleLengths = numberDesc.getPossibleLengthList(); + if (possibleLengths.size() > 0 && !possibleLengths.contains(actualLength)) { + return false; + } + return matcherApi.matchNationalNumber(nationalNumber, numberDesc, false); + } + + /** + * Tests whether a phone number matches a valid pattern. Note this doesn't verify the number + * is actually in use, which is impossible to tell by just looking at a number itself. It only + * verifies whether the parsed, canonicalised number is valid: not whether a particular series of + * digits entered by the user is diallable from the region provided when parsing. For example, the + * number +41 (0) 78 927 2696 can be parsed into a number with country code "41" and national + * significant number "789272696". This is valid, while the original string is not diallable. + * + * @param number the phone number that we want to validate + * @return a boolean that indicates whether the number is of a valid pattern + */ + public boolean isValidNumber(PhoneNumber number) { + String regionCode = getRegionCodeForNumber(number); + return isValidNumberForRegion(number, regionCode); + } + + /** + * Tests whether a phone number is valid for a certain region. Note this doesn't verify the number + * is actually in use, which is impossible to tell by just looking at a number itself. If the + * country calling code is not the same as the country calling code for the region, this + * immediately exits with false. After this, the specific number pattern rules for the region are + * examined. This is useful for determining for example whether a particular number is valid for + * Canada, rather than just a valid NANPA number. + * Warning: In most cases, you want to use {@link #isValidNumber} instead. For example, this + * method will mark numbers from British Crown dependencies such as the Isle of Man as invalid for + * the region "GB" (United Kingdom), since it has its own region code, "IM", which may be + * undesirable. + * + * @param number the phone number that we want to validate + * @param regionCode the region that we want to validate the phone number for + * @return a boolean that indicates whether the number is of a valid pattern + */ + public boolean isValidNumberForRegion(PhoneNumber number, String regionCode) { + int countryCode = number.getCountryCode(); + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); + if ((metadata == null) + || (!REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode) + && countryCode != getCountryCodeForValidRegion(regionCode))) { + // Either the region code was invalid, or the country calling code for this number does not + // match that of the region code. + return false; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return getNumberTypeHelper(nationalSignificantNumber, metadata) != PhoneNumberType.UNKNOWN; + } + + /** + * Returns the region where a phone number is from. This could be used for geocoding at the region + * level. Only guarantees correct results for valid, full numbers (not short-codes, or invalid + * numbers). + * + * @param number the phone number whose origin we want to know + * @return the region where the phone number is from, or null if no region matches this calling + * code + */ + public String getRegionCodeForNumber(PhoneNumber number) { + int countryCode = number.getCountryCode(); + List regions = countryCallingCodeToRegionCodeMap.get(countryCode); + if (regions == null) { + logger.log(Level.INFO, "Missing/invalid country_code (" + countryCode + ")"); + return null; + } + if (regions.size() == 1) { + return regions.get(0); + } else { + return getRegionCodeForNumberFromRegionList(number, regions); + } + } + + private String getRegionCodeForNumberFromRegionList(PhoneNumber number, + List regionCodes) { + String nationalNumber = getNationalSignificantNumber(number); + for (String regionCode : regionCodes) { + // If leadingDigits is present, use this. Otherwise, do full validation. + // Metadata cannot be null because the region codes come from the country calling code map. + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata.hasLeadingDigits()) { + if (regexCache.getPatternForRegex(metadata.getLeadingDigits()) + .matcher(nationalNumber).lookingAt()) { + return regionCode; + } + } else if (getNumberTypeHelper(nationalNumber, metadata) != PhoneNumberType.UNKNOWN) { + return regionCode; + } + } + return null; + } + + /** + * Returns the region code that matches the specific country calling code. In the case of no + * region code being found, ZZ will be returned. In the case of multiple regions, the one + * designated in the metadata as the "main" region for this calling code will be returned. If the + * countryCallingCode entered is valid but doesn't match a specific region (such as in the case of + * non-geographical calling codes like 800) the value "001" will be returned (corresponding to + * the value for World in the UN M.49 schema). + */ + public String getRegionCodeForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return regionCodes == null ? UNKNOWN_REGION : regionCodes.get(0); + } + + /** + * Returns a list with the region codes that match the specific country calling code. For + * non-geographical country calling codes, the region code 001 is returned. Also, in the case + * of no region code being found, an empty list is returned. + */ + public List getRegionCodesForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return Collections.unmodifiableList(regionCodes == null ? new ArrayList(0) + : regionCodes); + } + + /** + * Returns the country calling code for a specific region. For example, this would be 1 for the + * United States, and 64 for New Zealand. + * + * @param regionCode the region that we want to get the country calling code for + * @return the country calling code for the region denoted by regionCode + */ + public int getCountryCodeForRegion(String regionCode) { + if (!isValidRegionCode(regionCode)) { + logger.log(Level.WARNING, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); + return 0; + } + return getCountryCodeForValidRegion(regionCode); + } + + /** + * Returns the country calling code for a specific region. For example, this would be 1 for the + * United States, and 64 for New Zealand. Assumes the region is already valid. + * + * @param regionCode the region that we want to get the country calling code for + * @return the country calling code for the region denoted by regionCode + * @throws IllegalArgumentException if the region is invalid + */ + private int getCountryCodeForValidRegion(String regionCode) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + throw new IllegalArgumentException("Invalid region code: " + regionCode); + } + return metadata.getCountryCode(); + } + + /** + * Returns the national dialling prefix for a specific region. For example, this would be 1 for + * the United States, and 0 for New Zealand. Set stripNonDigits to true to strip symbols like "~" + * (which indicates a wait for a dialling tone) from the prefix returned. If no national prefix is + * present, we return null. + * + *

Warning: Do not use this method for do-your-own formatting - for some regions, the + * national dialling prefix is used only for certain types of numbers. Use the library's + * formatting functions to prefix the national prefix when required. + * + * @param regionCode the region that we want to get the dialling prefix for + * @param stripNonDigits true to strip non-digits from the national dialling prefix + * @return the dialling prefix for the region denoted by regionCode + */ + public String getNddPrefixForRegion(String regionCode, boolean stripNonDigits) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + logger.log(Level.WARNING, + "Invalid or missing region code (" + + ((regionCode == null) ? "null" : regionCode) + + ") provided."); + return null; + } + String nationalPrefix = metadata.getNationalPrefix(); + // If no national prefix was found, we return null. + if (nationalPrefix.length() == 0) { + return null; + } + if (stripNonDigits) { + // Note: if any other non-numeric symbols are ever used in national prefixes, these would have + // to be removed here as well. + nationalPrefix = nationalPrefix.replace("~", ""); + } + return nationalPrefix; + } + + /** + * Checks if this is a region under the North American Numbering Plan Administration (NANPA). + * + * @return true if regionCode is one of the regions under NANPA + */ + public boolean isNANPACountry(String regionCode) { + return nanpaRegions.contains(regionCode); + } + + /** + * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. A valid vanity + * number will start with at least 3 digits and will have three or more alpha characters. This + * does not do region-specific checks - to work out if this number is actually valid for a region, + * it should be parsed and methods such as {@link #isPossibleNumberWithReason} and + * {@link #isValidNumber} should be used. + * + * @param number the number that needs to be checked + * @return true if the number is a valid vanity number + */ + public boolean isAlphaNumber(CharSequence number) { + if (!isViablePhoneNumber(number)) { + // Number is too short, or doesn't match the basic phone number pattern. + return false; + } + StringBuilder strippedNumber = new StringBuilder(number); + maybeStripExtension(strippedNumber); + return VALID_ALPHA_PHONE_PATTERN.matcher(strippedNumber).matches(); + } + + /** + * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of returning the reason + * for failure, this method returns true if the number is either a possible fully-qualified number + * (containing the area code and country code), or if the number could be a possible local number + * (with a country code, but missing an area code). Local numbers are considered possible if they + * could be possibly dialled in this format: if the area code is needed for a call to connect, the + * number is not considered possible without it. + * + * @param number the number that needs to be checked + * @return true if the number is possible + */ + public boolean isPossibleNumber(PhoneNumber number) { + ValidationResult result = isPossibleNumberWithReason(number); + return result == ValidationResult.IS_POSSIBLE + || result == ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + /** + * Convenience wrapper around {@link #isPossibleNumberForTypeWithReason}. Instead of returning the + * reason for failure, this method returns true if the number is either a possible fully-qualified + * number (containing the area code and country code), or if the number could be a possible local + * number (with a country code, but missing an area code). Local numbers are considered possible + * if they could be possibly dialled in this format: if the area code is needed for a call to + * connect, the number is not considered possible without it. + * + * @param number the number that needs to be checked + * @param type the type we are interested in + * @return true if the number is possible for this particular type + */ + public boolean isPossibleNumberForType(PhoneNumber number, PhoneNumberType type) { + ValidationResult result = isPossibleNumberForTypeWithReason(number, type); + return result == ValidationResult.IS_POSSIBLE + || result == ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + /** + * Helper method to check a number against possible lengths for this region, based on the metadata + * being passed in, and determine whether it matches, or is too short or too long. + */ + private ValidationResult testNumberLength(CharSequence number, PhoneMetadata metadata) { + return testNumberLength(number, metadata, PhoneNumberType.UNKNOWN); + } + + /** + * Helper method to check a number against possible lengths for this number type, and determine + * whether it matches, or is too short or too long. + */ + private ValidationResult testNumberLength( + CharSequence number, PhoneMetadata metadata, PhoneNumberType type) { + PhoneNumberDesc descForType = getNumberDescByType(metadata, type); + // There should always be "possibleLengths" set for every element. This is declared in the XML + // schema which is verified by PhoneNumberMetadataSchemaTest. + // For size efficiency, where a sub-description (e.g. fixed-line) has the same possibleLengths + // as the parent, this is missing, so we fall back to the general desc (where no numbers of the + // type exist at all, there is one possible length (-1) which is guaranteed not to match the + // length of any real phone number). + List possibleLengths = descForType.getPossibleLengthList().isEmpty() + ? metadata.getGeneralDesc().getPossibleLengthList() : descForType.getPossibleLengthList(); + + List localLengths = descForType.getPossibleLengthLocalOnlyList(); + + if (type == PhoneNumberType.FIXED_LINE_OR_MOBILE) { + if (!descHasPossibleNumberData(getNumberDescByType(metadata, PhoneNumberType.FIXED_LINE))) { + // The rare case has been encountered where no fixedLine data is available (true for some + // non-geographical entities), so we just check mobile. + return testNumberLength(number, metadata, PhoneNumberType.MOBILE); + } else { + PhoneNumberDesc mobileDesc = getNumberDescByType(metadata, PhoneNumberType.MOBILE); + if (descHasPossibleNumberData(mobileDesc)) { + // Merge the mobile data in if there was any. We have to make a copy to do this. + possibleLengths = new ArrayList<>(possibleLengths); + // Note that when adding the possible lengths from mobile, we have to again check they + // aren't empty since if they are this indicates they are the same as the general desc and + // should be obtained from there. + possibleLengths.addAll(mobileDesc.getPossibleLengthCount() == 0 + ? metadata.getGeneralDesc().getPossibleLengthList() + : mobileDesc.getPossibleLengthList()); + // The current list is sorted; we need to merge in the new list and re-sort (duplicates + // are okay). Sorting isn't so expensive because the lists are very small. + Collections.sort(possibleLengths); + + if (localLengths.isEmpty()) { + localLengths = mobileDesc.getPossibleLengthLocalOnlyList(); + } else { + localLengths = new ArrayList<>(localLengths); + localLengths.addAll(mobileDesc.getPossibleLengthLocalOnlyList()); + Collections.sort(localLengths); + } + } + } + } + + // If the type is not supported at all (indicated by the possible lengths containing -1 at this + // point) we return invalid length. + if (possibleLengths.get(0) == -1) { + return ValidationResult.INVALID_LENGTH; + } + + int actualLength = number.length(); + // This is safe because there is never an overlap beween the possible lengths and the local-only + // lengths; this is checked at build time. + if (localLengths.contains(actualLength)) { + return ValidationResult.IS_POSSIBLE_LOCAL_ONLY; + } + + int minimumLength = possibleLengths.get(0); + if (minimumLength == actualLength) { + return ValidationResult.IS_POSSIBLE; + } else if (minimumLength > actualLength) { + return ValidationResult.TOO_SHORT; + } else if (possibleLengths.get(possibleLengths.size() - 1) < actualLength) { + return ValidationResult.TOO_LONG; + } + // We skip the first element; we've already checked it. + return possibleLengths.subList(1, possibleLengths.size()).contains(actualLength) + ? ValidationResult.IS_POSSIBLE : ValidationResult.INVALID_LENGTH; + } + + /** + * Check whether a phone number is a possible number. It provides a more lenient check than + * {@link #isValidNumber} in the following sense: + *

    + *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting + * digits of the number. + *
  2. It doesn't attempt to figure out the type of the number, but uses general rules which + * applies to all types of phone numbers in a region. Therefore, it is much faster than + * isValidNumber. + *
  3. For some numbers (particularly fixed-line), many regions have the concept of area code, + * which together with subscriber number constitute the national significant number. It is + * sometimes okay to dial only the subscriber number when dialing in the same area. This + * function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is + * passed in. On the other hand, because isValidNumber validates using information on both + * starting digits (for fixed line numbers, that would most likely be area codes) and + * length (obviously includes the length of area codes for fixed line numbers), it will + * return false for the subscriber-number-only version. + *
+ * + *

There is a known issue with this + * method: if a number is possible only in a certain region among several regions that share the + * same country calling code, this method will consider only the "main" region. For example, + * +1310xxxx are valid numbers in Canada. However, they are not possible in the US. As a result, + * this method will return IS_POSSIBLE_LOCAL_ONLY for +1310xxxx. + * + * @param number the number that needs to be checked + * @return a ValidationResult object which indicates whether the number is possible + */ + public ValidationResult isPossibleNumberWithReason(PhoneNumber number) { + return isPossibleNumberForTypeWithReason(number, PhoneNumberType.UNKNOWN); + } + + /** + * Check whether a phone number is a possible number of a particular type. For types that don't + * exist in a particular region, this will return a result that isn't so useful; it is recommended + * that you use {@link #getSupportedTypesForRegion} or {@link #getSupportedTypesForNonGeoEntity} + * respectively before calling this method to determine whether you should call it for this number + * at all. + * + * This provides a more lenient check than {@link #isValidNumber} in the following sense: + * + *

    + *
  1. It only checks the length of phone numbers. In particular, it doesn't check starting + * digits of the number. + *
  2. For some numbers (particularly fixed-line), many regions have the concept of area code, + * which together with subscriber number constitute the national significant number. It is + * sometimes okay to dial only the subscriber number when dialing in the same area. This + * function will return IS_POSSIBLE_LOCAL_ONLY if the subscriber-number-only version is + * passed in. On the other hand, because isValidNumber validates using information on both + * starting digits (for fixed line numbers, that would most likely be area codes) and + * length (obviously includes the length of area codes for fixed line numbers), it will + * return false for the subscriber-number-only version. + *
+ * + *

There is a known issue with this + * method: if a number is possible only in a certain region among several regions that share the + * same country calling code, this method will consider only the "main" region. For example, + * +1310xxxx are valid numbers in Canada. However, they are not possible in the US. As a result, + * this method will return IS_POSSIBLE_LOCAL_ONLY for +1310xxxx. + * + * @param number the number that needs to be checked + * @param type the type we are interested in + * @return a ValidationResult object which indicates whether the number is possible + */ + public ValidationResult isPossibleNumberForTypeWithReason( + PhoneNumber number, PhoneNumberType type) { + String nationalNumber = getNationalSignificantNumber(number); + int countryCode = number.getCountryCode(); + // Note: For regions that share a country calling code, like NANPA numbers, we just use the + // rules from the default region (US in this case) since the getRegionCodeForNumber will not + // work if the number is possible but not valid. There is in fact one country calling code (290) + // where the possible number pattern differs between various regions (Saint Helena and Tristan + // da Cuñha), but this is handled by putting all possible lengths for any country with this + // country calling code in the metadata for the default region in this case. + if (!hasValidCountryCallingCode(countryCode)) { + return ValidationResult.INVALID_COUNTRY_CODE; + } + String regionCode = getRegionCodeForCountryCode(countryCode); + // Metadata cannot be null because the country calling code is valid. + PhoneMetadata metadata = getMetadataForRegionOrCallingCode(countryCode, regionCode); + return testNumberLength(nationalNumber, metadata, type); + } + + /** + * Check whether a phone number is a possible number given a number in the form of a string, and + * the region where the number could be dialed from. It provides a more lenient check than + * {@link #isValidNumber}. See {@link #isPossibleNumber(PhoneNumber)} for details. + * + *

This method first parses the number, then invokes {@link #isPossibleNumber(PhoneNumber)} + * with the resultant PhoneNumber object. + * + * @param number the number that needs to be checked + * @param regionDialingFrom the region that we are expecting the number to be dialed from. + * Note this is different from the region where the number belongs. For example, the number + * +1 650 253 0000 is a number that belongs to US. When written in this form, it can be + * dialed from any region. When it is written as 00 1 650 253 0000, it can be dialed from any + * region which uses an international dialling prefix of 00. When it is written as + * 650 253 0000, it can only be dialed from within the US, and when written as 253 0000, it + * can only be dialed from within a smaller area in the US (Mountain View, CA, to be more + * specific). + * @return true if the number is possible + */ + public boolean isPossibleNumber(CharSequence number, String regionDialingFrom) { + try { + return isPossibleNumber(parse(number, regionDialingFrom)); + } catch (NumberParseException e) { + return false; + } + } + + /** + * Attempts to extract a valid number from a phone number that is too long to be valid, and resets + * the PhoneNumber object passed in to that valid version. If no valid number could be extracted, + * the PhoneNumber object passed in will not be modified. + * @param number a PhoneNumber object which contains a number that is too long to be valid + * @return true if a valid phone number can be successfully extracted + */ + public boolean truncateTooLongNumber(PhoneNumber number) { + if (isValidNumber(number)) { + return true; + } + PhoneNumber numberCopy = new PhoneNumber(); + numberCopy.mergeFrom(number); + long nationalNumber = number.getNationalNumber(); + do { + nationalNumber /= 10; + numberCopy.setNationalNumber(nationalNumber); + if (isPossibleNumberWithReason(numberCopy) == ValidationResult.TOO_SHORT + || nationalNumber == 0) { + return false; + } + } while (!isValidNumber(numberCopy)); + number.setNationalNumber(nationalNumber); + return true; + } + + /** + * Gets an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} for the specific region. + * + * @param regionCode the region where the phone number is being entered + * @return an {@link com.google.i18n.phonenumbers.AsYouTypeFormatter} object, which can be used + * to format phone numbers in the specific region "as you type" + */ + public AsYouTypeFormatter getAsYouTypeFormatter(String regionCode) { + return new AsYouTypeFormatter(regionCode); + } + + // Extracts country calling code from fullNumber, returns it and places the remaining number in + // nationalNumber. It assumes that the leading plus sign or IDD has already been removed. Returns + // 0 if fullNumber doesn't start with a valid country calling code, and leaves nationalNumber + // unmodified. + int extractCountryCode(StringBuilder fullNumber, StringBuilder nationalNumber) { + if ((fullNumber.length() == 0) || (fullNumber.charAt(0) == '0')) { + // Country codes do not begin with a '0'. + return 0; + } + int potentialCountryCode; + int numberLength = fullNumber.length(); + for (int i = 1; i <= MAX_LENGTH_COUNTRY_CODE && i <= numberLength; i++) { + potentialCountryCode = Integer.parseInt(fullNumber.substring(0, i)); + if (countryCallingCodeToRegionCodeMap.containsKey(potentialCountryCode)) { + nationalNumber.append(fullNumber.substring(i)); + return potentialCountryCode; + } + } + return 0; + } + + /** + * Tries to extract a country calling code from a number. This method will return zero if no + * country calling code is considered to be present. Country calling codes are extracted in the + * following ways: + *

    + *
  • by stripping the international dialing prefix of the region the person is dialing from, + * if this is present in the number, and looking at the next digits + *
  • by stripping the '+' sign if present and then looking at the next digits + *
  • by comparing the start of the number and the country calling code of the default region. + * If the number is not considered possible for the numbering plan of the default region + * initially, but starts with the country calling code of this region, validation will be + * reattempted after stripping this country calling code. If this number is considered a + * possible number, then the first digits will be considered the country calling code and + * removed as such. + *
+ * It will throw a NumberParseException if the number starts with a '+' but the country calling + * code supplied after this does not match that of any known region. + * + * @param number non-normalized telephone number that we wish to extract a country calling + * code from - may begin with '+' + * @param defaultRegionMetadata metadata about the region this number may be from + * @param nationalNumber a string buffer to store the national significant number in, in the case + * that a country calling code was extracted. The number is appended to any existing contents. + * If no country calling code was extracted, this will be left unchanged. + * @param keepRawInput true if the country_code_source and preferred_carrier_code fields of + * phoneNumber should be populated. + * @param phoneNumber the PhoneNumber object where the country_code and country_code_source need + * to be populated. Note the country_code is always populated, whereas country_code_source is + * only populated when keepCountryCodeSource is true. + * @return the country calling code extracted or 0 if none could be extracted + */ + // @VisibleForTesting + int maybeExtractCountryCode(CharSequence number, PhoneMetadata defaultRegionMetadata, + StringBuilder nationalNumber, boolean keepRawInput, + PhoneNumber phoneNumber) + throws NumberParseException { + if (number.length() == 0) { + return 0; + } + StringBuilder fullNumber = new StringBuilder(number); + // Set the default prefix to be something that will never match. + String possibleCountryIddPrefix = "NonMatch"; + if (defaultRegionMetadata != null) { + possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix(); + } + + CountryCodeSource countryCodeSource = + maybeStripInternationalPrefixAndNormalize(fullNumber, possibleCountryIddPrefix); + if (keepRawInput) { + phoneNumber.setCountryCodeSource(countryCodeSource); + } + if (countryCodeSource != CountryCodeSource.FROM_DEFAULT_COUNTRY) { + if (fullNumber.length() <= MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_AFTER_IDD, + "Phone number had an IDD, but after this was not " + + "long enough to be a viable phone number."); + } + int potentialCountryCode = extractCountryCode(fullNumber, nationalNumber); + if (potentialCountryCode != 0) { + phoneNumber.setCountryCode(potentialCountryCode); + return potentialCountryCode; + } + + // If this fails, they must be using a strange country calling code that we don't recognize, + // or that doesn't exist. + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Country calling code supplied was not recognised."); + } else if (defaultRegionMetadata != null) { + // Check to see if the number starts with the country calling code for the default region. If + // so, we remove the country calling code, and do some checks on the validity of the number + // before and after. + int defaultCountryCode = defaultRegionMetadata.getCountryCode(); + String defaultCountryCodeString = String.valueOf(defaultCountryCode); + String normalizedNumber = fullNumber.toString(); + if (normalizedNumber.startsWith(defaultCountryCodeString)) { + StringBuilder potentialNationalNumber = + new StringBuilder(normalizedNumber.substring(defaultCountryCodeString.length())); + PhoneNumberDesc generalDesc = defaultRegionMetadata.getGeneralDesc(); + maybeStripNationalPrefixAndCarrierCode( + potentialNationalNumber, defaultRegionMetadata, null /* Don't need the carrier code */); + // If the number was not valid before but is valid now, or if it was too long before, we + // consider the number with the country calling code stripped to be a better result and + // keep that instead. + if ((!matcherApi.matchNationalNumber(fullNumber, generalDesc, false) + && matcherApi.matchNationalNumber(potentialNationalNumber, generalDesc, false)) + || testNumberLength(fullNumber, defaultRegionMetadata) == ValidationResult.TOO_LONG) { + nationalNumber.append(potentialNationalNumber); + if (keepRawInput) { + phoneNumber.setCountryCodeSource(CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN); + } + phoneNumber.setCountryCode(defaultCountryCode); + return defaultCountryCode; + } + } + } + // No country calling code present. + phoneNumber.setCountryCode(0); + return 0; + } + + /** + * Strips the IDD from the start of the number if present. Helper function used by + * maybeStripInternationalPrefixAndNormalize. + */ + private boolean parsePrefixAsIdd(Pattern iddPattern, StringBuilder number) { + Matcher m = iddPattern.matcher(number); + if (m.lookingAt()) { + int matchEnd = m.end(); + // Only strip this if the first digit after the match is not a 0, since country calling codes + // cannot begin with 0. + Matcher digitMatcher = CAPTURING_DIGIT_PATTERN.matcher(number.substring(matchEnd)); + if (digitMatcher.find()) { + String normalizedGroup = normalizeDigitsOnly(digitMatcher.group(1)); + if (normalizedGroup.equals("0")) { + return false; + } + } + number.delete(0, matchEnd); + return true; + } + return false; + } + + /** + * Strips any international prefix (such as +, 00, 011) present in the number provided, normalizes + * the resulting number, and indicates if an international prefix was present. + * + * @param number the non-normalized telephone number that we wish to strip any international + * dialing prefix from + * @param possibleIddPrefix the international direct dialing prefix from the region we + * think this number may be dialed in + * @return the corresponding CountryCodeSource if an international dialing prefix could be + * removed from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if the number did + * not seem to be in international format + */ + // @VisibleForTesting + CountryCodeSource maybeStripInternationalPrefixAndNormalize( + StringBuilder number, + String possibleIddPrefix) { + if (number.length() == 0) { + return CountryCodeSource.FROM_DEFAULT_COUNTRY; + } + // Check to see if the number begins with one or more plus signs. + Matcher m = PLUS_CHARS_PATTERN.matcher(number); + if (m.lookingAt()) { + number.delete(0, m.end()); + // Can now normalize the rest of the number since we've consumed the "+" sign at the start. + normalize(number); + return CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN; + } + // Attempt to parse the first digits as an international prefix. + Pattern iddPattern = regexCache.getPatternForRegex(possibleIddPrefix); + normalize(number); + return parsePrefixAsIdd(iddPattern, number) + ? CountryCodeSource.FROM_NUMBER_WITH_IDD + : CountryCodeSource.FROM_DEFAULT_COUNTRY; + } + + /** + * Strips any national prefix (such as 0, 1) present in the number provided. + * + * @param number the normalized telephone number that we wish to strip any national + * dialing prefix from + * @param metadata the metadata for the region that we think this number is from + * @param carrierCode a place to insert the carrier code if one is extracted + * @return true if a national prefix or carrier code (or both) could be extracted + */ + // @VisibleForTesting + boolean maybeStripNationalPrefixAndCarrierCode( + StringBuilder number, PhoneMetadata metadata, StringBuilder carrierCode) { + int numberLength = number.length(); + String possibleNationalPrefix = metadata.getNationalPrefixForParsing(); + if (numberLength == 0 || possibleNationalPrefix.length() == 0) { + // Early return for numbers of zero length. + return false; + } + // Attempt to parse the first digits as a national prefix. + Matcher prefixMatcher = regexCache.getPatternForRegex(possibleNationalPrefix).matcher(number); + if (prefixMatcher.lookingAt()) { + PhoneNumberDesc generalDesc = metadata.getGeneralDesc(); + // Check if the original number is viable. + boolean isViableOriginalNumber = matcherApi.matchNationalNumber(number, generalDesc, false); + // prefixMatcher.group(numOfGroups) == null implies nothing was captured by the capturing + // groups in possibleNationalPrefix; therefore, no transformation is necessary, and we just + // remove the national prefix. + int numOfGroups = prefixMatcher.groupCount(); + String transformRule = metadata.getNationalPrefixTransformRule(); + if (transformRule == null || transformRule.length() == 0 + || prefixMatcher.group(numOfGroups) == null) { + // If the original number was viable, and the resultant number is not, we return. + if (isViableOriginalNumber + && !matcherApi.matchNationalNumber( + number.substring(prefixMatcher.end()), generalDesc, false)) { + return false; + } + if (carrierCode != null && numOfGroups > 0 && prefixMatcher.group(numOfGroups) != null) { + carrierCode.append(prefixMatcher.group(1)); + } + number.delete(0, prefixMatcher.end()); + return true; + } else { + // Check that the resultant number is still viable. If not, return. Check this by copying + // the string buffer and making the transformation on the copy first. + StringBuilder transformedNumber = new StringBuilder(number); + transformedNumber.replace(0, numberLength, prefixMatcher.replaceFirst(transformRule)); + if (isViableOriginalNumber + && !matcherApi.matchNationalNumber(transformedNumber.toString(), generalDesc, false)) { + return false; + } + if (carrierCode != null && numOfGroups > 1) { + carrierCode.append(prefixMatcher.group(1)); + } + number.replace(0, number.length(), transformedNumber.toString()); + return true; + } + } + return false; + } + + /** + * Strips any extension (as in, the part of the number dialled after the call is connected, + * usually indicated with extn, ext, x or similar) from the end of the number, and returns it. + * + * @param number the non-normalized telephone number that we wish to strip the extension from + * @return the phone extension + */ + // @VisibleForTesting + String maybeStripExtension(StringBuilder number) { + Matcher m = EXTN_PATTERN.matcher(number); + // If we find a potential extension, and the number preceding this is a viable number, we assume + // it is an extension. + if (m.find() && isViablePhoneNumber(number.substring(0, m.start()))) { + // The numbers are captured into groups in the regular expression. + for (int i = 1, length = m.groupCount(); i <= length; i++) { + if (m.group(i) != null) { + // We go through the capturing groups until we find one that captured some digits. If none + // did, then we will return the empty string. + String extension = m.group(i); + number.delete(m.start(), number.length()); + return extension; + } + } + } + return ""; + } + + /** + * Checks to see that the region code used is valid, or if it is not valid, that the number to + * parse starts with a + symbol so that we can attempt to infer the region from the number. + * Returns false if it cannot use the region provided and the region cannot be inferred. + */ + private boolean checkRegionForParsing(CharSequence numberToParse, String defaultRegion) { + if (!isValidRegionCode(defaultRegion)) { + // If the number is null or empty, we can't infer the region. + if ((numberToParse == null) || (numberToParse.length() == 0) + || !PLUS_CHARS_PATTERN.matcher(numberToParse).lookingAt()) { + return false; + } + } + return true; + } + + /** + * Parses a string and returns it as a phone number in proto buffer format. The method is quite + * lenient and looks for a number in the input text (raw input) and does not check whether the + * string is definitely only a phone number. To do this, it ignores punctuation and white-space, + * as well as any text before the number (e.g. a leading "Tel: ") and trims the non-number bits. + * It will accept a number in any format (E164, national, international etc), assuming it can be + * interpreted with the defaultRegion supplied. It also attempts to convert any alpha characters + * into digits if it thinks this is a vanity number of the type "1800 MICROSOFT". + * + *

This method will throw a {@link com.google.i18n.phonenumbers.NumberParseException} if the + * number is not considered to be a possible number. Note that validation of whether the number + * is actually a valid number for a particular region is not performed. This can be done + * separately with {@link #isValidNumber}. + * + *

Note this method canonicalizes the phone number such that different representations can be + * easily compared, no matter what form it was originally entered in (e.g. national, + * international). If you want to record context about the number being parsed, such as the raw + * input that was entered, how the country code was derived etc. then call {@link + * #parseAndKeepRawInput} instead. + * + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. It can also be provided in RFC3966 + * format. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. If the number + * is guaranteed to start with a '+' followed by the country calling code, then RegionCode.ZZ + * or null can be supplied. + * @return a phone number proto buffer filled with the parsed number + * @throws NumberParseException if the string is not considered to be a viable phone number (e.g. + * too few or too many digits) or if no default region was supplied and the number is not in + * international format (does not start with +) + */ + public PhoneNumber parse(CharSequence numberToParse, String defaultRegion) + throws NumberParseException { + PhoneNumber phoneNumber = new PhoneNumber(); + parse(numberToParse, defaultRegion, phoneNumber); + return phoneNumber; + } + + /** + * Same as {@link #parse(CharSequence, String)}, but accepts mutable PhoneNumber as a + * parameter to decrease object creation when invoked many times. + */ + public void parse(CharSequence numberToParse, String defaultRegion, PhoneNumber phoneNumber) + throws NumberParseException { + parseHelper(numberToParse, defaultRegion, false, true, phoneNumber); + } + + /** + * Parses a string and returns it in proto buffer format. This method differs from {@link #parse} + * in that it always populates the raw_input field of the protocol buffer with numberToParse as + * well as the country_code_source field. + * + * @param numberToParse number that we are attempting to parse. This can contain formatting such + * as +, ( and -, as well as a phone number extension. + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country calling code + * for the number in this case would be stored as that of the default region supplied. + * @return a phone number proto buffer filled with the parsed number + * @throws NumberParseException if the string is not considered to be a viable phone number or if + * no default region was supplied + */ + public PhoneNumber parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion) + throws NumberParseException { + PhoneNumber phoneNumber = new PhoneNumber(); + parseAndKeepRawInput(numberToParse, defaultRegion, phoneNumber); + return phoneNumber; + } + + /** + * Same as{@link #parseAndKeepRawInput(CharSequence, String)}, but accepts a mutable + * PhoneNumber as a parameter to decrease object creation when invoked many times. + */ + public void parseAndKeepRawInput(CharSequence numberToParse, String defaultRegion, + PhoneNumber phoneNumber) + throws NumberParseException { + parseHelper(numberToParse, defaultRegion, true, true, phoneNumber); + } + + /** + * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. This + * is a shortcut for {@link #findNumbers(CharSequence, String, Leniency, long) + * getMatcher(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE)}. + * + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. + */ + public Iterable findNumbers(CharSequence text, String defaultRegion) { + return findNumbers(text, defaultRegion, Leniency.VALID, Long.MAX_VALUE); + } + + /** + * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. + * + * @param text the text to search for phone numbers, null for no text + * @param defaultRegion region that we are expecting the number to be from. This is only used if + * the number being parsed is not written in international format. The country_code for the + * number in this case would be stored as that of the default region supplied. May be null if + * only international numbers are expected. + * @param leniency the leniency to use when evaluating candidate phone numbers + * @param maxTries the maximum number of invalid numbers to try before giving up on the text. + * This is to cover degenerate cases where the text has a lot of false positives in it. Must + * be {@code >= 0}. + */ + public Iterable findNumbers( + final CharSequence text, final String defaultRegion, final Leniency leniency, + final long maxTries) { + + return new Iterable() { + @Override + public Iterator iterator() { + return new PhoneNumberMatcher( + PhoneNumberUtil.this, text, defaultRegion, leniency, maxTries); + } + }; + } + + /** + * A helper function to set the values related to leading zeros in a PhoneNumber. + */ + static void setItalianLeadingZerosForPhoneNumber(CharSequence nationalNumber, + PhoneNumber phoneNumber) { + if (nationalNumber.length() > 1 && nationalNumber.charAt(0) == '0') { + phoneNumber.setItalianLeadingZero(true); + int numberOfLeadingZeros = 1; + // Note that if the national number is all "0"s, the last "0" is not counted as a leading + // zero. + while (numberOfLeadingZeros < nationalNumber.length() - 1 + && nationalNumber.charAt(numberOfLeadingZeros) == '0') { + numberOfLeadingZeros++; + } + if (numberOfLeadingZeros != 1) { + phoneNumber.setNumberOfLeadingZeros(numberOfLeadingZeros); + } + } + } + + /** + * Parses a string and fills up the phoneNumber. This method is the same as the public + * parse() method, with the exception that it allows the default region to be null, for use by + * isNumberMatch(). checkRegion should be set to false if it is permitted for the default region + * to be null or unknown ("ZZ"). + * + * Note if any new field is added to this method that should always be filled in, even when + * keepRawInput is false, it should also be handled in the copyCoreFieldsOnly() method. + */ + private void parseHelper(CharSequence numberToParse, String defaultRegion, + boolean keepRawInput, boolean checkRegion, PhoneNumber phoneNumber) + throws NumberParseException { + if (numberToParse == null) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The phone number supplied was null."); + } else if (numberToParse.length() > MAX_INPUT_STRING_LENGTH) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG, + "The string supplied was too long to parse."); + } + + StringBuilder nationalNumber = new StringBuilder(); + String numberBeingParsed = numberToParse.toString(); + buildNationalNumberForParsing(numberBeingParsed, nationalNumber); + + if (!isViablePhoneNumber(nationalNumber)) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The string supplied did not seem to be a phone number."); + } + + // Check the region supplied is valid, or that the extracted number starts with some sort of + + // sign so the number's region can be determined. + if (checkRegion && !checkRegionForParsing(nationalNumber, defaultRegion)) { + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Missing or invalid default region."); + } + + if (keepRawInput) { + phoneNumber.setRawInput(numberBeingParsed); + } + // Attempt to parse extension first, since it doesn't require region-specific data and we want + // to have the non-normalised number here. + String extension = maybeStripExtension(nationalNumber); + if (extension.length() > 0) { + phoneNumber.setExtension(extension); + } + + PhoneMetadata regionMetadata = getMetadataForRegion(defaultRegion); + // Check to see if the number is given in international format so we know whether this number is + // from the default region or not. + StringBuilder normalizedNationalNumber = new StringBuilder(); + int countryCode = 0; + try { + // TODO: This method should really just take in the string buffer that has already + // been created, and just remove the prefix, rather than taking in a string and then + // outputting a string buffer. + countryCode = maybeExtractCountryCode(nationalNumber, regionMetadata, + normalizedNationalNumber, keepRawInput, phoneNumber); + } catch (NumberParseException e) { + Matcher matcher = PLUS_CHARS_PATTERN.matcher(nationalNumber); + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE + && matcher.lookingAt()) { + // Strip the plus-char, and try again. + countryCode = maybeExtractCountryCode(nationalNumber.substring(matcher.end()), + regionMetadata, normalizedNationalNumber, + keepRawInput, phoneNumber); + if (countryCode == 0) { + throw new NumberParseException(NumberParseException.ErrorType.INVALID_COUNTRY_CODE, + "Could not interpret numbers after plus-sign."); + } + } else { + throw new NumberParseException(e.getErrorType(), e.getMessage()); + } + } + if (countryCode != 0) { + String phoneNumberRegion = getRegionCodeForCountryCode(countryCode); + if (!phoneNumberRegion.equals(defaultRegion)) { + // Metadata cannot be null because the country calling code is valid. + regionMetadata = getMetadataForRegionOrCallingCode(countryCode, phoneNumberRegion); + } + } else { + // If no extracted country calling code, use the region supplied instead. The national number + // is just the normalized version of the number we were given to parse. + normalizedNationalNumber.append(normalize(nationalNumber)); + if (defaultRegion != null) { + countryCode = regionMetadata.getCountryCode(); + phoneNumber.setCountryCode(countryCode); + } else if (keepRawInput) { + phoneNumber.clearCountryCodeSource(); + } + } + if (normalizedNationalNumber.length() < MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN, + "The string supplied is too short to be a phone number."); + } + if (regionMetadata != null) { + StringBuilder carrierCode = new StringBuilder(); + StringBuilder potentialNationalNumber = new StringBuilder(normalizedNationalNumber); + maybeStripNationalPrefixAndCarrierCode(potentialNationalNumber, regionMetadata, carrierCode); + // We require that the NSN remaining after stripping the national prefix and carrier code be + // long enough to be a possible length for the region. Otherwise, we don't do the stripping, + // since the original number could be a valid short number. + ValidationResult validationResult = testNumberLength(potentialNationalNumber, regionMetadata); + if (validationResult != ValidationResult.TOO_SHORT + && validationResult != ValidationResult.IS_POSSIBLE_LOCAL_ONLY + && validationResult != ValidationResult.INVALID_LENGTH) { + normalizedNationalNumber = potentialNationalNumber; + if (keepRawInput && carrierCode.length() > 0) { + phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString()); + } + } + } + int lengthOfNationalNumber = normalizedNationalNumber.length(); + if (lengthOfNationalNumber < MIN_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_SHORT_NSN, + "The string supplied is too short to be a phone number."); + } + if (lengthOfNationalNumber > MAX_LENGTH_FOR_NSN) { + throw new NumberParseException(NumberParseException.ErrorType.TOO_LONG, + "The string supplied is too long to be a phone number."); + } + setItalianLeadingZerosForPhoneNumber(normalizedNationalNumber, phoneNumber); + phoneNumber.setNationalNumber(Long.parseLong(normalizedNationalNumber.toString())); + } + + /** + * Extracts the value of the phone-context parameter of numberToExtractFrom where the index of + * ";phone-context=" is the parameter indexOfPhoneContext, following the syntax defined in + * RFC3966. + * + * @return the extracted string (possibly empty), or null if no phone-context parameter is found. + */ + private String extractPhoneContext(String numberToExtractFrom, int indexOfPhoneContext) { + // If no phone-context parameter is present + if (indexOfPhoneContext == -1) { + return null; + } + + int phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT.length(); + // If phone-context parameter is empty + if (phoneContextStart >= numberToExtractFrom.length()) { + return ""; + } + + int phoneContextEnd = numberToExtractFrom.indexOf(';', phoneContextStart); + // If phone-context is not the last parameter + if (phoneContextEnd != -1) { + return numberToExtractFrom.substring(phoneContextStart, phoneContextEnd); + } else { + return numberToExtractFrom.substring(phoneContextStart); + } + } + + /** + * Returns whether the value of phoneContext follows the syntax defined in RFC3966. + */ + private boolean isPhoneContextValid(String phoneContext) { + if (phoneContext == null) { + return true; + } + if (phoneContext.length() == 0) { + return false; + } + + // Does phone-context value match pattern of global-number-digits or domainname + return RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN.matcher(phoneContext).matches() + || RFC3966_DOMAINNAME_PATTERN.matcher(phoneContext).matches(); + } + + /** + * Converts numberToParse to a form that we can parse and write it to nationalNumber if it is + * written in RFC3966; otherwise extract a possible number out of it and write to nationalNumber. + */ + private void buildNationalNumberForParsing(String numberToParse, StringBuilder nationalNumber) + throws NumberParseException { + int indexOfPhoneContext = numberToParse.indexOf(RFC3966_PHONE_CONTEXT); + + String phoneContext = extractPhoneContext(numberToParse, indexOfPhoneContext); + if (!isPhoneContextValid(phoneContext)) { + throw new NumberParseException(NumberParseException.ErrorType.NOT_A_NUMBER, + "The phone-context value is invalid."); + } + if (phoneContext != null) { + // If the phone context contains a phone number prefix, we need to capture it, whereas domains + // will be ignored. + if (phoneContext.charAt(0) == PLUS_SIGN) { + // Additional parameters might follow the phone context. If so, we will remove them here + // because the parameters after phone context are not important for parsing the phone + // number. + nationalNumber.append(phoneContext); + } + + // Now append everything between the "tel:" prefix and the phone-context. This should include + // the national number, an optional extension or isdn-subaddress component. Note we also + // handle the case when "tel:" is missing, as we have seen in some of the phone number inputs. + // In that case, we append everything from the beginning. + int indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX); + int indexOfNationalNumber = + (indexOfRfc3966Prefix >= 0) ? indexOfRfc3966Prefix + RFC3966_PREFIX.length() : 0; + nationalNumber.append(numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext)); + } else { + // Extract a possible number from the string passed in (this strips leading characters that + // could not be the start of a phone number.) + nationalNumber.append(extractPossibleNumber(numberToParse)); + } + + // Delete the isdn-subaddress and everything after it if it is present. Note extension won't + // appear at the same time with isdn-subaddress according to paragraph 5.3 of the RFC3966 spec, + int indexOfIsdn = nationalNumber.indexOf(RFC3966_ISDN_SUBADDRESS); + if (indexOfIsdn > 0) { + nationalNumber.delete(indexOfIsdn, nationalNumber.length()); + } + // If both phone context and isdn-subaddress are absent but other parameters are present, the + // parameters are left in nationalNumber. This is because we are concerned about deleting + // content from a potential number string when there is no strong evidence that the number is + // actually written in RFC3966. + } + + /** + * Returns a new phone number containing only the fields needed to uniquely identify a phone + * number, rather than any fields that capture the context in which the phone number was created. + * These fields correspond to those set in parse() rather than parseAndKeepRawInput(). + */ + private static PhoneNumber copyCoreFieldsOnly(PhoneNumber phoneNumberIn) { + PhoneNumber phoneNumber = new PhoneNumber(); + phoneNumber.setCountryCode(phoneNumberIn.getCountryCode()); + phoneNumber.setNationalNumber(phoneNumberIn.getNationalNumber()); + if (phoneNumberIn.getExtension().length() > 0) { + phoneNumber.setExtension(phoneNumberIn.getExtension()); + } + if (phoneNumberIn.isItalianLeadingZero()) { + phoneNumber.setItalianLeadingZero(true); + // This field is only relevant if there are leading zeros at all. + phoneNumber.setNumberOfLeadingZeros(phoneNumberIn.getNumberOfLeadingZeros()); + } + return phoneNumber; + } + + /** + * Takes two phone numbers and compares them for equality. + * + *

Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero for Italian numbers + * and any extension present are the same. + * Returns NSN_MATCH if either or both has no region specified, and the NSNs and extensions are + * the same. + * Returns SHORT_NSN_MATCH if either or both has no region specified, or the region specified is + * the same, and one NSN could be a shorter version of the other number. This includes the case + * where one has an extension specified, and the other does not. + * Returns NO_MATCH otherwise. + * For example, the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. + * The numbers +1 345 657 1234 and 345 657 are a NO_MATCH. + * + * @param firstNumberIn first number to compare + * @param secondNumberIn second number to compare + * + * @return NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of equality + * of the two numbers, described in the method definition. + */ + public MatchType isNumberMatch(PhoneNumber firstNumberIn, PhoneNumber secondNumberIn) { + // We only care about the fields that uniquely define a number, so we copy these across + // explicitly. + PhoneNumber firstNumber = copyCoreFieldsOnly(firstNumberIn); + PhoneNumber secondNumber = copyCoreFieldsOnly(secondNumberIn); + // Early exit if both had extensions and these are different. + if (firstNumber.hasExtension() && secondNumber.hasExtension() + && !firstNumber.getExtension().equals(secondNumber.getExtension())) { + return MatchType.NO_MATCH; + } + int firstNumberCountryCode = firstNumber.getCountryCode(); + int secondNumberCountryCode = secondNumber.getCountryCode(); + // Both had country_code specified. + if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) { + if (firstNumber.exactlySameAs(secondNumber)) { + return MatchType.EXACT_MATCH; + } else if (firstNumberCountryCode == secondNumberCountryCode + && isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { + // A SHORT_NSN_MATCH occurs if there is a difference because of the presence or absence of + // an 'Italian leading zero', the presence or absence of an extension, or one NSN being a + // shorter variant of the other. + return MatchType.SHORT_NSN_MATCH; + } + // This is not a match. + return MatchType.NO_MATCH; + } + // Checks cases where one or both country_code fields were not specified. To make equality + // checks easier, we first set the country_code fields to be equal. + firstNumber.setCountryCode(secondNumberCountryCode); + // If all else was the same, then this is an NSN_MATCH. + if (firstNumber.exactlySameAs(secondNumber)) { + return MatchType.NSN_MATCH; + } + if (isNationalNumberSuffixOfTheOther(firstNumber, secondNumber)) { + return MatchType.SHORT_NSN_MATCH; + } + return MatchType.NO_MATCH; + } + + // Returns true when one national number is the suffix of the other or both are the same. + private boolean isNationalNumberSuffixOfTheOther(PhoneNumber firstNumber, + PhoneNumber secondNumber) { + String firstNumberNationalNumber = String.valueOf(firstNumber.getNationalNumber()); + String secondNumberNationalNumber = String.valueOf(secondNumber.getNationalNumber()); + // Note that endsWith returns true if the numbers are equal. + return firstNumberNationalNumber.endsWith(secondNumberNationalNumber) + || secondNumberNationalNumber.endsWith(firstNumberNationalNumber); + } + + /** + * Takes two phone numbers as strings and compares them for equality. This is a convenience + * wrapper for {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known. + * + * @param firstNumber first number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @param secondNumber second number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. + */ + public MatchType isNumberMatch(CharSequence firstNumber, CharSequence secondNumber) { + try { + PhoneNumber firstNumberAsProto = parse(firstNumber, UNKNOWN_REGION); + return isNumberMatch(firstNumberAsProto, secondNumber); + } catch (NumberParseException e) { + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + try { + PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION); + return isNumberMatch(secondNumberAsProto, firstNumber); + } catch (NumberParseException e2) { + if (e2.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + try { + PhoneNumber firstNumberProto = new PhoneNumber(); + PhoneNumber secondNumberProto = new PhoneNumber(); + parseHelper(firstNumber, null, false, false, firstNumberProto); + parseHelper(secondNumber, null, false, false, secondNumberProto); + return isNumberMatch(firstNumberProto, secondNumberProto); + } catch (NumberParseException e3) { + // Fall through and return MatchType.NOT_A_NUMBER. + } + } + } + } + } + // One or more of the phone numbers we are trying to match is not a viable phone number. + return MatchType.NOT_A_NUMBER; + } + + /** + * Takes two phone numbers and compares them for equality. This is a convenience wrapper for + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)}. No default region is known. + * + * @param firstNumber first number to compare in proto buffer format + * @param secondNumber second number to compare. Can contain formatting, and can have country + * calling code specified with + at the start. + * @return NOT_A_NUMBER, NO_MATCH, SHORT_NSN_MATCH, NSN_MATCH, EXACT_MATCH. See + * {@link #isNumberMatch(PhoneNumber, PhoneNumber)} for more details. + */ + public MatchType isNumberMatch(PhoneNumber firstNumber, CharSequence secondNumber) { + // First see if the second number has an implicit country calling code, by attempting to parse + // it. + try { + PhoneNumber secondNumberAsProto = parse(secondNumber, UNKNOWN_REGION); + return isNumberMatch(firstNumber, secondNumberAsProto); + } catch (NumberParseException e) { + if (e.getErrorType() == NumberParseException.ErrorType.INVALID_COUNTRY_CODE) { + // The second number has no country calling code. EXACT_MATCH is no longer possible. + // We parse it as if the region was the same as that for the first number, and if + // EXACT_MATCH is returned, we replace this with NSN_MATCH. + String firstNumberRegion = getRegionCodeForCountryCode(firstNumber.getCountryCode()); + try { + if (!firstNumberRegion.equals(UNKNOWN_REGION)) { + PhoneNumber secondNumberWithFirstNumberRegion = parse(secondNumber, firstNumberRegion); + MatchType match = isNumberMatch(firstNumber, secondNumberWithFirstNumberRegion); + if (match == MatchType.EXACT_MATCH) { + return MatchType.NSN_MATCH; + } + return match; + } else { + // If the first number didn't have a valid country calling code, then we parse the + // second number without one as well. + PhoneNumber secondNumberProto = new PhoneNumber(); + parseHelper(secondNumber, null, false, false, secondNumberProto); + return isNumberMatch(firstNumber, secondNumberProto); + } + } catch (NumberParseException e2) { + // Fall-through to return NOT_A_NUMBER. + } + } + } + // One or more of the phone numbers we are trying to match is not a viable phone number. + return MatchType.NOT_A_NUMBER; + } + + /** + * Returns true if the number can be dialled from outside the region, or unknown. If the number + * can only be dialled from within the region, returns false. Does not check the number is a valid + * number. Note that, at the moment, this method does not handle short numbers (which are + * currently all presumed to not be diallable from outside their country). + * + * @param number the phone-number for which we want to know whether it is diallable from + * outside the region + */ + public boolean canBeInternationallyDialled(PhoneNumber number) { + PhoneMetadata metadata = getMetadataForRegion(getRegionCodeForNumber(number)); + if (metadata == null) { + // Note numbers belonging to non-geographical entities (e.g. +800 numbers) are always + // internationally diallable, and will be caught here. + return true; + } + String nationalSignificantNumber = getNationalSignificantNumber(number); + return !isNumberMatchingDesc(nationalSignificantNumber, metadata.getNoInternationalDialling()); + } + + /** + * Returns true if the supplied region supports mobile number portability. Returns false for + * invalid, unknown or regions that don't support mobile number portability. + * + * @param regionCode the region for which we want to know whether it supports mobile number + * portability or not + */ + public boolean isMobileNumberPortableRegion(String regionCode) { + PhoneMetadata metadata = getMetadataForRegion(regionCode); + if (metadata == null) { + logger.log(Level.WARNING, "Invalid or unknown region code provided: " + regionCode); + return false; + } + return metadata.getMobileNumberPortableRegion(); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonemetadata.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonemetadata.java new file mode 100644 index 0000000000..914c796368 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonemetadata.java @@ -0,0 +1,1188 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Definition of the class representing metadata for international telephone numbers. This class is + * hand created based on the class file compiled from phonemetadata.proto. Please refer to that file + * for detailed descriptions of the meaning of each field. + * + *

WARNING: This API isn't stable. It is considered libphonenumber-internal and can change at any + * time. We only declare it as public for easy inclusion in our build tools not in this package. + * Clients should not refer to this file, we do not commit to support backwards-compatibility or to + * warn about breaking changes. + */ + +package com.google.i18n.phonenumbers; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +public final class Phonemetadata { + private Phonemetadata() {} + public static class NumberFormat implements Externalizable { + private static final long serialVersionUID = 1; + public NumberFormat() {} + + /** + * Provides a dummy builder to 'emulate' the API of the code generated by the latest version of + * Protocol Buffers. This lets BuildMetadataFromXml class to build with both this hand created + * class and the one generated by the latest version of Protocol Buffers. + */ + public static final class Builder extends NumberFormat { + public NumberFormat build() { + return this; + } + + public Builder mergeFrom(NumberFormat other) { + if (other.hasPattern()) { + setPattern(other.getPattern()); + } + if (other.hasFormat()) { + setFormat(other.getFormat()); + } + for (int i = 0; i < other.leadingDigitsPatternSize(); i++) { + addLeadingDigitsPattern(other.getLeadingDigitsPattern(i)); + } + if (other.hasNationalPrefixFormattingRule()) { + setNationalPrefixFormattingRule(other.getNationalPrefixFormattingRule()); + } + if (other.hasDomesticCarrierCodeFormattingRule()) { + setDomesticCarrierCodeFormattingRule(other.getDomesticCarrierCodeFormattingRule()); + } + if (other.hasNationalPrefixOptionalWhenFormatting()) { + setNationalPrefixOptionalWhenFormatting(other.getNationalPrefixOptionalWhenFormatting()); + } + return this; + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + // required string pattern = 1; + private boolean hasPattern; + private String pattern_ = ""; + public boolean hasPattern() { return hasPattern; } + public String getPattern() { return pattern_; } + public NumberFormat setPattern(String value) { + hasPattern = true; + pattern_ = value; + return this; + } + + // required string format = 2; + private boolean hasFormat; + private String format_ = ""; + public boolean hasFormat() { return hasFormat; } + public String getFormat() { return format_; } + public NumberFormat setFormat(String value) { + hasFormat = true; + format_ = value; + return this; + } + + // repeated string leading_digits_pattern = 3; + private java.util.List leadingDigitsPattern_ = new java.util.ArrayList(); + public java.util.List leadingDigitPatterns() { + return leadingDigitsPattern_; + } + @Deprecated + public int leadingDigitsPatternSize() { return getLeadingDigitsPatternCount(); } + public int getLeadingDigitsPatternCount() { return leadingDigitsPattern_.size(); } + public String getLeadingDigitsPattern(int index) { + return leadingDigitsPattern_.get(index); + } + public NumberFormat addLeadingDigitsPattern(String value) { + if (value == null) { + throw new NullPointerException(); + } + leadingDigitsPattern_.add(value); + return this; + } + + // optional string national_prefix_formatting_rule = 4; + private boolean hasNationalPrefixFormattingRule; + private String nationalPrefixFormattingRule_ = ""; + public boolean hasNationalPrefixFormattingRule() { return hasNationalPrefixFormattingRule; } + public String getNationalPrefixFormattingRule() { return nationalPrefixFormattingRule_; } + public NumberFormat setNationalPrefixFormattingRule(String value) { + hasNationalPrefixFormattingRule = true; + nationalPrefixFormattingRule_ = value; + return this; + } + public NumberFormat clearNationalPrefixFormattingRule() { + hasNationalPrefixFormattingRule = false; + nationalPrefixFormattingRule_ = ""; + return this; + } + + // optional bool national_prefix_optional_when_formatting = 6 [default = false]; + private boolean hasNationalPrefixOptionalWhenFormatting; + private boolean nationalPrefixOptionalWhenFormatting_ = false; + public boolean hasNationalPrefixOptionalWhenFormatting() { + return hasNationalPrefixOptionalWhenFormatting; } + public boolean getNationalPrefixOptionalWhenFormatting() { + return nationalPrefixOptionalWhenFormatting_; } + public NumberFormat setNationalPrefixOptionalWhenFormatting(boolean value) { + hasNationalPrefixOptionalWhenFormatting = true; + nationalPrefixOptionalWhenFormatting_ = value; + return this; + } + + // optional string domestic_carrier_code_formatting_rule = 5; + private boolean hasDomesticCarrierCodeFormattingRule; + private String domesticCarrierCodeFormattingRule_ = ""; + public boolean hasDomesticCarrierCodeFormattingRule() { + return hasDomesticCarrierCodeFormattingRule; } + public String getDomesticCarrierCodeFormattingRule() { + return domesticCarrierCodeFormattingRule_; } + public NumberFormat setDomesticCarrierCodeFormattingRule(String value) { + hasDomesticCarrierCodeFormattingRule = true; + domesticCarrierCodeFormattingRule_ = value; + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeUTF(pattern_); + objectOutput.writeUTF(format_); + int leadingDigitsPatternSize = leadingDigitsPatternSize(); + objectOutput.writeInt(leadingDigitsPatternSize); + for (int i = 0; i < leadingDigitsPatternSize; i++) { + objectOutput.writeUTF(leadingDigitsPattern_.get(i)); + } + + objectOutput.writeBoolean(hasNationalPrefixFormattingRule); + if (hasNationalPrefixFormattingRule) { + objectOutput.writeUTF(nationalPrefixFormattingRule_); + } + objectOutput.writeBoolean(hasDomesticCarrierCodeFormattingRule); + if (hasDomesticCarrierCodeFormattingRule) { + objectOutput.writeUTF(domesticCarrierCodeFormattingRule_); + } + objectOutput.writeBoolean(nationalPrefixOptionalWhenFormatting_); + } + + public void readExternal(ObjectInput objectInput) throws IOException { + setPattern(objectInput.readUTF()); + setFormat(objectInput.readUTF()); + int leadingDigitsPatternSize = objectInput.readInt(); + for (int i = 0; i < leadingDigitsPatternSize; i++) { + leadingDigitsPattern_.add(objectInput.readUTF()); + } + if (objectInput.readBoolean()) { + setNationalPrefixFormattingRule(objectInput.readUTF()); + } + if (objectInput.readBoolean()) { + setDomesticCarrierCodeFormattingRule(objectInput.readUTF()); + } + setNationalPrefixOptionalWhenFormatting(objectInput.readBoolean()); + } + } + + public static class PhoneNumberDesc implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneNumberDesc() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneNumberDesc { + public PhoneNumberDesc build() { + return this; + } + + public Builder mergeFrom(PhoneNumberDesc other) { + if (other.hasNationalNumberPattern()) { + setNationalNumberPattern(other.getNationalNumberPattern()); + } + for (int i = 0; i < other.getPossibleLengthCount(); i++) { + addPossibleLength(other.getPossibleLength(i)); + } + for (int i = 0; i < other.getPossibleLengthLocalOnlyCount(); i++) { + addPossibleLengthLocalOnly(other.getPossibleLengthLocalOnly(i)); + } + if (other.hasExampleNumber()) { + setExampleNumber(other.getExampleNumber()); + } + return this; + } + } + + public static Builder newBuilder() { + return new Builder(); + } + + // optional string national_number_pattern = 2; + private boolean hasNationalNumberPattern; + private String nationalNumberPattern_ = ""; + public boolean hasNationalNumberPattern() { return hasNationalNumberPattern; } + public String getNationalNumberPattern() { return nationalNumberPattern_; } + public PhoneNumberDesc setNationalNumberPattern(String value) { + hasNationalNumberPattern = true; + nationalNumberPattern_ = value; + return this; + } + public PhoneNumberDesc clearNationalNumberPattern() { + hasNationalNumberPattern = false; + nationalNumberPattern_ = ""; + return this; + } + + // repeated int32 possible_length = 9; + private java.util.List possibleLength_ = new java.util.ArrayList(); + public java.util.List getPossibleLengthList() { + return possibleLength_; + } + public int getPossibleLengthCount() { return possibleLength_.size(); } + public int getPossibleLength(int index) { + return possibleLength_.get(index); + } + public PhoneNumberDesc addPossibleLength(int value) { + possibleLength_.add(value); + return this; + } + public PhoneNumberDesc clearPossibleLength() { + possibleLength_.clear(); + return this; + } + + // repeated int32 possible_length_local_only = 10; + private java.util.List possibleLengthLocalOnly_ = new java.util.ArrayList(); + public java.util.List getPossibleLengthLocalOnlyList() { + return possibleLengthLocalOnly_; + } + public int getPossibleLengthLocalOnlyCount() { return possibleLengthLocalOnly_.size(); } + public int getPossibleLengthLocalOnly(int index) { + return possibleLengthLocalOnly_.get(index); + } + public PhoneNumberDesc addPossibleLengthLocalOnly(int value) { + possibleLengthLocalOnly_.add(value); + return this; + } + public PhoneNumberDesc clearPossibleLengthLocalOnly() { + possibleLengthLocalOnly_.clear(); + return this; + } + + // optional string example_number = 6; + private boolean hasExampleNumber; + private String exampleNumber_ = ""; + public boolean hasExampleNumber() { return hasExampleNumber; } + public String getExampleNumber() { return exampleNumber_; } + public PhoneNumberDesc setExampleNumber(String value) { + hasExampleNumber = true; + exampleNumber_ = value; + return this; + } + public PhoneNumberDesc clearExampleNumber() { + hasExampleNumber = false; + exampleNumber_ = ""; + return this; + } + + public boolean exactlySameAs(PhoneNumberDesc other) { + return nationalNumberPattern_.equals(other.nationalNumberPattern_) && + possibleLength_.equals(other.possibleLength_) && + possibleLengthLocalOnly_.equals(other.possibleLengthLocalOnly_) && + exampleNumber_.equals(other.exampleNumber_); + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeBoolean(hasNationalNumberPattern); + if (hasNationalNumberPattern) { + objectOutput.writeUTF(nationalNumberPattern_); + } + + int possibleLengthSize = getPossibleLengthCount(); + objectOutput.writeInt(possibleLengthSize); + for (int i = 0; i < possibleLengthSize; i++) { + objectOutput.writeInt(possibleLength_.get(i)); + } + + int possibleLengthLocalOnlySize = getPossibleLengthLocalOnlyCount(); + objectOutput.writeInt(possibleLengthLocalOnlySize); + for (int i = 0; i < possibleLengthLocalOnlySize; i++) { + objectOutput.writeInt(possibleLengthLocalOnly_.get(i)); + } + + objectOutput.writeBoolean(hasExampleNumber); + if (hasExampleNumber) { + objectOutput.writeUTF(exampleNumber_); + } + } + + public void readExternal(ObjectInput objectInput) throws IOException { + if (objectInput.readBoolean()) { + setNationalNumberPattern(objectInput.readUTF()); + } + + int possibleLengthSize = objectInput.readInt(); + for (int i = 0; i < possibleLengthSize; i++) { + possibleLength_.add(objectInput.readInt()); + } + + int possibleLengthLocalOnlySize = objectInput.readInt(); + for (int i = 0; i < possibleLengthLocalOnlySize; i++) { + possibleLengthLocalOnly_.add(objectInput.readInt()); + } + + if (objectInput.readBoolean()) { + setExampleNumber(objectInput.readUTF()); + } + } + } + + public static class PhoneMetadata implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneMetadata() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneMetadata { + public PhoneMetadata build() { + return this; + } + + public Builder setId(String value) { + super.setId(value); + return this; + } + + public Builder setInternationalPrefix(String value) { + super.setInternationalPrefix(value); + return this; + } + } + public static Builder newBuilder() { + return new Builder(); + } + + // optional PhoneNumberDesc general_desc = 1; + private boolean hasGeneralDesc; + private PhoneNumberDesc generalDesc_ = null; + public boolean hasGeneralDesc() { return hasGeneralDesc; } + public PhoneNumberDesc getGeneralDesc() { return generalDesc_; } + public PhoneNumberDesc getGeneralDescBuilder() { + if (generalDesc_ == null) { + generalDesc_ = new PhoneNumberDesc(); + } + return generalDesc_ ; + } + public PhoneMetadata setGeneralDesc(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasGeneralDesc = true; + generalDesc_ = value; + return this; + } + + // optional PhoneNumberDesc fixed_line = 2; + private boolean hasFixedLine; + private PhoneNumberDesc fixedLine_ = null; + public boolean hasFixedLine() { return hasFixedLine; } + public PhoneNumberDesc getFixedLine() { return fixedLine_; } + public PhoneMetadata setFixedLine(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasFixedLine = true; + fixedLine_ = value; + return this; + } + + // optional PhoneNumberDesc mobile = 3; + private boolean hasMobile; + private PhoneNumberDesc mobile_ = null; + public boolean hasMobile() { return hasMobile; } + public PhoneNumberDesc getMobile() { return mobile_; } + public PhoneMetadata setMobile(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasMobile = true; + mobile_ = value; + return this; + } + + // optional PhoneNumberDesc toll_free = 4; + private boolean hasTollFree; + private PhoneNumberDesc tollFree_ = null; + public boolean hasTollFree() { return hasTollFree; } + public PhoneNumberDesc getTollFree() { return tollFree_; } + public PhoneMetadata setTollFree(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasTollFree = true; + tollFree_ = value; + return this; + } + + // optional PhoneNumberDesc premium_rate = 5; + private boolean hasPremiumRate; + private PhoneNumberDesc premiumRate_ = null; + public boolean hasPremiumRate() { return hasPremiumRate; } + public PhoneNumberDesc getPremiumRate() { return premiumRate_; } + public PhoneMetadata setPremiumRate(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPremiumRate = true; + premiumRate_ = value; + return this; + } + + // optional PhoneNumberDesc shared_cost = 6; + private boolean hasSharedCost; + private PhoneNumberDesc sharedCost_ = null; + public boolean hasSharedCost() { return hasSharedCost; } + public PhoneNumberDesc getSharedCost() { return sharedCost_; } + public PhoneMetadata setSharedCost(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasSharedCost = true; + sharedCost_ = value; + return this; + } + + // optional PhoneNumberDesc personal_number = 7; + private boolean hasPersonalNumber; + private PhoneNumberDesc personalNumber_ = null; + public boolean hasPersonalNumber() { return hasPersonalNumber; } + public PhoneNumberDesc getPersonalNumber() { return personalNumber_; } + public PhoneMetadata setPersonalNumber(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPersonalNumber = true; + personalNumber_ = value; + return this; + } + + // optional PhoneNumberDesc voip = 8; + private boolean hasVoip; + private PhoneNumberDesc voip_ = null; + public boolean hasVoip() { return hasVoip; } + public PhoneNumberDesc getVoip() { return voip_; } + public PhoneMetadata setVoip(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasVoip = true; + voip_ = value; + return this; + } + + // optional PhoneNumberDesc pager = 21; + private boolean hasPager; + private PhoneNumberDesc pager_ = null; + public boolean hasPager() { return hasPager; } + public PhoneNumberDesc getPager() { return pager_; } + public PhoneMetadata setPager(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasPager = true; + pager_ = value; + return this; + } + + // optional PhoneNumberDesc uan = 25; + private boolean hasUan; + private PhoneNumberDesc uan_ = null; + public boolean hasUan() { return hasUan; } + public PhoneNumberDesc getUan() { return uan_; } + public PhoneMetadata setUan(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasUan = true; + uan_ = value; + return this; + } + + // optional PhoneNumberDesc emergency = 27; + private boolean hasEmergency; + private PhoneNumberDesc emergency_ = null; + public boolean hasEmergency() { return hasEmergency; } + public PhoneNumberDesc getEmergency() { return emergency_; } + public PhoneMetadata setEmergency(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasEmergency = true; + emergency_ = value; + return this; + } + + // optional PhoneNumberDesc voicemail = 28; + private boolean hasVoicemail; + private PhoneNumberDesc voicemail_ = null; + public boolean hasVoicemail() { return hasVoicemail; } + public PhoneNumberDesc getVoicemail() { return voicemail_; } + public PhoneMetadata setVoicemail(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasVoicemail = true; + voicemail_ = value; + return this; + } + + // optional PhoneNumberDesc short_code = 29; + private boolean hasShortCode; + private PhoneNumberDesc shortCode_ = null; + public boolean hasShortCode() { return hasShortCode; } + public PhoneNumberDesc getShortCode() { return shortCode_; } + public PhoneMetadata setShortCode(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasShortCode = true; + shortCode_ = value; + return this; + } + + // optional PhoneNumberDesc standard_rate = 30; + private boolean hasStandardRate; + private PhoneNumberDesc standardRate_ = null; + public boolean hasStandardRate() { return hasStandardRate; } + public PhoneNumberDesc getStandardRate() { return standardRate_; } + public PhoneMetadata setStandardRate(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasStandardRate = true; + standardRate_ = value; + return this; + } + + // optional PhoneNumberDesc carrier_specific = 31; + private boolean hasCarrierSpecific; + private PhoneNumberDesc carrierSpecific_ = null; + public boolean hasCarrierSpecific() { return hasCarrierSpecific; } + public PhoneNumberDesc getCarrierSpecific() { return carrierSpecific_; } + public PhoneMetadata setCarrierSpecific(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasCarrierSpecific = true; + carrierSpecific_ = value; + return this; + } + + // optional PhoneNumberDesc sms_services = 33; + private boolean hasSmsServices; + private PhoneNumberDesc smsServices_ = null; + public boolean hasSmsServices() { return hasSmsServices; } + public PhoneNumberDesc getSmsServices() { return smsServices_; } + public PhoneMetadata setSmsServices(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasSmsServices = true; + smsServices_ = value; + return this; + } + + // optional PhoneNumberDesc noInternationalDialling = 24; + private boolean hasNoInternationalDialling; + private PhoneNumberDesc noInternationalDialling_ = null; + public boolean hasNoInternationalDialling() { return hasNoInternationalDialling; } + public PhoneNumberDesc getNoInternationalDialling() { return noInternationalDialling_; } + public PhoneMetadata setNoInternationalDialling(PhoneNumberDesc value) { + if (value == null) { + throw new NullPointerException(); + } + hasNoInternationalDialling = true; + noInternationalDialling_ = value; + return this; + } + + // required string id = 9; + private boolean hasId; + private String id_ = ""; + public boolean hasId() { return hasId; } + public String getId() { return id_; } + public PhoneMetadata setId(String value) { + hasId = true; + id_ = value; + return this; + } + + // optional int32 country_code = 10; + private boolean hasCountryCode; + private int countryCode_ = 0; + public boolean hasCountryCode() { return hasCountryCode; } + public int getCountryCode() { return countryCode_; } + public PhoneMetadata setCountryCode(int value) { + hasCountryCode = true; + countryCode_ = value; + return this; + } + + // optional string international_prefix = 11; + private boolean hasInternationalPrefix; + private String internationalPrefix_ = ""; + public boolean hasInternationalPrefix() { return hasInternationalPrefix; } + public String getInternationalPrefix() { return internationalPrefix_; } + public PhoneMetadata setInternationalPrefix(String value) { + hasInternationalPrefix = true; + internationalPrefix_ = value; + return this; + } + + // optional string preferred_international_prefix = 17; + private boolean hasPreferredInternationalPrefix; + private String preferredInternationalPrefix_ = ""; + public boolean hasPreferredInternationalPrefix() { return hasPreferredInternationalPrefix; } + public String getPreferredInternationalPrefix() { return preferredInternationalPrefix_; } + public PhoneMetadata setPreferredInternationalPrefix(String value) { + hasPreferredInternationalPrefix = true; + preferredInternationalPrefix_ = value; + return this; + } + public PhoneMetadata clearPreferredInternationalPrefix() { + hasPreferredInternationalPrefix = false; + preferredInternationalPrefix_ = ""; + return this; + } + + // optional string national_prefix = 12; + private boolean hasNationalPrefix; + private String nationalPrefix_ = ""; + public boolean hasNationalPrefix() { return hasNationalPrefix; } + public String getNationalPrefix() { return nationalPrefix_; } + public PhoneMetadata setNationalPrefix(String value) { + hasNationalPrefix = true; + nationalPrefix_ = value; + return this; + } + public PhoneMetadata clearNationalPrefix() { + hasNationalPrefix = false; + nationalPrefix_ = ""; + return this; + } + + // optional string preferred_extn_prefix = 13; + private boolean hasPreferredExtnPrefix; + private String preferredExtnPrefix_ = ""; + public boolean hasPreferredExtnPrefix() { return hasPreferredExtnPrefix; } + public String getPreferredExtnPrefix() { return preferredExtnPrefix_; } + public PhoneMetadata setPreferredExtnPrefix(String value) { + hasPreferredExtnPrefix = true; + preferredExtnPrefix_ = value; + return this; + } + public PhoneMetadata clearPreferredExtnPrefix() { + hasPreferredExtnPrefix = false; + preferredExtnPrefix_ = ""; + return this; + } + + // optional string national_prefix_for_parsing = 15; + private boolean hasNationalPrefixForParsing; + private String nationalPrefixForParsing_ = ""; + public boolean hasNationalPrefixForParsing() { return hasNationalPrefixForParsing; } + public String getNationalPrefixForParsing() { return nationalPrefixForParsing_; } + public PhoneMetadata setNationalPrefixForParsing(String value) { + hasNationalPrefixForParsing = true; + nationalPrefixForParsing_ = value; + return this; + } + + // optional string national_prefix_transform_rule = 16; + private boolean hasNationalPrefixTransformRule; + private String nationalPrefixTransformRule_ = ""; + public boolean hasNationalPrefixTransformRule() { return hasNationalPrefixTransformRule; } + public String getNationalPrefixTransformRule() { return nationalPrefixTransformRule_; } + public PhoneMetadata setNationalPrefixTransformRule(String value) { + hasNationalPrefixTransformRule = true; + nationalPrefixTransformRule_ = value; + return this; + } + public PhoneMetadata clearNationalPrefixTransformRule() { + hasNationalPrefixTransformRule = false; + nationalPrefixTransformRule_ = ""; + return this; + } + + // optional bool same_mobile_and_fixed_line_pattern = 18 [default = false]; + private boolean hasSameMobileAndFixedLinePattern; + private boolean sameMobileAndFixedLinePattern_ = false; + public boolean hasSameMobileAndFixedLinePattern() { return hasSameMobileAndFixedLinePattern; } + public boolean getSameMobileAndFixedLinePattern() { return sameMobileAndFixedLinePattern_; } + public PhoneMetadata setSameMobileAndFixedLinePattern(boolean value) { + hasSameMobileAndFixedLinePattern = true; + sameMobileAndFixedLinePattern_ = value; + return this; + } + public PhoneMetadata clearSameMobileAndFixedLinePattern() { + hasSameMobileAndFixedLinePattern = false; + sameMobileAndFixedLinePattern_ = false; + return this; + } + + // repeated NumberFormat number_format = 19; + private java.util.List numberFormat_ = new java.util.ArrayList(); + @Deprecated + public java.util.List numberFormats() { + return getNumberFormatList(); + } + public java.util.List getNumberFormatList() { + return numberFormat_; + } + @Deprecated + public int numberFormatSize() { return getNumberFormatCount(); } + public int getNumberFormatCount() { return numberFormat_.size(); } + public NumberFormat getNumberFormat(int index) { + return numberFormat_.get(index); + } + public PhoneMetadata addNumberFormat(NumberFormat value) { + if (value == null) { + throw new NullPointerException(); + } + numberFormat_.add(value); + return this; + } + + // repeated NumberFormat intl_number_format = 20; + private java.util.List intlNumberFormat_ = + new java.util.ArrayList(); + @Deprecated + public java.util.List intlNumberFormats() { + return getIntlNumberFormatList(); + } + public java.util.List getIntlNumberFormatList() { + return intlNumberFormat_; + } + @Deprecated + public int intlNumberFormatSize() { return getIntlNumberFormatCount(); } + public int getIntlNumberFormatCount() { return intlNumberFormat_.size(); } + public NumberFormat getIntlNumberFormat(int index) { + return intlNumberFormat_.get(index); + } + + public PhoneMetadata addIntlNumberFormat(NumberFormat value) { + if (value == null) { + throw new NullPointerException(); + } + intlNumberFormat_.add(value); + return this; + } + public PhoneMetadata clearIntlNumberFormat() { + intlNumberFormat_.clear(); + return this; + } + + // optional bool main_country_for_code = 22 [default = false]; + private boolean hasMainCountryForCode; + private boolean mainCountryForCode_ = false; + public boolean hasMainCountryForCode() { return hasMainCountryForCode; } + public boolean isMainCountryForCode() { return mainCountryForCode_; } + // Method that lets this class have the same interface as the one generated by Protocol Buffers + // which is used by C++ build tools. + public boolean getMainCountryForCode() { return mainCountryForCode_; } + public PhoneMetadata setMainCountryForCode(boolean value) { + hasMainCountryForCode = true; + mainCountryForCode_ = value; + return this; + } + public PhoneMetadata clearMainCountryForCode() { + hasMainCountryForCode = false; + mainCountryForCode_ = false; + return this; + } + + // optional string leading_digits = 23; + private boolean hasLeadingDigits; + private String leadingDigits_ = ""; + public boolean hasLeadingDigits() { return hasLeadingDigits; } + public String getLeadingDigits() { return leadingDigits_; } + public PhoneMetadata setLeadingDigits(String value) { + hasLeadingDigits = true; + leadingDigits_ = value; + return this; + } + + // optional bool mobile_number_portable_region = 32 [default = false]; + private boolean hasMobileNumberPortableRegion; + private boolean mobileNumberPortableRegion_ = false; + public boolean hasMobileNumberPortableRegion() { return hasMobileNumberPortableRegion; } + @Deprecated + public boolean isMobileNumberPortableRegion() { return getMobileNumberPortableRegion(); } + public boolean getMobileNumberPortableRegion() { return mobileNumberPortableRegion_; } + public PhoneMetadata setMobileNumberPortableRegion(boolean value) { + hasMobileNumberPortableRegion = true; + mobileNumberPortableRegion_ = value; + return this; + } + public PhoneMetadata clearMobileNumberPortableRegion() { + hasMobileNumberPortableRegion = false; + mobileNumberPortableRegion_ = false; + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeBoolean(hasGeneralDesc); + if (hasGeneralDesc) { + generalDesc_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasFixedLine); + if (hasFixedLine) { + fixedLine_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasMobile); + if (hasMobile) { + mobile_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasTollFree); + if (hasTollFree) { + tollFree_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPremiumRate); + if (hasPremiumRate) { + premiumRate_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasSharedCost); + if (hasSharedCost) { + sharedCost_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPersonalNumber); + if (hasPersonalNumber) { + personalNumber_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasVoip); + if (hasVoip) { + voip_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasPager); + if (hasPager) { + pager_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasUan); + if (hasUan) { + uan_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasEmergency); + if (hasEmergency) { + emergency_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasVoicemail); + if (hasVoicemail) { + voicemail_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasShortCode); + if (hasShortCode) { + shortCode_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasStandardRate); + if (hasStandardRate) { + standardRate_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasCarrierSpecific); + if (hasCarrierSpecific) { + carrierSpecific_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasSmsServices); + if (hasSmsServices) { + smsServices_.writeExternal(objectOutput); + } + objectOutput.writeBoolean(hasNoInternationalDialling); + if (hasNoInternationalDialling) { + noInternationalDialling_.writeExternal(objectOutput); + } + + objectOutput.writeUTF(id_); + objectOutput.writeInt(countryCode_); + objectOutput.writeUTF(internationalPrefix_); + + objectOutput.writeBoolean(hasPreferredInternationalPrefix); + if (hasPreferredInternationalPrefix) { + objectOutput.writeUTF(preferredInternationalPrefix_); + } + + objectOutput.writeBoolean(hasNationalPrefix); + if (hasNationalPrefix) { + objectOutput.writeUTF(nationalPrefix_); + } + + objectOutput.writeBoolean(hasPreferredExtnPrefix); + if (hasPreferredExtnPrefix) { + objectOutput.writeUTF(preferredExtnPrefix_); + } + + objectOutput.writeBoolean(hasNationalPrefixForParsing); + if (hasNationalPrefixForParsing) { + objectOutput.writeUTF(nationalPrefixForParsing_); + } + + objectOutput.writeBoolean(hasNationalPrefixTransformRule); + if (hasNationalPrefixTransformRule) { + objectOutput.writeUTF(nationalPrefixTransformRule_); + } + + objectOutput.writeBoolean(sameMobileAndFixedLinePattern_); + + int numberFormatSize = numberFormatSize(); + objectOutput.writeInt(numberFormatSize); + for (int i = 0; i < numberFormatSize; i++) { + numberFormat_.get(i).writeExternal(objectOutput); + } + + int intlNumberFormatSize = intlNumberFormatSize(); + objectOutput.writeInt(intlNumberFormatSize); + for (int i = 0; i < intlNumberFormatSize; i++) { + intlNumberFormat_.get(i).writeExternal(objectOutput); + } + + objectOutput.writeBoolean(mainCountryForCode_); + + objectOutput.writeBoolean(hasLeadingDigits); + if (hasLeadingDigits) { + objectOutput.writeUTF(leadingDigits_); + } + + objectOutput.writeBoolean(mobileNumberPortableRegion_); + } + + public void readExternal(ObjectInput objectInput) throws IOException { + boolean hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setGeneralDesc(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setFixedLine(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setMobile(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setTollFree(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPremiumRate(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setSharedCost(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPersonalNumber(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setVoip(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setPager(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setUan(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setEmergency(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setVoicemail(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setShortCode(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setStandardRate(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setCarrierSpecific(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setSmsServices(desc); + } + hasDesc = objectInput.readBoolean(); + if (hasDesc) { + PhoneNumberDesc desc = new PhoneNumberDesc(); + desc.readExternal(objectInput); + setNoInternationalDialling(desc); + } + + setId(objectInput.readUTF()); + setCountryCode(objectInput.readInt()); + setInternationalPrefix(objectInput.readUTF()); + + boolean hasString = objectInput.readBoolean(); + if (hasString) { + setPreferredInternationalPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setPreferredExtnPrefix(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefixForParsing(objectInput.readUTF()); + } + + hasString = objectInput.readBoolean(); + if (hasString) { + setNationalPrefixTransformRule(objectInput.readUTF()); + } + + setSameMobileAndFixedLinePattern(objectInput.readBoolean()); + + int nationalFormatSize = objectInput.readInt(); + for (int i = 0; i < nationalFormatSize; i++) { + NumberFormat numFormat = new NumberFormat(); + numFormat.readExternal(objectInput); + numberFormat_.add(numFormat); + } + + int intlNumberFormatSize = objectInput.readInt(); + for (int i = 0; i < intlNumberFormatSize; i++) { + NumberFormat numFormat = new NumberFormat(); + numFormat.readExternal(objectInput); + intlNumberFormat_.add(numFormat); + } + + setMainCountryForCode(objectInput.readBoolean()); + + hasString = objectInput.readBoolean(); + if (hasString) { + setLeadingDigits(objectInput.readUTF()); + } + + setMobileNumberPortableRegion(objectInput.readBoolean()); + } + } + + public static class PhoneMetadataCollection implements Externalizable { + private static final long serialVersionUID = 1; + public PhoneMetadataCollection() {} + + /** + * Provides a dummy builder. + * + * @see NumberFormat.Builder + */ + public static final class Builder extends PhoneMetadataCollection { + public PhoneMetadataCollection build() { + return this; + } + } + public static Builder newBuilder() { + return new Builder(); + } + + // repeated PhoneMetadata metadata = 1; + private java.util.List metadata_ = new java.util.ArrayList(); + + public java.util.List getMetadataList() { + return metadata_; + } + public int getMetadataCount() { return metadata_.size(); } + + public PhoneMetadataCollection addMetadata(PhoneMetadata value) { + if (value == null) { + throw new NullPointerException(); + } + metadata_.add(value); + return this; + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + int size = getMetadataCount(); + objectOutput.writeInt(size); + for (int i = 0; i < size; i++) { + metadata_.get(i).writeExternal(objectOutput); + } + } + + public void readExternal(ObjectInput objectInput) throws IOException { + int size = objectInput.readInt(); + for (int i = 0; i < size; i++) { + PhoneMetadata metadata = new PhoneMetadata(); + metadata.readExternal(objectInput); + metadata_.add(metadata); + } + } + + public PhoneMetadataCollection clear() { + metadata_.clear(); + return this; + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonenumber.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonenumber.java new file mode 100644 index 0000000000..fe88a465c6 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/Phonenumber.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Definition of the class representing international telephone numbers. This class is hand-created + * based on the class file compiled from phonenumber.proto. Please refer to that file for detailed + * descriptions of the meaning of each field. + */ + +package com.google.i18n.phonenumbers; + +import java.io.Serializable; + +public final class Phonenumber { + private Phonenumber() {} + public static class PhoneNumber implements Serializable { + private static final long serialVersionUID = 1L; + public enum CountryCodeSource { + FROM_NUMBER_WITH_PLUS_SIGN, + FROM_NUMBER_WITH_IDD, + FROM_NUMBER_WITHOUT_PLUS_SIGN, + FROM_DEFAULT_COUNTRY, + UNSPECIFIED + } + + public PhoneNumber() { + countryCodeSource_ = CountryCodeSource.UNSPECIFIED; + } + + // required int32 country_code = 1; + private boolean hasCountryCode; + private int countryCode_ = 0; + public boolean hasCountryCode() { return hasCountryCode; } + public int getCountryCode() { return countryCode_; } + public PhoneNumber setCountryCode(int value) { + hasCountryCode = true; + countryCode_ = value; + return this; + } + public PhoneNumber clearCountryCode() { + hasCountryCode = false; + countryCode_ = 0; + return this; + } + + // required uint64 national_number = 2; + private boolean hasNationalNumber; + private long nationalNumber_ = 0L; + public boolean hasNationalNumber() { return hasNationalNumber; } + public long getNationalNumber() { return nationalNumber_; } + public PhoneNumber setNationalNumber(long value) { + hasNationalNumber = true; + nationalNumber_ = value; + return this; + } + public PhoneNumber clearNationalNumber() { + hasNationalNumber = false; + nationalNumber_ = 0L; + return this; + } + + // optional string extension = 3; + private boolean hasExtension; + private java.lang.String extension_ = ""; + public boolean hasExtension() { return hasExtension; } + public String getExtension() { return extension_; } + public PhoneNumber setExtension(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasExtension = true; + extension_ = value; + return this; + } + public PhoneNumber clearExtension() { + hasExtension = false; + extension_ = ""; + return this; + } + + // optional bool italian_leading_zero = 4; + private boolean hasItalianLeadingZero; + private boolean italianLeadingZero_ = false; + public boolean hasItalianLeadingZero() { return hasItalianLeadingZero; } + public boolean isItalianLeadingZero() { return italianLeadingZero_; } + public PhoneNumber setItalianLeadingZero(boolean value) { + hasItalianLeadingZero = true; + italianLeadingZero_ = value; + return this; + } + public PhoneNumber clearItalianLeadingZero() { + hasItalianLeadingZero = false; + italianLeadingZero_ = false; + return this; + } + + // optional int32 number_of_leading_zeros = 8 [default = 1]; + private boolean hasNumberOfLeadingZeros; + private int numberOfLeadingZeros_ = 1; + public boolean hasNumberOfLeadingZeros() { return hasNumberOfLeadingZeros; } + public int getNumberOfLeadingZeros() { return numberOfLeadingZeros_; } + public PhoneNumber setNumberOfLeadingZeros(int value) { + hasNumberOfLeadingZeros = true; + numberOfLeadingZeros_ = value; + return this; + } + public PhoneNumber clearNumberOfLeadingZeros() { + hasNumberOfLeadingZeros = false; + numberOfLeadingZeros_ = 1; + return this; + } + + // optional string raw_input = 5; + private boolean hasRawInput; + private String rawInput_ = ""; + public boolean hasRawInput() { return hasRawInput; } + public String getRawInput() { return rawInput_; } + public PhoneNumber setRawInput(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasRawInput = true; + rawInput_ = value; + return this; + } + public PhoneNumber clearRawInput() { + hasRawInput = false; + rawInput_ = ""; + return this; + } + + // optional CountryCodeSource country_code_source = 6; + private boolean hasCountryCodeSource; + private CountryCodeSource countryCodeSource_; + public boolean hasCountryCodeSource() { return hasCountryCodeSource; } + public CountryCodeSource getCountryCodeSource() { return countryCodeSource_; } + public PhoneNumber setCountryCodeSource(CountryCodeSource value) { + if (value == null) { + throw new NullPointerException(); + } + hasCountryCodeSource = true; + countryCodeSource_ = value; + return this; + } + public PhoneNumber clearCountryCodeSource() { + hasCountryCodeSource = false; + countryCodeSource_ = CountryCodeSource.UNSPECIFIED; + return this; + } + + // optional string preferred_domestic_carrier_code = 7; + private boolean hasPreferredDomesticCarrierCode; + private java.lang.String preferredDomesticCarrierCode_ = ""; + public boolean hasPreferredDomesticCarrierCode() { return hasPreferredDomesticCarrierCode; } + public String getPreferredDomesticCarrierCode() { return preferredDomesticCarrierCode_; } + public PhoneNumber setPreferredDomesticCarrierCode(String value) { + if (value == null) { + throw new NullPointerException(); + } + hasPreferredDomesticCarrierCode = true; + preferredDomesticCarrierCode_ = value; + return this; + } + public PhoneNumber clearPreferredDomesticCarrierCode() { + hasPreferredDomesticCarrierCode = false; + preferredDomesticCarrierCode_ = ""; + return this; + } + + public final PhoneNumber clear() { + clearCountryCode(); + clearNationalNumber(); + clearExtension(); + clearItalianLeadingZero(); + clearNumberOfLeadingZeros(); + clearRawInput(); + clearCountryCodeSource(); + clearPreferredDomesticCarrierCode(); + return this; + } + + public PhoneNumber mergeFrom(PhoneNumber other) { + if (other.hasCountryCode()) { + setCountryCode(other.getCountryCode()); + } + if (other.hasNationalNumber()) { + setNationalNumber(other.getNationalNumber()); + } + if (other.hasExtension()) { + setExtension(other.getExtension()); + } + if (other.hasItalianLeadingZero()) { + setItalianLeadingZero(other.isItalianLeadingZero()); + } + if (other.hasNumberOfLeadingZeros()) { + setNumberOfLeadingZeros(other.getNumberOfLeadingZeros()); + } + if (other.hasRawInput()) { + setRawInput(other.getRawInput()); + } + if (other.hasCountryCodeSource()) { + setCountryCodeSource(other.getCountryCodeSource()); + } + if (other.hasPreferredDomesticCarrierCode()) { + setPreferredDomesticCarrierCode(other.getPreferredDomesticCarrierCode()); + } + return this; + } + + public boolean exactlySameAs(PhoneNumber other) { + if (other == null) { + return false; + } + if (this == other) { + return true; + } + return (countryCode_ == other.countryCode_ && nationalNumber_ == other.nationalNumber_ && + extension_.equals(other.extension_) && italianLeadingZero_ == other.italianLeadingZero_ && + numberOfLeadingZeros_ == other.numberOfLeadingZeros_ && + rawInput_.equals(other.rawInput_) && countryCodeSource_ == other.countryCodeSource_ && + preferredDomesticCarrierCode_.equals(other.preferredDomesticCarrierCode_) && + hasPreferredDomesticCarrierCode() == other.hasPreferredDomesticCarrierCode()); + } + + @Override + public boolean equals(Object that) { + return (that instanceof PhoneNumber) && exactlySameAs((PhoneNumber) that); + } + + @Override + public int hashCode() { + // Simplified rendition of the hashCode function automatically generated from the proto + // compiler with java_generate_equals_and_hash set to true. We are happy with unset values to + // be considered equal to their explicitly-set equivalents, so don't check if any value is + // unknown. The only exception to this is the preferred domestic carrier code. + int hash = 41; + hash = (53 * hash) + getCountryCode(); + hash = (53 * hash) + Long.valueOf(getNationalNumber()).hashCode(); + hash = (53 * hash) + getExtension().hashCode(); + hash = (53 * hash) + (isItalianLeadingZero() ? 1231 : 1237); + hash = (53 * hash) + getNumberOfLeadingZeros(); + hash = (53 * hash) + getRawInput().hashCode(); + hash = (53 * hash) + getCountryCodeSource().hashCode(); + hash = (53 * hash) + getPreferredDomesticCarrierCode().hashCode(); + hash = (53 * hash) + (hasPreferredDomesticCarrierCode() ? 1231 : 1237); + return hash; + } + + @Override + public String toString() { + StringBuilder outputString = new StringBuilder(); + outputString.append("Country Code: ").append(countryCode_); + outputString.append(" National Number: ").append(nationalNumber_); + if (hasItalianLeadingZero() && isItalianLeadingZero()) { + outputString.append(" Leading Zero(s): true"); + } + if (hasNumberOfLeadingZeros()) { + outputString.append(" Number of leading zeros: ").append(numberOfLeadingZeros_); + } + if (hasExtension()) { + outputString.append(" Extension: ").append(extension_); + } + if (hasCountryCodeSource()) { + outputString.append(" Country Code Source: ").append(countryCodeSource_); + } + if (hasPreferredDomesticCarrierCode()) { + outputString.append(" Preferred Domestic Carrier Code: "). + append(preferredDomesticCarrierCode_); + } + return outputString.toString(); + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumberInfo.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumberInfo.java new file mode 100644 index 0000000000..7ce2972bac --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumberInfo.java @@ -0,0 +1,569 @@ +/* + * Copyright (C) 2013 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers; + +import com.google.i18n.phonenumbers.internal.MatcherApi; +import com.google.i18n.phonenumbers.internal.RegexBasedMatcher; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Methods for getting information about short phone numbers, such as short codes and emergency + * numbers. Note that most commercial short numbers are not handled here, but by the + * {@link PhoneNumberUtil}. + * + * @author Shaopeng Jia + * @author David Yonge-Mallo + */ +public class ShortNumberInfo { + private static final Logger logger = Logger.getLogger(ShortNumberInfo.class.getName()); + + private static final ShortNumberInfo INSTANCE = + new ShortNumberInfo( + RegexBasedMatcher.create(), + DefaultMetadataDependenciesProvider.getInstance().getShortNumberMetadataSource()); + + // In these countries, if extra digits are added to an emergency number, it no longer connects + // to the emergency service. + private static final Set REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT = new HashSet<>(); + static { + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("BR"); + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("CL"); + REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.add("NI"); + } + + /** Cost categories of short numbers. */ + public enum ShortNumberCost { + TOLL_FREE, + STANDARD_RATE, + PREMIUM_RATE, + UNKNOWN_COST + } + + /** Returns the singleton instance of the ShortNumberInfo. */ + public static ShortNumberInfo getInstance() { + return INSTANCE; + } + + // MatcherApi supports the basic matching method for checking if a given national number matches + // a national number pattern defined in the given {@code PhoneNumberDesc}. + private final MatcherApi matcherApi; + + // A mapping from a country calling code to the region codes which denote the region represented + // by that country calling code. In the case of multiple regions sharing a calling code, such as + // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be + // first. + private final Map> countryCallingCodeToRegionCodeMap; + + private final RegionMetadataSource shortNumberMetadataSource; + + // @VisibleForTesting + ShortNumberInfo(MatcherApi matcherApi, + RegionMetadataSource shortNumberMetadataSource) { + this.matcherApi = matcherApi; + this.shortNumberMetadataSource = shortNumberMetadataSource; + // TODO: Create ShortNumberInfo for a given map + this.countryCallingCodeToRegionCodeMap = + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap(); + } + + /** + * Returns a list with the region codes that match the specific country calling code. For + * non-geographical country calling codes, the region code 001 is returned. Also, in the case + * of no region code being found, an empty list is returned. + */ + private List getRegionCodesForCountryCode(int countryCallingCode) { + List regionCodes = countryCallingCodeToRegionCodeMap.get(countryCallingCode); + return Collections.unmodifiableList(regionCodes == null ? new ArrayList(0) + : regionCodes); + } + + /** + * Helper method to check that the country calling code of the number matches the region it's + * being dialed from. + */ + private boolean regionDialingFromMatchesNumber(PhoneNumber number, + String regionDialingFrom) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + return regionCodes.contains(regionDialingFrom); + } + + /** + * A thin wrapper around {@code shortNumberMetadataSource} which catches {@link + * IllegalArgumentException} for invalid region code and instead returns {@code null} + */ + private PhoneMetadata getShortNumberMetadataForRegion(String regionCode) { + if (regionCode == null) { + return null; + } + try { + return shortNumberMetadataSource.getMetadataForRegion(regionCode); + } catch (IllegalArgumentException e) { + return null; + } + } + + /** + * Check whether a short number is a possible number when dialed from the given region. This + * provides a more lenient check than {@link #isValidShortNumberForRegion}. + * + * @param number the short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the number is a possible short number + */ + public boolean isPossibleShortNumberForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return false; + } + int numberLength = getNationalSignificantNumber(number).length(); + return phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(numberLength); + } + + /** + * Check whether a short number is a possible number. If a country calling code is shared by + * multiple regions, this returns true if it's possible in any of them. This provides a more + * lenient check than {@link #isValidShortNumber}. See {@link + * #isPossibleShortNumberForRegion(PhoneNumber, String)} for details. + * + * @param number the short number to check + * @return whether the number is a possible short number + */ + public boolean isPossibleShortNumber(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + int shortNumberLength = getNationalSignificantNumber(number).length(); + for (String region : regionCodes) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(region); + if (phoneMetadata == null) { + continue; + } + if (phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(shortNumberLength)) { + return true; + } + } + return false; + } + + /** + * Tests whether a short number matches a valid pattern in a region. Note that this doesn't verify + * the number is actually in use, which is impossible to tell by just looking at the number + * itself. + * + * @param number the short number for which we want to test the validity + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number matches a valid pattern + */ + public boolean isValidShortNumberForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return false; + } + String shortNumber = getNationalSignificantNumber(number); + PhoneNumberDesc generalDesc = phoneMetadata.getGeneralDesc(); + if (!matchesPossibleNumberAndNationalNumber(shortNumber, generalDesc)) { + return false; + } + PhoneNumberDesc shortNumberDesc = phoneMetadata.getShortCode(); + return matchesPossibleNumberAndNationalNumber(shortNumber, shortNumberDesc); + } + + /** + * Tests whether a short number matches a valid pattern. If a country calling code is shared by + * multiple regions, this returns true if it's valid in any of them. Note that this doesn't verify + * the number is actually in use, which is impossible to tell by just looking at the number + * itself. See {@link #isValidShortNumberForRegion(PhoneNumber, String)} for details. + * + * @param number the short number for which we want to test the validity + * @return whether the short number matches a valid pattern + */ + public boolean isValidShortNumber(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); + if (regionCodes.size() > 1 && regionCode != null) { + // If a matching region had been found for the phone number from among two or more regions, + // then we have already implicitly verified its validity for that region. + return true; + } + return isValidShortNumberForRegion(number, regionCode); + } + + /** + * Gets the expected cost category of a short number when dialed from a region (however, nothing + * is implied about its validity). If it is important that the number is valid, then its validity + * must first be checked using {@link #isValidShortNumberForRegion}. Note that emergency numbers + * are always considered toll-free. Example usage: + *

{@code
+   * // The region for which the number was parsed and the region we subsequently check against
+   * // need not be the same. Here we parse the number in the US and check it for Canada.
+   * PhoneNumber number = phoneUtil.parse("110", "US");
+   * ...
+   * String regionCode = "CA";
+   * ShortNumberInfo shortInfo = ShortNumberInfo.getInstance();
+   * if (shortInfo.isValidShortNumberForRegion(shortNumber, regionCode)) {
+   *   ShortNumberCost cost = shortInfo.getExpectedCostForRegion(number, regionCode);
+   *   // Do something with the cost information here.
+   * }}
+ * + * @param number the short number for which we want to know the expected cost category + * @param regionDialingFrom the region from which the number is dialed + * @return the expected cost category for that region of the short number. Returns UNKNOWN_COST if + * the number does not match a cost category. Note that an invalid number may match any cost + * category. + */ + public ShortNumberCost getExpectedCostForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return ShortNumberCost.UNKNOWN_COST; + } + // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null. + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + if (phoneMetadata == null) { + return ShortNumberCost.UNKNOWN_COST; + } + + String shortNumber = getNationalSignificantNumber(number); + + // The possible lengths are not present for a particular sub-type if they match the general + // description; for this reason, we check the possible lengths against the general description + // first to allow an early exit if possible. + if (!phoneMetadata.getGeneralDesc().getPossibleLengthList().contains(shortNumber.length())) { + return ShortNumberCost.UNKNOWN_COST; + } + + // The cost categories are tested in order of decreasing expense, since if for some reason the + // patterns overlap the most expensive matching cost category should be returned. + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getPremiumRate())) { + return ShortNumberCost.PREMIUM_RATE; + } + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getStandardRate())) { + return ShortNumberCost.STANDARD_RATE; + } + if (matchesPossibleNumberAndNationalNumber(shortNumber, phoneMetadata.getTollFree())) { + return ShortNumberCost.TOLL_FREE; + } + if (isEmergencyNumber(shortNumber, regionDialingFrom)) { + // Emergency numbers are implicitly toll-free. + return ShortNumberCost.TOLL_FREE; + } + return ShortNumberCost.UNKNOWN_COST; + } + + /** + * Gets the expected cost category of a short number (however, nothing is implied about its + * validity). If the country calling code is unique to a region, this method behaves exactly the + * same as {@link #getExpectedCostForRegion(PhoneNumber, String)}. However, if the country + * calling code is shared by multiple regions, then it returns the highest cost in the sequence + * PREMIUM_RATE, UNKNOWN_COST, STANDARD_RATE, TOLL_FREE. The reason for the position of + * UNKNOWN_COST in this order is that if a number is UNKNOWN_COST in one region but STANDARD_RATE + * or TOLL_FREE in another, its expected cost cannot be estimated as one of the latter since it + * might be a PREMIUM_RATE number. + *

+ * For example, if a number is STANDARD_RATE in the US, but TOLL_FREE in Canada, the expected + * cost returned by this method will be STANDARD_RATE, since the NANPA countries share the same + * country calling code. + *

+ * Note: If the region from which the number is dialed is known, it is highly preferable to call + * {@link #getExpectedCostForRegion(PhoneNumber, String)} instead. + * + * @param number the short number for which we want to know the expected cost category + * @return the highest expected cost category of the short number in the region(s) with the given + * country calling code + */ + public ShortNumberCost getExpectedCost(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + if (regionCodes.size() == 0) { + return ShortNumberCost.UNKNOWN_COST; + } + if (regionCodes.size() == 1) { + return getExpectedCostForRegion(number, regionCodes.get(0)); + } + ShortNumberCost cost = ShortNumberCost.TOLL_FREE; + for (String regionCode : regionCodes) { + ShortNumberCost costForRegion = getExpectedCostForRegion(number, regionCode); + switch (costForRegion) { + case PREMIUM_RATE: + return ShortNumberCost.PREMIUM_RATE; + case UNKNOWN_COST: + cost = ShortNumberCost.UNKNOWN_COST; + break; + case STANDARD_RATE: + if (cost != ShortNumberCost.UNKNOWN_COST) { + cost = ShortNumberCost.STANDARD_RATE; + } + break; + case TOLL_FREE: + // Do nothing. + break; + default: + logger.log(Level.SEVERE, "Unrecognised cost for region: " + costForRegion); + } + } + return cost; + } + + // Helper method to get the region code for a given phone number, from a list of possible region + // codes. If the list contains more than one region, the first region for which the number is + // valid is returned. + private String getRegionCodeForShortNumberFromRegionList(PhoneNumber number, + List regionCodes) { + if (regionCodes.size() == 0) { + return null; + } else if (regionCodes.size() == 1) { + return regionCodes.get(0); + } + String nationalNumber = getNationalSignificantNumber(number); + for (String regionCode : regionCodes) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata != null + && matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getShortCode())) { + // The number is valid for this region. + return regionCode; + } + } + return null; + } + + /** + * Gets a valid short number for the specified region. + * + * @param regionCode the region for which an example short number is needed + * @return a valid short number for the specified region. Returns an empty string when the + * metadata does not contain such information. + */ + // @VisibleForTesting + String getExampleShortNumber(String regionCode) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata == null) { + return ""; + } + PhoneNumberDesc desc = phoneMetadata.getShortCode(); + if (desc.hasExampleNumber()) { + return desc.getExampleNumber(); + } + return ""; + } + + /** + * Gets a valid short number for the specified cost category. + * + * @param regionCode the region for which an example short number is needed + * @param cost the cost category of number that is needed + * @return a valid short number for the specified region and cost category. Returns an empty + * string when the metadata does not contain such information, or the cost is UNKNOWN_COST. + */ + // @VisibleForTesting + String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) { + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + if (phoneMetadata == null) { + return ""; + } + PhoneNumberDesc desc = null; + switch (cost) { + case TOLL_FREE: + desc = phoneMetadata.getTollFree(); + break; + case STANDARD_RATE: + desc = phoneMetadata.getStandardRate(); + break; + case PREMIUM_RATE: + desc = phoneMetadata.getPremiumRate(); + break; + default: + // UNKNOWN_COST numbers are computed by the process of elimination from the other cost + // categories. + } + if (desc != null && desc.hasExampleNumber()) { + return desc.getExampleNumber(); + } + return ""; + } + + /** + * Returns true if the given number, exactly as dialed, might be used to connect to an emergency + * service in the given region. + *

+ * This method accepts a string, rather than a PhoneNumber, because it needs to distinguish + * cases such as "+1 911" and "911", where the former may not connect to an emergency service in + * all cases but the latter would. This method takes into account cases where the number might + * contain formatting, or might have additional digits appended (when it is okay to do that in + * the specified region). + * + * @param number the phone number to test + * @param regionCode the region where the phone number is being dialed + * @return whether the number might be used to connect to an emergency service in the given region + */ + public boolean connectsToEmergencyNumber(String number, String regionCode) { + return matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */); + } + + /** + * Returns true if the given number exactly matches an emergency service number in the given + * region. + *

+ * This method takes into account cases where the number might contain formatting, but doesn't + * allow additional digits to be appended. Note that {@code isEmergencyNumber(number, region)} + * implies {@code connectsToEmergencyNumber(number, region)}. + * + * @param number the phone number to test + * @param regionCode the region where the phone number is being dialed + * @return whether the number exactly matches an emergency services number in the given region + */ + public boolean isEmergencyNumber(CharSequence number, String regionCode) { + return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */); + } + + private boolean matchesEmergencyNumberHelper(CharSequence number, String regionCode, + boolean allowPrefixMatch) { + CharSequence possibleNumber = PhoneNumberUtil.extractPossibleNumber(number); + if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(possibleNumber).lookingAt()) { + // Returns false if the number starts with a plus sign. We don't believe dialing the country + // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can + // add additional logic here to handle it. + return false; + } + PhoneMetadata metadata = getShortNumberMetadataForRegion(regionCode); + if (metadata == null || !metadata.hasEmergency()) { + return false; + } + + String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(possibleNumber); + boolean allowPrefixMatchForRegion = + allowPrefixMatch && !REGIONS_WHERE_EMERGENCY_NUMBERS_MUST_BE_EXACT.contains(regionCode); + return matcherApi.matchNationalNumber(normalizedNumber, metadata.getEmergency(), + allowPrefixMatchForRegion); + } + + /** + * Given a valid short number, determines whether it is carrier-specific (however, nothing is + * implied about its validity). Carrier-specific numbers may connect to a different end-point, or + * not connect at all, depending on the user's carrier. If it is important that the number is + * valid, then its validity must first be checked using {@link #isValidShortNumber} or + * {@link #isValidShortNumberForRegion}. + * + * @param number the valid short number to check + * @return whether the short number is carrier-specific, assuming the input was a valid short + * number + */ + public boolean isCarrierSpecific(PhoneNumber number) { + List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); + String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); + String nationalNumber = getNationalSignificantNumber(number); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); + return (phoneMetadata != null) + && (matchesPossibleNumberAndNationalNumber(nationalNumber, + phoneMetadata.getCarrierSpecific())); + } + + /** + * Given a valid short number, determines whether it is carrier-specific when dialed from the + * given region (however, nothing is implied about its validity). Carrier-specific numbers may + * connect to a different end-point, or not connect at all, depending on the user's carrier. If + * it is important that the number is valid, then its validity must first be checked using + * {@link #isValidShortNumber} or {@link #isValidShortNumberForRegion}. Returns false if the + * number doesn't match the region provided. + * + * @param number the valid short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number is carrier-specific in the provided region, assuming the + * input was a valid short number + */ + public boolean isCarrierSpecificForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + String nationalNumber = getNationalSignificantNumber(number); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + return (phoneMetadata != null) + && (matchesPossibleNumberAndNationalNumber(nationalNumber, + phoneMetadata.getCarrierSpecific())); + } + + /** + * Given a valid short number, determines whether it is an SMS service (however, nothing is + * implied about its validity). An SMS service is where the primary or only intended usage is to + * receive and/or send text messages (SMSs). This includes MMS as MMS numbers downgrade to SMS if + * the other party isn't MMS-capable. If it is important that the number is valid, then its + * validity must first be checked using {@link #isValidShortNumber} or {@link + * #isValidShortNumberForRegion}. Returns false if the number doesn't match the region provided. + * + * @param number the valid short number to check + * @param regionDialingFrom the region from which the number is dialed + * @return whether the short number is an SMS service in the provided region, assuming the input + * was a valid short number + */ + public boolean isSmsServiceForRegion(PhoneNumber number, String regionDialingFrom) { + if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { + return false; + } + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); + return phoneMetadata != null + && matchesPossibleNumberAndNationalNumber(getNationalSignificantNumber(number), + phoneMetadata.getSmsServices()); + } + + /** + * Gets the national significant number of the a phone number. Note a national significant number + * doesn't contain a national prefix or any formatting. + *

+ * This is a temporary duplicate of the {@code getNationalSignificantNumber} method from + * {@code PhoneNumberUtil}. Ultimately a canonical static version should exist in a separate + * utility class (to prevent {@code ShortNumberInfo} needing to depend on PhoneNumberUtil). + * + * @param number the phone number for which the national significant number is needed + * @return the national significant number of the PhoneNumber object passed in + */ + private static String getNationalSignificantNumber(PhoneNumber number) { + // If leading zero(s) have been set, we prefix this now. Note this is not a national prefix. + StringBuilder nationalNumber = new StringBuilder(); + if (number.isItalianLeadingZero()) { + char[] zeros = new char[number.getNumberOfLeadingZeros()]; + Arrays.fill(zeros, '0'); + nationalNumber.append(new String(zeros)); + } + nationalNumber.append(number.getNationalNumber()); + return nationalNumber.toString(); + } + + // TODO: Once we have benchmarked ShortNumberInfo, consider if it is worth keeping + // this performance optimization. + private boolean matchesPossibleNumberAndNationalNumber(String number, + PhoneNumberDesc numberDesc) { + if (numberDesc.getPossibleLengthCount() > 0 + && !numberDesc.getPossibleLengthList().contains(number.length())) { + return false; + } + return matcherApi.matchNationalNumber(number, numberDesc, false); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java new file mode 100644 index 0000000000..e2046b0cd3 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/ShortNumbersRegionCodeSet.java @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2013 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + +package com.google.i18n.phonenumbers; + +import java.util.HashSet; +import java.util.Set; + +public class ShortNumbersRegionCodeSet { + // A set of all region codes for which data is available. + public static Set getRegionCodeSet() { + // The capacity is set to 321 as there are 241 different entries, + // and this offers a load factor of roughly 0.75. + Set regionCodeSet = new HashSet(321); + + regionCodeSet.add("AC"); + regionCodeSet.add("AD"); + regionCodeSet.add("AE"); + regionCodeSet.add("AF"); + regionCodeSet.add("AG"); + regionCodeSet.add("AI"); + regionCodeSet.add("AL"); + regionCodeSet.add("AM"); + regionCodeSet.add("AO"); + regionCodeSet.add("AR"); + regionCodeSet.add("AS"); + regionCodeSet.add("AT"); + regionCodeSet.add("AU"); + regionCodeSet.add("AW"); + regionCodeSet.add("AX"); + regionCodeSet.add("AZ"); + regionCodeSet.add("BA"); + regionCodeSet.add("BB"); + regionCodeSet.add("BD"); + regionCodeSet.add("BE"); + regionCodeSet.add("BF"); + regionCodeSet.add("BG"); + regionCodeSet.add("BH"); + regionCodeSet.add("BI"); + regionCodeSet.add("BJ"); + regionCodeSet.add("BL"); + regionCodeSet.add("BM"); + regionCodeSet.add("BN"); + regionCodeSet.add("BO"); + regionCodeSet.add("BQ"); + regionCodeSet.add("BR"); + regionCodeSet.add("BS"); + regionCodeSet.add("BT"); + regionCodeSet.add("BW"); + regionCodeSet.add("BY"); + regionCodeSet.add("BZ"); + regionCodeSet.add("CA"); + regionCodeSet.add("CC"); + regionCodeSet.add("CD"); + regionCodeSet.add("CF"); + regionCodeSet.add("CG"); + regionCodeSet.add("CH"); + regionCodeSet.add("CI"); + regionCodeSet.add("CK"); + regionCodeSet.add("CL"); + regionCodeSet.add("CM"); + regionCodeSet.add("CN"); + regionCodeSet.add("CO"); + regionCodeSet.add("CR"); + regionCodeSet.add("CU"); + regionCodeSet.add("CV"); + regionCodeSet.add("CW"); + regionCodeSet.add("CX"); + regionCodeSet.add("CY"); + regionCodeSet.add("CZ"); + regionCodeSet.add("DE"); + regionCodeSet.add("DJ"); + regionCodeSet.add("DK"); + regionCodeSet.add("DM"); + regionCodeSet.add("DO"); + regionCodeSet.add("DZ"); + regionCodeSet.add("EC"); + regionCodeSet.add("EE"); + regionCodeSet.add("EG"); + regionCodeSet.add("EH"); + regionCodeSet.add("ER"); + regionCodeSet.add("ES"); + regionCodeSet.add("ET"); + regionCodeSet.add("FI"); + regionCodeSet.add("FJ"); + regionCodeSet.add("FK"); + regionCodeSet.add("FM"); + regionCodeSet.add("FO"); + regionCodeSet.add("FR"); + regionCodeSet.add("GA"); + regionCodeSet.add("GB"); + regionCodeSet.add("GD"); + regionCodeSet.add("GE"); + regionCodeSet.add("GF"); + regionCodeSet.add("GG"); + regionCodeSet.add("GH"); + regionCodeSet.add("GI"); + regionCodeSet.add("GL"); + regionCodeSet.add("GM"); + regionCodeSet.add("GN"); + regionCodeSet.add("GP"); + regionCodeSet.add("GR"); + regionCodeSet.add("GT"); + regionCodeSet.add("GU"); + regionCodeSet.add("GW"); + regionCodeSet.add("GY"); + regionCodeSet.add("HK"); + regionCodeSet.add("HN"); + regionCodeSet.add("HR"); + regionCodeSet.add("HT"); + regionCodeSet.add("HU"); + regionCodeSet.add("ID"); + regionCodeSet.add("IE"); + regionCodeSet.add("IL"); + regionCodeSet.add("IM"); + regionCodeSet.add("IN"); + regionCodeSet.add("IQ"); + regionCodeSet.add("IR"); + regionCodeSet.add("IS"); + regionCodeSet.add("IT"); + regionCodeSet.add("JE"); + regionCodeSet.add("JM"); + regionCodeSet.add("JO"); + regionCodeSet.add("JP"); + regionCodeSet.add("KE"); + regionCodeSet.add("KG"); + regionCodeSet.add("KH"); + regionCodeSet.add("KI"); + regionCodeSet.add("KM"); + regionCodeSet.add("KN"); + regionCodeSet.add("KP"); + regionCodeSet.add("KR"); + regionCodeSet.add("KW"); + regionCodeSet.add("KY"); + regionCodeSet.add("KZ"); + regionCodeSet.add("LA"); + regionCodeSet.add("LB"); + regionCodeSet.add("LC"); + regionCodeSet.add("LI"); + regionCodeSet.add("LK"); + regionCodeSet.add("LR"); + regionCodeSet.add("LS"); + regionCodeSet.add("LT"); + regionCodeSet.add("LU"); + regionCodeSet.add("LV"); + regionCodeSet.add("LY"); + regionCodeSet.add("MA"); + regionCodeSet.add("MC"); + regionCodeSet.add("MD"); + regionCodeSet.add("ME"); + regionCodeSet.add("MF"); + regionCodeSet.add("MG"); + regionCodeSet.add("MH"); + regionCodeSet.add("MK"); + regionCodeSet.add("ML"); + regionCodeSet.add("MM"); + regionCodeSet.add("MN"); + regionCodeSet.add("MO"); + regionCodeSet.add("MP"); + regionCodeSet.add("MQ"); + regionCodeSet.add("MR"); + regionCodeSet.add("MS"); + regionCodeSet.add("MT"); + regionCodeSet.add("MU"); + regionCodeSet.add("MV"); + regionCodeSet.add("MW"); + regionCodeSet.add("MX"); + regionCodeSet.add("MY"); + regionCodeSet.add("MZ"); + regionCodeSet.add("NA"); + regionCodeSet.add("NC"); + regionCodeSet.add("NE"); + regionCodeSet.add("NF"); + regionCodeSet.add("NG"); + regionCodeSet.add("NI"); + regionCodeSet.add("NL"); + regionCodeSet.add("NO"); + regionCodeSet.add("NP"); + regionCodeSet.add("NR"); + regionCodeSet.add("NU"); + regionCodeSet.add("NZ"); + regionCodeSet.add("OM"); + regionCodeSet.add("PA"); + regionCodeSet.add("PE"); + regionCodeSet.add("PF"); + regionCodeSet.add("PG"); + regionCodeSet.add("PH"); + regionCodeSet.add("PK"); + regionCodeSet.add("PL"); + regionCodeSet.add("PM"); + regionCodeSet.add("PR"); + regionCodeSet.add("PS"); + regionCodeSet.add("PT"); + regionCodeSet.add("PW"); + regionCodeSet.add("PY"); + regionCodeSet.add("QA"); + regionCodeSet.add("RE"); + regionCodeSet.add("RO"); + regionCodeSet.add("RS"); + regionCodeSet.add("RU"); + regionCodeSet.add("RW"); + regionCodeSet.add("SA"); + regionCodeSet.add("SB"); + regionCodeSet.add("SC"); + regionCodeSet.add("SD"); + regionCodeSet.add("SE"); + regionCodeSet.add("SG"); + regionCodeSet.add("SH"); + regionCodeSet.add("SI"); + regionCodeSet.add("SJ"); + regionCodeSet.add("SK"); + regionCodeSet.add("SL"); + regionCodeSet.add("SM"); + regionCodeSet.add("SN"); + regionCodeSet.add("SO"); + regionCodeSet.add("SR"); + regionCodeSet.add("SS"); + regionCodeSet.add("ST"); + regionCodeSet.add("SV"); + regionCodeSet.add("SX"); + regionCodeSet.add("SY"); + regionCodeSet.add("SZ"); + regionCodeSet.add("TC"); + regionCodeSet.add("TD"); + regionCodeSet.add("TG"); + regionCodeSet.add("TH"); + regionCodeSet.add("TJ"); + regionCodeSet.add("TL"); + regionCodeSet.add("TM"); + regionCodeSet.add("TN"); + regionCodeSet.add("TO"); + regionCodeSet.add("TR"); + regionCodeSet.add("TT"); + regionCodeSet.add("TV"); + regionCodeSet.add("TW"); + regionCodeSet.add("TZ"); + regionCodeSet.add("UA"); + regionCodeSet.add("UG"); + regionCodeSet.add("US"); + regionCodeSet.add("UY"); + regionCodeSet.add("UZ"); + regionCodeSet.add("VA"); + regionCodeSet.add("VC"); + regionCodeSet.add("VE"); + regionCodeSet.add("VG"); + regionCodeSet.add("VI"); + regionCodeSet.add("VN"); + regionCodeSet.add("VU"); + regionCodeSet.add("WF"); + regionCodeSet.add("WS"); + regionCodeSet.add("XK"); + regionCodeSet.add("YE"); + regionCodeSet.add("YT"); + regionCodeSet.add("ZA"); + regionCodeSet.add("ZM"); + regionCodeSet.add("ZW"); + + return regionCodeSet; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/PhoneNumberMetadataForGoldenTests.xml b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/PhoneNumberMetadataForGoldenTests.xml new file mode 100644 index 0000000000..d6299aefd5 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/PhoneNumberMetadataForGoldenTests.xml @@ -0,0 +1,192 @@ + + + + + + http://www.itu.int/oth/T02020000AF/en + + + + [46]\d{4}| + [01589]\d{5} + + + + + 6[2-467]\d{3} + + + 62889 + + + 4\d{4} + + 40123 + + + [01589]\d{5} + + 542011 + + + + + + + http://www.itu.int/oth/T0202000009/en + + + + [68] + $1-$2-$3 + + + [2-9] + $1-$2 + NA + + + 911 + $2 15-$3-$4 + $1 $2 $3-$4 + + + 1 + $1 $2-$3 + + + + + 11\d{8}| + [2368]\d{9}| + 9\d{10} + + + + 810\d{7} + + 8101234567 + + + 11\d{8} + + 1123456789 + + + 810\d{7} + + 8101234567 + + + + + + + http://www.nationalnanpa.com/nas/public/assigned_code_query_step1.do?method=resetCodeQueryModel + + + [5689]\d{9} + + + + 671(?: + 3(?: + 00| + 3[39]| + 4[349]| + 55| + 6[26] + )| + 4(?: + 56| + 7[1-9]| + 8[236-9] + ) + )\d{4} + + + 6713001234 + + + + + 671(?: + 3(?: + 00| + 3[39]| + 4[349]| + 55| + 6[26] + )| + 4(?: + 56| + 7[1-9]| + 8[236-9] + ) + )\d{4} + + + 6713001234 + + + + 8(?: + 00| + 33| + 44| + 55| + 66| + 77| + 88 + )[2-9]\d{6} + + + 8002123456 + + + 900[2-9]\d{6} + + 9002123456 + + + + 5(?: + 00| + 22| + 33| + 44| + 66| + 77| + 88 + )[2-9]\d{6} + + + 5002345678 + + + + + + + http://www.itu.int/rec/T-REC-E.169-200205-I/en + + + + $1 $2 $3 + + + + \d{9} + + + \d{9} + + 123456789 + + + + diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/ShortNumberMetadataForGoldenTests.xml b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/ShortNumberMetadataForGoldenTests.xml new file mode 100644 index 0000000000..0adacbc41c --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/ShortNumberMetadataForGoldenTests.xml @@ -0,0 +1,117 @@ + + + + + + + 9\d{2} + + + 911 + + 911 + + + + 911 + + 911 + + + + + + + + + [01389]\d{1,4} + + + + 000| + 1(?: + 0[0-35-7]| + 1[02-5]| + 2[15]| + 9 + )| + 3372| + 89338| + 911 + + + 121 + + + + + [09]\d{2}| + 1(?: + [02-9]\d?| + 1[0-24-9]? + ) + + + 111 + + + + + + 89338| + 911 + + + 89338 + + + + + + 10[017]| + 911 + + + 101 + + + 10[356] + + 103 + + + + + 3372| + 89338 + + + 3372 + + + + + + + + 9\d{2} + + + 911 + + 911 + + + + 911 + + 911 + + + + diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_metadata.js b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_metadata.js new file mode 100644 index 0000000000..831b3da374 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_metadata.js @@ -0,0 +1,159 @@ +/** + * @license + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generated metadata for file + * googledata/third_party/i18n/phonenumbers/PhoneNumberMetadata.xml + * @author Nikolaos Trogkanis + */ + +goog.provide('i18n.phonenumbers.metadata'); + +/** + * A mapping from a country calling code to the region codes which denote the + * region represented by that country calling code. In the case of multiple + * countries sharing a calling code, such as the NANPA regions, the one + * indicated with "isMainCountryForCode" in the metadata should be first. + * @type {!Object.>} + */ +i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = { +1:["GU"] +,54:["AR"] +,247:["AC"] +,979:["001"] +}; + +/** + * A mapping from a region code to the PhoneMetadata for that region. + * @type {!Object.} + */ +i18n.phonenumbers.metadata.countryToMetadata = { +"AC":[,[,,"[46]\\d{4}|[01589]\\d{5}",,,,,,,[5,6] +] +,[,,"6[2-467]\\d{3}",,,,"62889",,,[5] +] +,[,,"4\\d{4}",,,,"40123",,,[5] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,"AC",247,"00",,,,,,,,,,[,,,,,,,,,[-1] +] +,,,[,,,,,,,,,[-1] +] +,[,,"[01589]\\d{5}",,,,"542011",,,[6] +] +,,,[,,,,,,,,,[-1] +] +] +,"AR":[,[,,"11\\d{8}|[2368]\\d{9}|9\\d{10}",,,,,,,[10] +,[6,7,8] +] +,[,,"11\\d{8}",,,,"1123456789",,,,[6,7,8] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,"AR",54,"00","0",,,"0?(?:(11)?15)?","9$1",,,[[,"([68]\\d{2})(\\d{3})(\\d{4})","$1-$2-$3",["[68]"] +,"0$1"] +,[,"(\\d{2})(\\d{4})","$1-$2",["[2-9]"] +,"$1"] +,[,"(9)(11)(\\d{4})(\\d{4})","$2 15-$3-$4",["911"] +,"0$1"] +,[,"(11)(\\d{4})(\\d{4})","$1 $2-$3",["1"] +,"0$1",,1] +] +,[[,"([68]\\d{2})(\\d{3})(\\d{4})","$1-$2-$3",["[68]"] +,"0$1"] +,[,"(9)(11)(\\d{4})(\\d{4})","$1 $2 $3-$4",["911"] +] +,[,"(11)(\\d{4})(\\d{4})","$1 $2-$3",["1"] +,"0$1",,1] +] +,[,,,,,,,,,[-1] +] +,,,[,,"810\\d{7}",,,,"8101234567"] +,[,,"810\\d{7}",,,,"8101234567"] +,,,[,,,,,,,,,[-1] +] +] +,"GU":[,[,,"[5689]\\d{9}",,,,,,,[10] +,[7] +] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[236-9]))\\d{4}",,,,"6713001234",,,,[7] +] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[236-9]))\\d{4}",,,,"6713001234",,,,[7] +] +,[,,"8(?:00|33|44|55|66|77|88)[2-9]\\d{6}",,,,"8002123456"] +,[,,"900[2-9]\\d{6}",,,,"9002123456"] +,[,,,,,,,,,[-1] +] +,[,,"5(?:00|22|33|44|66|77|88)[2-9]\\d{6}",,,,"5002345678"] +,[,,,,,,,,,[-1] +] +,"GU",1,"011","1",,,"1",,,1,,,[,,,,,,,,,[-1] +] +,,"671",[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,,[,,,,,,,,,[-1] +] +] +,"979":[,[,,"\\d{9}",,,,,,,[9] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,"\\d{9}",,,,"123456789"] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,"001",979,,,,,,,,1,[[,"(\\d)(\\d{4})(\\d{4})","$1 $2 $3"] +] +,,[,,,,,,,,,[-1] +] +,,,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,,[,,,,,,,,,[-1] +] +] +}; diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_shortnumbermetadata.js b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_shortnumbermetadata.js new file mode 100644 index 0000000000..94be19ce52 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/buildtools/testdata/expected_shortnumbermetadata.js @@ -0,0 +1,88 @@ +/** + * @license + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generated metadata for file + * googledata/third_party/i18n/phonenumbers/ShortNumberMetadata.xml + * @author Nikolaos Trogkanis + */ + +goog.provide('i18n.phonenumbers.shortnumbergoldenmetadata'); + +/** + * A mapping from a country calling code to the region codes which denote the + * region represented by that country calling code. In the case of multiple + * countries sharing a calling code, such as the NANPA regions, the one + * indicated with "isMainCountryForCode" in the metadata should be first. + * @type {!Object.>} + */ +i18n.phonenumbers.shortnumbergoldenmetadata.countryCodeToRegionCodeMap = { +0:["AC","AR","GU"] +}; + +/** + * A mapping from a region code to the PhoneMetadata for that region. + * @type {!Object.} + */ +i18n.phonenumbers.shortnumbergoldenmetadata.countryToMetadata = { +"AC":[,[,,"9\\d{2}",,,,,,,[3] +] +,,,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,,,"AC",,,,,,,,,,,,,,,,,,[,,"911",,,,"911"] +,,[,,"911",,,,"911"] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,[,,,,,,,,,[-1] +] +] +,"AR":[,[,,"[01389]\\d{1,4}",,,,,,,[2,3,4,5] +] +,,,[,,"[09]\\d{2}|1(?:[02-9]\\d?|1[0-24-9]?)",,,,"111",,,[2,3] +] +,[,,,,,,,,,[-1] +] +,,,,"AR",,,,,,,,,,,,,,,,,,[,,"10[017]|911",,,,"101",,,[3] +] +,,[,,"000|1(?:0[0-35-7]|1[02-5]|2[15]|9)|3372|89338|911",,,,"121"] +,[,,,,,,,,,[-1] +] +,[,,"89338|911",,,,"89338",,,[3,5] +] +,,[,,"3372|89338",,,,"3372",,,[4,5] +] +] +,"GU":[,[,,"9\\d{2}",,,,,,,[3] +] +,,,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,,,"GU",,,,,,,,,,,,,,,,,,[,,"911",,,,"911"] +,,[,,"911",,,,"911"] +,[,,,,,,,,,[-1] +] +,[,,,,,,,,,[-1] +] +,,[,,,,,,,,,[-1] +] +] +}; diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 new file mode 100644 index 0000000000..1510187d46 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_255 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 new file mode 100644 index 0000000000..3d86d493cb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_27 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 new file mode 100644 index 0000000000..72ac06a4a2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_30 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 new file mode 100644 index 0000000000..c5abeb6858 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_31 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 new file mode 100644 index 0000000000..fdef134299 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_34 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 new file mode 100644 index 0000000000..a404c3e891 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_350 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 new file mode 100644 index 0000000000..7496756575 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_351 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 new file mode 100644 index 0000000000..684e8e1e61 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_352 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 new file mode 100644 index 0000000000..c6148a8628 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_358 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 new file mode 100644 index 0000000000..e04014289d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_359 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 new file mode 100644 index 0000000000..f979aacc26 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_36 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 new file mode 100644 index 0000000000..6e38688c07 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_372 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 new file mode 100644 index 0000000000..7207f15f7e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_373 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 new file mode 100644 index 0000000000..426f6f89c7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_380 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 new file mode 100644 index 0000000000..2d5605b80e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_381 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 new file mode 100644 index 0000000000..161558328e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_385 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 new file mode 100644 index 0000000000..06f4b99f6c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_39 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 new file mode 100644 index 0000000000..175243cfdc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_43 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 new file mode 100644 index 0000000000..244a842c28 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_44 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 new file mode 100644 index 0000000000..b5335e7ed2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_49 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 new file mode 100644 index 0000000000..2f7b212cf0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_505 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 new file mode 100644 index 0000000000..2b6dd35943 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_506 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 new file mode 100644 index 0000000000..e23beaabe1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_52 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 new file mode 100644 index 0000000000..ff52ce4cc1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_54 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 new file mode 100644 index 0000000000..21d60dc6d3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_55 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 new file mode 100644 index 0000000000..2eafd93ee4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_58 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 new file mode 100644 index 0000000000..9b3af0a9ae Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_595 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 new file mode 100644 index 0000000000..0ec23d5729 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_61 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 new file mode 100644 index 0000000000..a17ebbbf3d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_62 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 new file mode 100644 index 0000000000..77374df900 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_64 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 new file mode 100644 index 0000000000..3dd783aed6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_66 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 new file mode 100644 index 0000000000..7355c1babc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_675 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 new file mode 100644 index 0000000000..64625de937 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_676 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 new file mode 100644 index 0000000000..a501a87f08 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_679 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 new file mode 100644 index 0000000000..f74102b958 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_7 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 new file mode 100644 index 0000000000..db17512850 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_81 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 new file mode 100644 index 0000000000..3db56a2563 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_84 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 new file mode 100644 index 0000000000..07537c978e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_855 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 new file mode 100644 index 0000000000..7a56715715 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_856 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 new file mode 100644 index 0000000000..ecd338a121 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_90 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 new file mode 100644 index 0000000000..49b1ee6e9e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_91 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 new file mode 100644 index 0000000000..36fbcee849 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_94 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 new file mode 100644 index 0000000000..853cd55bc5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_95 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 new file mode 100644 index 0000000000..42c771c756 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_971 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 new file mode 100644 index 0000000000..dfa294c229 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_972 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 new file mode 100644 index 0000000000..152bf34840 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto_995 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 new file mode 100644 index 0000000000..76b8bf2c7d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_800 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 new file mode 100644 index 0000000000..c43d67c807 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_808 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 new file mode 100644 index 0000000000..45c6e6c557 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_870 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 new file mode 100644 index 0000000000..ada9c95fe8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_878 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 new file mode 100644 index 0000000000..78b3256834 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_881 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 new file mode 100644 index 0000000000..fe026b0d69 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_882 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 new file mode 100644 index 0000000000..56b7d66090 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_883 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 new file mode 100644 index 0000000000..634ecce02e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_888 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 new file mode 100644 index 0000000000..89f33ec6ca Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_979 differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC new file mode 100644 index 0000000000..e5b1e8f20d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD new file mode 100644 index 0000000000..708a118b46 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE new file mode 100644 index 0000000000..3ec1512110 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF new file mode 100644 index 0000000000..b16f32963a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG new file mode 100644 index 0000000000..6118d9c1e1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI new file mode 100644 index 0000000000..0f145839ed Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL new file mode 100644 index 0000000000..9e80663c72 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM new file mode 100644 index 0000000000..0b71623998 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO new file mode 100644 index 0000000000..5345c505b4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR new file mode 100644 index 0000000000..7554f2df06 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS new file mode 100644 index 0000000000..ce57e4b5c8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT new file mode 100644 index 0000000000..124ad972d3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU new file mode 100644 index 0000000000..e2d65cd669 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW new file mode 100644 index 0000000000..1671079ae4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX new file mode 100644 index 0000000000..f89f906be8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ new file mode 100644 index 0000000000..21bb446caf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA new file mode 100644 index 0000000000..9f8e63bdc3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB new file mode 100644 index 0000000000..5cd771bf54 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD new file mode 100644 index 0000000000..5c4cb85a70 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE new file mode 100644 index 0000000000..fc413d6fa8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF new file mode 100644 index 0000000000..8375abe516 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG new file mode 100644 index 0000000000..503a558160 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH new file mode 100644 index 0000000000..0483e11c7e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI new file mode 100644 index 0000000000..0ee448eac3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ new file mode 100644 index 0000000000..38990a8995 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL new file mode 100644 index 0000000000..706168429c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM new file mode 100644 index 0000000000..dc8bf14fb1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN new file mode 100644 index 0000000000..2e5a9d8c56 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO new file mode 100644 index 0000000000..028a73fead Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ new file mode 100644 index 0000000000..b2aa5b880a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR new file mode 100644 index 0000000000..4722a6b884 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS new file mode 100644 index 0000000000..8223c67ee5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT new file mode 100644 index 0000000000..3a2a40c44a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW new file mode 100644 index 0000000000..0f877729f0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY new file mode 100644 index 0000000000..b5615e3466 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ new file mode 100644 index 0000000000..feac3a5b88 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA new file mode 100644 index 0000000000..18a08a5dc3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC new file mode 100644 index 0000000000..226552455f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD new file mode 100644 index 0000000000..dea8bcb416 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF new file mode 100644 index 0000000000..464e15519f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG new file mode 100644 index 0000000000..f12515e161 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH new file mode 100644 index 0000000000..ddbc79cac1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI new file mode 100644 index 0000000000..eacc997bba Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK new file mode 100644 index 0000000000..0b268b4bd6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL new file mode 100644 index 0000000000..0b4069634e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM new file mode 100644 index 0000000000..0dea728944 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN new file mode 100644 index 0000000000..43dc62fb8e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO new file mode 100644 index 0000000000..fa2b7deeb7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR new file mode 100644 index 0000000000..f0201674da Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU new file mode 100644 index 0000000000..795fd07218 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV new file mode 100644 index 0000000000..cbc793c896 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW new file mode 100644 index 0000000000..78e8c9f74c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX new file mode 100644 index 0000000000..bbd0e4d82b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY new file mode 100644 index 0000000000..3ed050adfd Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ new file mode 100644 index 0000000000..686d18a65a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE new file mode 100644 index 0000000000..250769a0e4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ new file mode 100644 index 0000000000..c4174f1e2c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK new file mode 100644 index 0000000000..b2af72b656 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM new file mode 100644 index 0000000000..d6b4f64fc2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO new file mode 100644 index 0000000000..8d9d06cbbb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ new file mode 100644 index 0000000000..fe704f355c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC new file mode 100644 index 0000000000..726b61cde5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE new file mode 100644 index 0000000000..75f93bd99a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG new file mode 100644 index 0000000000..5270ea38a6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH new file mode 100644 index 0000000000..d470ee3abe Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER new file mode 100644 index 0000000000..9ac4c6955a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ER differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES new file mode 100644 index 0000000000..f686b949d9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET new file mode 100644 index 0000000000..7988307b13 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ET differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI new file mode 100644 index 0000000000..0a0c7a0709 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ new file mode 100644 index 0000000000..303845b68e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK new file mode 100644 index 0000000000..f931d3bf2d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM new file mode 100644 index 0000000000..6fd391e565 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO new file mode 100644 index 0000000000..6637ff15c8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR new file mode 100644 index 0000000000..3d3ebbb4ff Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_FR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA new file mode 100644 index 0000000000..68a02bd132 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB new file mode 100644 index 0000000000..8c6657cf07 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD new file mode 100644 index 0000000000..b3057866dc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE new file mode 100644 index 0000000000..8f2cbfb6d2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF new file mode 100644 index 0000000000..2c27a29290 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG new file mode 100644 index 0000000000..7860e3113f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH new file mode 100644 index 0000000000..20a93cdc3a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI new file mode 100644 index 0000000000..9d235f9d4c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL new file mode 100644 index 0000000000..6881e2bbc9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM new file mode 100644 index 0000000000..5e62ed5a37 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN new file mode 100644 index 0000000000..a5be8c8439 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP new file mode 100644 index 0000000000..3c4e10e9cc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ new file mode 100644 index 0000000000..3f6a6da632 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR new file mode 100644 index 0000000000..75dd781eb8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT new file mode 100644 index 0000000000..c1c0d4f39f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU new file mode 100644 index 0000000000..54d99db7a4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW new file mode 100644 index 0000000000..3fdee90061 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY new file mode 100644 index 0000000000..eee7fc4fae Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_GY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK new file mode 100644 index 0000000000..3520b154d5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN new file mode 100644 index 0000000000..64788dcae1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR new file mode 100644 index 0000000000..76ba85efb8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT new file mode 100644 index 0000000000..057bee3e65 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU new file mode 100644 index 0000000000..7238138dd7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID new file mode 100644 index 0000000000..0a67a1a27a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ID differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE new file mode 100644 index 0000000000..9d9c82c169 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL new file mode 100644 index 0000000000..024675b99e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM new file mode 100644 index 0000000000..42f4bdf4f3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN new file mode 100644 index 0000000000..9e10ced9a4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO new file mode 100644 index 0000000000..9a9d77e5a0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ new file mode 100644 index 0000000000..d0d8e4cfaa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR new file mode 100644 index 0000000000..8f254a22cf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS new file mode 100644 index 0000000000..b1f7eb0292 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT new file mode 100644 index 0000000000..a07ef18283 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE new file mode 100644 index 0000000000..3a6542d64d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM new file mode 100644 index 0000000000..4b97837fca Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO new file mode 100644 index 0000000000..14bcd58a47 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP new file mode 100644 index 0000000000..1568a8f57e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE new file mode 100644 index 0000000000..8e10e28d41 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG new file mode 100644 index 0000000000..41797005fc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH new file mode 100644 index 0000000000..0156233aca Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI new file mode 100644 index 0000000000..e1beb0cdd9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM new file mode 100644 index 0000000000..483658cb93 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN new file mode 100644 index 0000000000..c249995264 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP new file mode 100644 index 0000000000..a12d7deeeb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR new file mode 100644 index 0000000000..ce4de56369 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW new file mode 100644 index 0000000000..27e1c8cf14 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY new file mode 100644 index 0000000000..95bed5e01f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ new file mode 100644 index 0000000000..346ae181e9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_KZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA new file mode 100644 index 0000000000..39c98b7375 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB new file mode 100644 index 0000000000..31946984c6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC new file mode 100644 index 0000000000..6820248c9e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI new file mode 100644 index 0000000000..db5e577972 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK new file mode 100644 index 0000000000..89a060b615 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR new file mode 100644 index 0000000000..c69e3ae3e9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS new file mode 100644 index 0000000000..68261efa7c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT new file mode 100644 index 0000000000..521df976c2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU new file mode 100644 index 0000000000..63217e0cfa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV new file mode 100644 index 0000000000..07323a7ed3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY new file mode 100644 index 0000000000..ccf6d2baef Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_LY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA new file mode 100644 index 0000000000..3c13bd9647 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC new file mode 100644 index 0000000000..34a35da4cd Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD new file mode 100644 index 0000000000..bd5d320624 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME new file mode 100644 index 0000000000..94f2430774 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ME differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF new file mode 100644 index 0000000000..dc4373bbb2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG new file mode 100644 index 0000000000..53d307b1f5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH new file mode 100644 index 0000000000..f9424efc7d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK new file mode 100644 index 0000000000..12b2210e5c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML new file mode 100644 index 0000000000..817f806046 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ML differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM new file mode 100644 index 0000000000..ec27b2c48c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN new file mode 100644 index 0000000000..1039995371 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO new file mode 100644 index 0000000000..b7e0c23fb3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP new file mode 100644 index 0000000000..c7659bad3e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ new file mode 100644 index 0000000000..ea6af790b6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR new file mode 100644 index 0000000000..fd7282a2db Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS new file mode 100644 index 0000000000..1a8393a0b1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT new file mode 100644 index 0000000000..1d9fa0604d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU new file mode 100644 index 0000000000..8780975977 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV new file mode 100644 index 0000000000..3e121e0a41 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW new file mode 100644 index 0000000000..7ff74bab1a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX new file mode 100644 index 0000000000..d33f966fb2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY new file mode 100644 index 0000000000..efad3c5bc2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ new file mode 100644 index 0000000000..c45028701b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA new file mode 100644 index 0000000000..fe4623de2e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC new file mode 100644 index 0000000000..ce01121470 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE new file mode 100644 index 0000000000..fb42930d36 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF new file mode 100644 index 0000000000..923bb18283 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG new file mode 100644 index 0000000000..b14cb361aa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI new file mode 100644 index 0000000000..3cc901dab1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL new file mode 100644 index 0000000000..3cd0ab0e03 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO new file mode 100644 index 0000000000..b807aa3dea Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP new file mode 100644 index 0000000000..ee2edd26be Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR new file mode 100644 index 0000000000..20864a9a59 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU new file mode 100644 index 0000000000..47b5118856 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ new file mode 100644 index 0000000000..34fd143c18 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_NZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM new file mode 100644 index 0000000000..7cf9a03d86 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_OM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA new file mode 100644 index 0000000000..014e949f77 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE new file mode 100644 index 0000000000..c8fffa02ec Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF new file mode 100644 index 0000000000..8e4c6f09e6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG new file mode 100644 index 0000000000..95fd8f4392 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH new file mode 100644 index 0000000000..e3ce4c51a6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK new file mode 100644 index 0000000000..37210beb31 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL new file mode 100644 index 0000000000..2fe18a2847 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM new file mode 100644 index 0000000000..592f052a1e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR new file mode 100644 index 0000000000..253a5eda92 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS new file mode 100644 index 0000000000..6ccfbb7f27 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT new file mode 100644 index 0000000000..1cb1fb6fe6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW new file mode 100644 index 0000000000..3783c6a81e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY new file mode 100644 index 0000000000..b1f8f3e7c8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA new file mode 100644 index 0000000000..f7b7f33ad4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_QA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE new file mode 100644 index 0000000000..1efaf2b721 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO new file mode 100644 index 0000000000..c2a71717e7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS new file mode 100644 index 0000000000..87cc3ffdb7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU new file mode 100644 index 0000000000..73562cace6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW new file mode 100644 index 0000000000..9538d1a644 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_RW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA new file mode 100644 index 0000000000..f8c860238a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB new file mode 100644 index 0000000000..539014c75c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC new file mode 100644 index 0000000000..0340ea64c9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD new file mode 100644 index 0000000000..e6b07106e7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE new file mode 100644 index 0000000000..5d862048e9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG new file mode 100644 index 0000000000..a9959bfa54 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH new file mode 100644 index 0000000000..2c6bbd1f8d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI new file mode 100644 index 0000000000..1a01783c99 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ new file mode 100644 index 0000000000..a475b19afc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK new file mode 100644 index 0000000000..e2788862fb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL new file mode 100644 index 0000000000..94038f18a2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM new file mode 100644 index 0000000000..df14671319 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN new file mode 100644 index 0000000000..ad8bad1a71 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO new file mode 100644 index 0000000000..c4a80bded3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR new file mode 100644 index 0000000000..a1965d0cda Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS new file mode 100644 index 0000000000..7c1a82a1e9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST new file mode 100644 index 0000000000..63ffc4404b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV new file mode 100644 index 0000000000..95054b58ac Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX new file mode 100644 index 0000000000..9d1c0e242c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY new file mode 100644 index 0000000000..3228df26c9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ new file mode 100644 index 0000000000..ce335be555 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA new file mode 100644 index 0000000000..248ff7c0c8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC new file mode 100644 index 0000000000..75da36f588 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD new file mode 100644 index 0000000000..719ade9853 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG new file mode 100644 index 0000000000..23c0f80878 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH new file mode 100644 index 0000000000..d8f9f301a6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ new file mode 100644 index 0000000000..ee20c517a9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK new file mode 100644 index 0000000000..f6092ebf3d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL new file mode 100644 index 0000000000..b969919d64 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM new file mode 100644 index 0000000000..a0508897bf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN new file mode 100644 index 0000000000..926d10400b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO new file mode 100644 index 0000000000..5a0b0a8f6a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR new file mode 100644 index 0000000000..8392e637dd Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT new file mode 100644 index 0000000000..99b760fa51 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV new file mode 100644 index 0000000000..47f5bcb867 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW new file mode 100644 index 0000000000..10970e4122 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ new file mode 100644 index 0000000000..670561c94f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA new file mode 100644 index 0000000000..72e05da797 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG new file mode 100644 index 0000000000..84eb43935a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US new file mode 100644 index 0000000000..65e034d428 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_US differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY new file mode 100644 index 0000000000..544748e7d8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ new file mode 100644 index 0000000000..e7f52e54b5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_UZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA new file mode 100644 index 0000000000..b595164fb4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC new file mode 100644 index 0000000000..1b04808283 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE new file mode 100644 index 0000000000..bdfb7d7b63 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG new file mode 100644 index 0000000000..9629cb595f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI new file mode 100644 index 0000000000..a0a7941882 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN new file mode 100644 index 0000000000..33692697f9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU new file mode 100644 index 0000000000..151e425973 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_VU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF new file mode 100644 index 0000000000..1f75adeca9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS new file mode 100644 index 0000000000..0efa97a1c1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_WS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK new file mode 100644 index 0000000000..eb7e6292d3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_XK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE new file mode 100644 index 0000000000..615db52ed0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT new file mode 100644 index 0000000000..749d8675a7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA new file mode 100644 index 0000000000..23bc348b1f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM new file mode 100644 index 0000000000..52e4c4a5be Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW new file mode 100644 index 0000000000..a4b68429dc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC new file mode 100644 index 0000000000..31befc231f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD new file mode 100644 index 0000000000..614e70c775 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE new file mode 100644 index 0000000000..e9968bba15 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF new file mode 100644 index 0000000000..0bc1491690 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG new file mode 100644 index 0000000000..0cb86c9099 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI new file mode 100644 index 0000000000..0b4d4fee13 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL new file mode 100644 index 0000000000..60db0b0940 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM new file mode 100644 index 0000000000..cbecebe4fa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO new file mode 100644 index 0000000000..9565c32236 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR new file mode 100644 index 0000000000..a056cd2373 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS new file mode 100644 index 0000000000..b25ab705de Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT new file mode 100644 index 0000000000..ffce32def9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU new file mode 100644 index 0000000000..e64990eaef Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW new file mode 100644 index 0000000000..960a9b2590 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX new file mode 100644 index 0000000000..8fcd3f9444 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ new file mode 100644 index 0000000000..373615b64f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_AZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA new file mode 100644 index 0000000000..aa64520819 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB new file mode 100644 index 0000000000..6b94258553 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD new file mode 100644 index 0000000000..2d91d8a2e3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE new file mode 100644 index 0000000000..3967c15c35 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF new file mode 100644 index 0000000000..73cbb89a45 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG new file mode 100644 index 0000000000..c9cee1453d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH new file mode 100644 index 0000000000..4c048fb12f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI new file mode 100644 index 0000000000..833325ee36 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ new file mode 100644 index 0000000000..cc5edf442b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL new file mode 100644 index 0000000000..8a9eeb543c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM new file mode 100644 index 0000000000..24ee0a145d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN new file mode 100644 index 0000000000..ae3b1f1972 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO new file mode 100644 index 0000000000..52c1ece21f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ new file mode 100644 index 0000000000..e33f379a9d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR new file mode 100644 index 0000000000..a2d1f1a033 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS new file mode 100644 index 0000000000..ed383266f4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT new file mode 100644 index 0000000000..47a4c6c19a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW new file mode 100644 index 0000000000..346bfb444c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY new file mode 100644 index 0000000000..5a9cce9d21 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ new file mode 100644 index 0000000000..255205afa8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_BZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA new file mode 100644 index 0000000000..3a78361e88 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC new file mode 100644 index 0000000000..500a225897 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD new file mode 100644 index 0000000000..1b326c9ef0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF new file mode 100644 index 0000000000..5d82f6188d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG new file mode 100644 index 0000000000..3d37a798f1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH new file mode 100644 index 0000000000..fcafbbebee Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI new file mode 100644 index 0000000000..a389c339b5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK new file mode 100644 index 0000000000..c4e5176fd7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL new file mode 100644 index 0000000000..87c02839b2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM new file mode 100644 index 0000000000..7625824089 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN new file mode 100644 index 0000000000..062fdcaff6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO new file mode 100644 index 0000000000..51b6508a15 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR new file mode 100644 index 0000000000..796fb16da9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU new file mode 100644 index 0000000000..2d18cf7da9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV new file mode 100644 index 0000000000..f97fc8ac85 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW new file mode 100644 index 0000000000..2c8cb66178 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX new file mode 100644 index 0000000000..9b91cf86d8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY new file mode 100644 index 0000000000..7feb7f8711 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ new file mode 100644 index 0000000000..b5cfbdc7a8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_CZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE new file mode 100644 index 0000000000..2895ccce16 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ new file mode 100644 index 0000000000..2457a13da1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK new file mode 100644 index 0000000000..b6e571bae1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM new file mode 100644 index 0000000000..c5264b25ed Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO new file mode 100644 index 0000000000..ca339572e3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ new file mode 100644 index 0000000000..f5695a193c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_DZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC new file mode 100644 index 0000000000..a42e53b9d3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE new file mode 100644 index 0000000000..e1448ef237 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG new file mode 100644 index 0000000000..9ff6e65376 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH new file mode 100644 index 0000000000..80c491c970 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_EH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER new file mode 100644 index 0000000000..e298284dcf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ER differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES new file mode 100644 index 0000000000..c4b40539de Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ES differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET new file mode 100644 index 0000000000..9c0c3c1fdd Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ET differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI new file mode 100644 index 0000000000..e50ad8f1e0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ new file mode 100644 index 0000000000..0275a2d27a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK new file mode 100644 index 0000000000..5c16cb200e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM new file mode 100644 index 0000000000..e06e4c19fb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO new file mode 100644 index 0000000000..dd4dd01ab9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR new file mode 100644 index 0000000000..4fde5fe011 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_FR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA new file mode 100644 index 0000000000..721ce4e441 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB new file mode 100644 index 0000000000..6eb65ad469 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD new file mode 100644 index 0000000000..e5cee36f64 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE new file mode 100644 index 0000000000..288d8883ae Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF new file mode 100644 index 0000000000..6cda55a525 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG new file mode 100644 index 0000000000..0a6ad17ca8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH new file mode 100644 index 0000000000..467315044f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI new file mode 100644 index 0000000000..2ae84745e1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL new file mode 100644 index 0000000000..6748aef666 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM new file mode 100644 index 0000000000..1b2a03a672 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN new file mode 100644 index 0000000000..fa8954a2cb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP new file mode 100644 index 0000000000..43e217f2ab Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR new file mode 100644 index 0000000000..1ac216e648 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT new file mode 100644 index 0000000000..ede385ac4d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU new file mode 100644 index 0000000000..f4e508cc80 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW new file mode 100644 index 0000000000..2bef055ca2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY new file mode 100644 index 0000000000..db33cceacc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_GY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK new file mode 100644 index 0000000000..d65427d37c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN new file mode 100644 index 0000000000..7ce9d8e647 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR new file mode 100644 index 0000000000..ddbf4654c8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT new file mode 100644 index 0000000000..ac6f5cd078 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU new file mode 100644 index 0000000000..f23d173a1a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID new file mode 100644 index 0000000000..64b6a35eff Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ID differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE new file mode 100644 index 0000000000..c6ea1e526a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL new file mode 100644 index 0000000000..8529cf27a0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM new file mode 100644 index 0000000000..7698e16dd1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN new file mode 100644 index 0000000000..5f0744e876 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ new file mode 100644 index 0000000000..63477f21f3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR new file mode 100644 index 0000000000..3451a0026c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS new file mode 100644 index 0000000000..96668f3235 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT new file mode 100644 index 0000000000..2a1f7ab7a6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_IT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE new file mode 100644 index 0000000000..4d01e44e08 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM new file mode 100644 index 0000000000..bcb6c85a3f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO new file mode 100644 index 0000000000..ec29ccde96 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP new file mode 100644 index 0000000000..485360c217 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_JP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE new file mode 100644 index 0000000000..d33355e193 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG new file mode 100644 index 0000000000..a2b22fc479 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH new file mode 100644 index 0000000000..b9610350a9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI new file mode 100644 index 0000000000..a381e3fe04 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM new file mode 100644 index 0000000000..9c4a073760 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN new file mode 100644 index 0000000000..7a3f1ae810 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP new file mode 100644 index 0000000000..093275551b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR new file mode 100644 index 0000000000..6c770c97d0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW new file mode 100644 index 0000000000..c37942e118 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY new file mode 100644 index 0000000000..3353ad9369 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ new file mode 100644 index 0000000000..03d7639434 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA new file mode 100644 index 0000000000..bcfc00618a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB new file mode 100644 index 0000000000..628496307e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC new file mode 100644 index 0000000000..bd295e7dfe Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI new file mode 100644 index 0000000000..f24d529e12 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK new file mode 100644 index 0000000000..bef8687933 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR new file mode 100644 index 0000000000..2dcb801dfd Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS new file mode 100644 index 0000000000..228c9d47fa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT new file mode 100644 index 0000000000..9ca9325385 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU new file mode 100644 index 0000000000..febd5a97db Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV new file mode 100644 index 0000000000..812f9222e9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY new file mode 100644 index 0000000000..5ef69345f6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_LY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA new file mode 100644 index 0000000000..a9203196eb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC new file mode 100644 index 0000000000..0fb1738c6d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD new file mode 100644 index 0000000000..703bf72052 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME new file mode 100644 index 0000000000..cc028a0e1c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ME differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF new file mode 100644 index 0000000000..7106c2f843 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG new file mode 100644 index 0000000000..29aadef6bf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH new file mode 100644 index 0000000000..e42f2eea25 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK new file mode 100644 index 0000000000..2f5696fb54 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML new file mode 100644 index 0000000000..9b903bad8d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ML differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM new file mode 100644 index 0000000000..922ffccc4a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN new file mode 100644 index 0000000000..44c35eb2f1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO new file mode 100644 index 0000000000..cab7cbe5ae Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP new file mode 100644 index 0000000000..577d33c7b1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ new file mode 100644 index 0000000000..f4965bc7cc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MQ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR new file mode 100644 index 0000000000..bd9cbf662d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS new file mode 100644 index 0000000000..f4dd3eca9f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT new file mode 100644 index 0000000000..75042eeebb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU new file mode 100644 index 0000000000..56c4fd6441 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV new file mode 100644 index 0000000000..4d7bcbbd24 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW new file mode 100644 index 0000000000..27ed1791cb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX new file mode 100644 index 0000000000..f5b17552ef Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY new file mode 100644 index 0000000000..28b81a588e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ new file mode 100644 index 0000000000..fcce2b3773 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA new file mode 100644 index 0000000000..c69a95ec37 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC new file mode 100644 index 0000000000..d1ae2941e4 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE new file mode 100644 index 0000000000..b933add408 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF new file mode 100644 index 0000000000..851a2b4956 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG new file mode 100644 index 0000000000..7229d6a28c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI new file mode 100644 index 0000000000..62dd13c116 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL new file mode 100644 index 0000000000..4c9128189c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO new file mode 100644 index 0000000000..7f0731331e Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP new file mode 100644 index 0000000000..d943ce5ca1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NP differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR new file mode 100644 index 0000000000..317c9d3fce Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU new file mode 100644 index 0000000000..55f86a23db Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ new file mode 100644 index 0000000000..e922a873ad Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_NZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM new file mode 100644 index 0000000000..3fff62fbcb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_OM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA new file mode 100644 index 0000000000..9c977677fa Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE new file mode 100644 index 0000000000..f660b534d6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF new file mode 100644 index 0000000000..b431f93433 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG new file mode 100644 index 0000000000..022009b726 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH new file mode 100644 index 0000000000..745f5cadac Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK new file mode 100644 index 0000000000..228f85a6b2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL new file mode 100644 index 0000000000..96ad400ae3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM new file mode 100644 index 0000000000..b07b532a37 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR new file mode 100644 index 0000000000..03bbbbd9c7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS new file mode 100644 index 0000000000..3a437d58e3 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT new file mode 100644 index 0000000000..be530d73a6 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW new file mode 100644 index 0000000000..dfa8e34031 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY new file mode 100644 index 0000000000..f8618ca22b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_PY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA new file mode 100644 index 0000000000..60774e9010 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_QA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE new file mode 100644 index 0000000000..83b0d7b509 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO new file mode 100644 index 0000000000..6173c031a1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS new file mode 100644 index 0000000000..4baaf09cbe Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU new file mode 100644 index 0000000000..ba90e65e3a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW new file mode 100644 index 0000000000..bf4c546402 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_RW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA new file mode 100644 index 0000000000..476baef6a7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB new file mode 100644 index 0000000000..46fc12706d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SB differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC new file mode 100644 index 0000000000..b3b13e738d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD new file mode 100644 index 0000000000..9c84b486ed Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE new file mode 100644 index 0000000000..2624935a08 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG new file mode 100644 index 0000000000..6aca982a55 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH new file mode 100644 index 0000000000..36c30aa95a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI new file mode 100644 index 0000000000..68f0d5610b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ new file mode 100644 index 0000000000..14b46668cf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK new file mode 100644 index 0000000000..94639e8082 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL new file mode 100644 index 0000000000..53fc6e66df Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM new file mode 100644 index 0000000000..9ce5a90dbf Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN new file mode 100644 index 0000000000..424f4f8f87 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO new file mode 100644 index 0000000000..9257eff825 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR new file mode 100644 index 0000000000..5bde39828f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS new file mode 100644 index 0000000000..23d11a4991 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST new file mode 100644 index 0000000000..1d52d4ed86 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ST differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV new file mode 100644 index 0000000000..b37645ec17 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX new file mode 100644 index 0000000000..1c247755b9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SX differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY new file mode 100644 index 0000000000..b71062fa2d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ new file mode 100644 index 0000000000..7284651d57 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_SZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC new file mode 100644 index 0000000000..7f9f221e45 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD new file mode 100644 index 0000000000..9d1f9e6518 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TD differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG new file mode 100644 index 0000000000..8bae33c68d Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH new file mode 100644 index 0000000000..5ec30571cb Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TH differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ new file mode 100644 index 0000000000..de63252fc7 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TJ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL new file mode 100644 index 0000000000..1cc6a1987f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TL differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM new file mode 100644 index 0000000000..7623973b28 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN new file mode 100644 index 0000000000..192ca3302c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO new file mode 100644 index 0000000000..4a340a72c0 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TO differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR new file mode 100644 index 0000000000..0847c59312 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TR differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT new file mode 100644 index 0000000000..bbf62cfc01 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV new file mode 100644 index 0000000000..4625d190d1 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TV differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW new file mode 100644 index 0000000000..17b8ee5a5a Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ new file mode 100644 index 0000000000..1118137e0c Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_TZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA new file mode 100644 index 0000000000..3cb25984dc Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG new file mode 100644 index 0000000000..7b9f64cfbe Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US new file mode 100644 index 0000000000..2c52287263 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_US differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY new file mode 100644 index 0000000000..a6b493cbc8 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UY differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ new file mode 100644 index 0000000000..3f18f85fb5 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_UZ differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA new file mode 100644 index 0000000000..f3a3a6e1c2 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC new file mode 100644 index 0000000000..cce977b1a9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VC differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE new file mode 100644 index 0000000000..033f6d3fad Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG new file mode 100644 index 0000000000..0e19a0bf25 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VG differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI new file mode 100644 index 0000000000..776e00630f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VI differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN new file mode 100644 index 0000000000..3246aa77ce Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VN differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU new file mode 100644 index 0000000000..3e55971753 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_VU differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF new file mode 100644 index 0000000000..d2cf29bf73 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WF differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS new file mode 100644 index 0000000000..6eac506ea9 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_WS differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK new file mode 100644 index 0000000000..847f9dd17b Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_XK differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE new file mode 100644 index 0000000000..86864619ca Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YE differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT new file mode 100644 index 0000000000..23e960b504 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_YT differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA new file mode 100644 index 0000000000..6b4e6e9042 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZA differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM new file mode 100644 index 0000000000..84d736c221 Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZM differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW new file mode 100644 index 0000000000..6f78c0005f Binary files /dev/null and b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW differ diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java new file mode 100644 index 0000000000..ef0cf67fa8 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/GeoEntityUtility.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.CountryCodeToRegionCodeMap; +import java.util.List; + +/** + * Utility class for checking whether identifiers region code and country calling code belong + * to geographical entities. For more information about geo vs. non-geo entities see {@link + * com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource} and {@link + * com.google.i18n.phonenumbers.metadata.source.NonGeographicalEntityMetadataSource} + */ +public final class GeoEntityUtility { + + /** Region code with a special meaning, used to mark non-geographical entities */ + public static final String REGION_CODE_FOR_NON_GEO_ENTITIES = "001"; + + /** Determines whether {@code regionCode} belongs to a geographical entity. */ + public static boolean isGeoEntity(String regionCode) { + return !regionCode.equals(REGION_CODE_FOR_NON_GEO_ENTITIES); + } + + /** + * Determines whether {@code countryCallingCode} belongs to a geographical entity. + * + *

A single country calling code could map to several different regions. It is considered that + * {@code countryCallingCode} belongs to a geo entity if all of these regions are geo entities + * + *

Note that this method will not throw an exception even when the underlying mapping for the + * {@code countryCallingCode} does not exist, instead it will return {@code false} + */ + public static boolean isGeoEntity(int countryCallingCode) { + List regionCodesForCountryCallingCode = + CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap().get(countryCallingCode); + + return regionCodesForCountryCallingCode != null + && !regionCodesForCountryCallingCode.contains(REGION_CODE_FOR_NON_GEO_ENTITIES); + } + + private GeoEntityUtility() {} +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/MatcherApi.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/MatcherApi.java new file mode 100644 index 0000000000..d2c32b9eaf --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/MatcherApi.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; + +/** + * Internal phonenumber matching API used to isolate the underlying implementation of the + * matcher and allow different implementations to be swapped in easily. + */ +public interface MatcherApi { + /** + * Returns whether the given national number (a string containing only decimal digits) matches + * the national number pattern defined in the given {@code PhoneNumberDesc} message. + */ + boolean matchNationalNumber(CharSequence number, PhoneNumberDesc numberDesc, + boolean allowPrefixMatch); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java new file mode 100644 index 0000000000..ed18ed0948 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexBasedMatcher.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implementation of the matcher API using the regular expressions in the PhoneNumberDesc + * proto message to match numbers. + */ +public final class RegexBasedMatcher implements MatcherApi { + public static MatcherApi create() { + return new RegexBasedMatcher(); + } + + private final RegexCache regexCache = new RegexCache(100); + + private RegexBasedMatcher() {} + + // @Override + public boolean matchNationalNumber(CharSequence number, PhoneNumberDesc numberDesc, + boolean allowPrefixMatch) { + String nationalNumberPattern = numberDesc.getNationalNumberPattern(); + // We don't want to consider it a prefix match when matching non-empty input against an empty + // pattern. + if (nationalNumberPattern.length() == 0) { + return false; + } + return match(number, regexCache.getPatternForRegex(nationalNumberPattern), allowPrefixMatch); + } + + private static boolean match(CharSequence number, Pattern pattern, boolean allowPrefixMatch) { + Matcher matcher = pattern.matcher(number); + if (!matcher.lookingAt()) { + return false; + } else { + return (matcher.matches()) ? true : allowPrefixMatch; + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexCache.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexCache.java new file mode 100644 index 0000000000..f29005e23b --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/internal/RegexCache.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.internal; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * LRU Cache for compiled regular expressions used by the libphonenumbers libary. + * + * @author Shaopeng Jia + */ +public class RegexCache { + private LRUCache cache; + + public RegexCache(int size) { + cache = new LRUCache(size); + } + + public Pattern getPatternForRegex(String regex) { + Pattern pattern = cache.get(regex); + if (pattern == null) { + pattern = Pattern.compile(regex); + cache.put(regex, pattern); + } + return pattern; + } + + // @VisibleForTesting + boolean containsRegex(String regex) { + return cache.containsKey(regex); + } + + private static class LRUCache { + // LinkedHashMap offers a straightforward implementation of LRU cache. + private LinkedHashMap map; + private int size; + + @SuppressWarnings("serial") + public LRUCache(int size) { + this.size = size; + // Using access-order instead of insertion-order. + map = new LinkedHashMap(size * 4 / 3 + 1, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > LRUCache.this.size; + } + }; + } + + public synchronized V get(K key) { + return map.get(key); + } + + public synchronized void put(K key, V value) { + map.put(key, value); + } + + public synchronized boolean containsKey(K key) { + return map.containsKey(key); + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java new file mode 100644 index 0000000000..6bf4df9413 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.metadata.init.ClassPathResourceMetadataLoader; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; +import com.google.i18n.phonenumbers.metadata.source.FormattingMetadataSource; +import com.google.i18n.phonenumbers.metadata.source.FormattingMetadataSourceImpl; +import com.google.i18n.phonenumbers.metadata.source.MetadataSource; +import com.google.i18n.phonenumbers.metadata.source.MetadataSourceImpl; +import com.google.i18n.phonenumbers.metadata.source.MultiFileModeFileNameProvider; +import com.google.i18n.phonenumbers.metadata.source.PhoneMetadataFileNameProvider; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSourceImpl; + +/** + * Provides metadata init and source dependencies when metadata is stored in multi-file mode and + * loaded as a classpath resource. + */ +public final class DefaultMetadataDependenciesProvider { + + private static final DefaultMetadataDependenciesProvider INSTANCE = new DefaultMetadataDependenciesProvider(); + + public static DefaultMetadataDependenciesProvider getInstance() { + return INSTANCE; + } + + private DefaultMetadataDependenciesProvider() { + } + + private final MetadataParser metadataParser = MetadataParser.newLenientParser(); + private final MetadataLoader metadataLoader = new ClassPathResourceMetadataLoader(); + + private final PhoneMetadataFileNameProvider phoneNumberMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto"); + private final MetadataSource phoneNumberMetadataSource = + new MetadataSourceImpl( + phoneNumberMetadataFileNameProvider, + metadataLoader, + metadataParser); + + private final PhoneMetadataFileNameProvider shortNumberMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto"); + private final RegionMetadataSource shortNumberMetadataSource = + new RegionMetadataSourceImpl( + shortNumberMetadataFileNameProvider, + metadataLoader, + metadataParser); + + private final PhoneMetadataFileNameProvider alternateFormatsMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto"); + private final FormattingMetadataSource alternateFormatsMetadataSource = + new FormattingMetadataSourceImpl( + alternateFormatsMetadataFileNameProvider, + metadataLoader, + metadataParser); + + public MetadataParser getMetadataParser() { + return metadataParser; + } + + public MetadataLoader getMetadataLoader() { + return metadataLoader; + } + + public PhoneMetadataFileNameProvider getPhoneNumberMetadataFileNameProvider() { + return phoneNumberMetadataFileNameProvider; + } + + public MetadataSource getPhoneNumberMetadataSource() { + return phoneNumberMetadataSource; + } + + public PhoneMetadataFileNameProvider getShortNumberMetadataFileNameProvider() { + return shortNumberMetadataFileNameProvider; + } + + public RegionMetadataSource getShortNumberMetadataSource() { + return shortNumberMetadataSource; + } + + public PhoneMetadataFileNameProvider getAlternateFormatsMetadataFileNameProvider() { + return alternateFormatsMetadataFileNameProvider; + } + + public FormattingMetadataSource getAlternateFormatsMetadataSource() { + return alternateFormatsMetadataSource; + } + + public String getCarrierDataDirectory() { + return "/com/google/i18n/phonenumbers/carrier/data/"; + } + + public String getGeocodingDataDirectory() { + return "/com/google/i18n/phonenumbers/geocoding/data/"; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java new file mode 100644 index 0000000000..76122b8ad8 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/ClassPathResourceMetadataLoader.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.init; + +import com.google.i18n.phonenumbers.MetadataLoader; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A {@link MetadataLoader} implementation that reads phone number metadata files as classpath + * resources. + */ +public final class ClassPathResourceMetadataLoader implements MetadataLoader { + + private static final Logger logger = + Logger.getLogger(ClassPathResourceMetadataLoader.class.getName()); + + @Override + public InputStream loadMetadata(String metadataFileName) { + InputStream inputStream = + ClassPathResourceMetadataLoader.class.getResourceAsStream(metadataFileName); + if (inputStream == null) { + logger.log(Level.WARNING, String.format("File %s not found", metadataFileName)); + } + return inputStream; + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java new file mode 100644 index 0000000000..e923dfadf7 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/init/MetadataParser.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.init; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Exposes single method for parsing {@link InputStream} content into {@link Collection} of {@link + * PhoneMetadata} + */ +public final class MetadataParser { + + private static final Logger logger = Logger.getLogger(MetadataParser.class.getName()); + + /** + * Creates new instance in lenient mode, see {@link MetadataParser#parse(InputStream)} for more + * info. + */ + public static MetadataParser newLenientParser() { + return new MetadataParser(false); + } + + /** + * Creates new instance in strict mode, see {@link MetadataParser#parse(InputStream)} for more + * info + */ + public static MetadataParser newStrictParser() { + return new MetadataParser(true); + } + + private final boolean strictMode; + + private MetadataParser(boolean strictMode) { + this.strictMode = strictMode; + } + + /** + * Parses given {@link InputStream} into a {@link Collection} of {@link PhoneMetadata}. + * + * @throws IllegalArgumentException if {@code source} is {@code null} and strict mode is on + * @return parsed {@link PhoneMetadata}, or empty {@link Collection} if {@code source} is {@code + * null} and lenient mode is on + */ + public Collection parse(InputStream source) { + if (source == null) { + return handleNullSource(); + } + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(source); + PhoneMetadataCollection phoneMetadataCollection = new PhoneMetadataCollection(); + phoneMetadataCollection.readExternal(ois); + List phoneMetadata = phoneMetadataCollection.getMetadataList(); + // Sanity check; this should not happen if provided InputStream is valid + if (phoneMetadata.isEmpty()) { + throw new IllegalStateException("Empty metadata"); + } + return phoneMetadataCollection.getMetadataList(); + } catch (IOException e) { + throw new IllegalStateException("Unable to parse metadata file", e); + } finally { + if (ois != null) { + // This will close all underlying streams as well, including source. + close(ois); + } else { + close(source); + } + } + } + + private List handleNullSource() { + if (strictMode) { + throw new IllegalArgumentException("Source cannot be null"); + } + return Collections.emptyList(); + } + + private void close(InputStream inputStream) { + try { + inputStream.close(); + } catch (IOException e) { + logger.log(Level.WARNING, "Error closing input stream (ignored)", e); + } + } +} \ No newline at end of file diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java new file mode 100644 index 0000000000..d621e0cf5f --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/BlockingMetadataBootstrappingGuard.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; +import java.io.InputStream; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A blocking implementation of {@link MetadataBootstrappingGuard}. Can be used for both single-file + * (bulk) and multi-file metadata + * + * @param needs to extend {@link MetadataContainer} + */ +final class BlockingMetadataBootstrappingGuard + implements MetadataBootstrappingGuard { + + private final MetadataLoader metadataLoader; + private final MetadataParser metadataParser; + private final T metadataContainer; + private final Map loadedFiles; // identity map + + BlockingMetadataBootstrappingGuard( + MetadataLoader metadataLoader, MetadataParser metadataParser, T metadataContainer) { + this.metadataLoader = metadataLoader; + this.metadataParser = metadataParser; + this.metadataContainer = metadataContainer; + this.loadedFiles = new ConcurrentHashMap<>(); + } + + @Override + public T getOrBootstrap(String phoneMetadataFile) { + if (!loadedFiles.containsKey(phoneMetadataFile)) { + bootstrapMetadata(phoneMetadataFile); + } + return metadataContainer; + } + + private synchronized void bootstrapMetadata(String phoneMetadataFile) { + // Additional check is needed because multiple threads could pass the first check when calling + // getOrBootstrap() at the same time for unloaded metadata file + if (loadedFiles.containsKey(phoneMetadataFile)) { + return; + } + Collection phoneMetadata = read(phoneMetadataFile); + for (PhoneMetadata metadata : phoneMetadata) { + metadataContainer.accept(metadata); + } + loadedFiles.put(phoneMetadataFile, phoneMetadataFile); + } + + private Collection read(String phoneMetadataFile) { + try { + InputStream metadataStream = metadataLoader.loadMetadata(phoneMetadataFile); + return metadataParser.parse(metadataStream); + } catch (IllegalArgumentException | IllegalStateException e) { + throw new IllegalStateException("Failed to read file " + phoneMetadataFile, e); + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java new file mode 100644 index 0000000000..7275749578 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/CompositeMetadataContainer.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; + +/** + * Implementation of {@link MetadataContainer} which is a composition of different {@link + * MapBackedMetadataContainer}s. It adds items to a single simpler container at a time depending on + * the content of {@link PhoneMetadata}. + */ +final class CompositeMetadataContainer implements MetadataContainer { + + private final MapBackedMetadataContainer metadataByCountryCode = + MapBackedMetadataContainer.byCountryCallingCode(); + private final MapBackedMetadataContainer metadataByRegionCode = + MapBackedMetadataContainer.byRegionCode(); + + /** + * Intended to be called for geographical regions only. For non-geographical entities, use {@link + * CompositeMetadataContainer#getMetadataBy(int)} + */ + PhoneMetadata getMetadataBy(String regionCode) { + return metadataByRegionCode.getMetadataBy(regionCode); + } + + /** + * Intended to be called for non-geographical entities only, such as 800 (country code assigned to + * the Universal International Freephone Service). For geographical regions, use {@link + * CompositeMetadataContainer#getMetadataBy(String)} + */ + PhoneMetadata getMetadataBy(int countryCallingCode) { + return metadataByCountryCode.getMetadataBy(countryCallingCode); + } + + /** + * If the metadata belongs to a specific geographical region (it has a region code other than + * {@link GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES}), it will be added to a {@link + * MapBackedMetadataContainer} which stores metadata by region code. Otherwise, it will be added + * to a {@link MapBackedMetadataContainer} which stores metadata by country calling code. This + * means that {@link CompositeMetadataContainer#getMetadataBy(int)} will not work for country + * calling codes such as 41 (country calling code for Switzerland), only for country calling codes + * such as 800 (country code assigned to the Universal International Freephone Service) + */ + @Override + public void accept(PhoneMetadata phoneMetadata) { + String regionCode = metadataByRegionCode.getKeyProvider().getKeyOf(phoneMetadata); + if (GeoEntityUtility.isGeoEntity(regionCode)) { + metadataByRegionCode.accept(phoneMetadata); + } else { + metadataByCountryCode.accept(phoneMetadata); + } + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java new file mode 100644 index 0000000000..f4f332cb21 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSource.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** A source of formatting phone metadata. */ +public interface FormattingMetadataSource { + + /** + * Returns formatting phone metadata for provided country calling code. + * + *

This method is similar to the one in {@link + * NonGeographicalEntityMetadataSource#getMetadataForNonGeographicalRegion(int)}, except that it + * will not fail for geographical regions, it can be used for both geo- and non-geo entities. + * + *

In case the provided {@code countryCallingCode} maps to several different regions, only one + * would contain formatting metadata. + * + * @return the phone metadata for provided {@code countryCallingCode}, or null if there is none. + */ + PhoneMetadata getFormattingMetadataForCountryCallingCode(int countryCallingCode); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java new file mode 100644 index 0000000000..d6a819099f --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/FormattingMetadataSourceImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link FormattingMetadataSource} guarded by {@link MetadataBootstrappingGuard} + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class FormattingMetadataSourceImpl implements FormattingMetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard> bootstrappingGuard; + + public FormattingMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard> bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public FormattingMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, MapBackedMetadataContainer.byCountryCallingCode())); + } + + @Override + public PhoneMetadata getFormattingMetadataForCountryCallingCode(int countryCallingCode) { + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(countryCallingCode)) + .getMetadataBy(countryCallingCode); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java new file mode 100644 index 0000000000..639280d87c --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MapBackedMetadataContainer.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * A {@link MetadataContainer} implementation backed by a {@link ConcurrentHashMap} with generic + * keys. + */ +final class MapBackedMetadataContainer implements MetadataContainer { + + static MapBackedMetadataContainer byRegionCode() { + return new MapBackedMetadataContainer<>( + new KeyProvider() { + @Override + public String getKeyOf(PhoneMetadata phoneMetadata) { + return phoneMetadata.getId(); + } + }); + } + + static MapBackedMetadataContainer byCountryCallingCode() { + return new MapBackedMetadataContainer<>( + new KeyProvider() { + @Override + public Integer getKeyOf(PhoneMetadata phoneMetadata) { + return phoneMetadata.getCountryCode(); + } + }); + } + + private final ConcurrentMap metadataMap; + + private final KeyProvider keyProvider; + + private MapBackedMetadataContainer(KeyProvider keyProvider) { + this.metadataMap = new ConcurrentHashMap<>(); + this.keyProvider = keyProvider; + } + + PhoneMetadata getMetadataBy(T key) { + return key != null ? metadataMap.get(key) : null; + } + + KeyProvider getKeyProvider() { + return keyProvider; + } + + @Override + public void accept(PhoneMetadata phoneMetadata) { + metadataMap.put(keyProvider.getKeyOf(phoneMetadata), phoneMetadata); + } + + interface KeyProvider { + T getKeyOf(PhoneMetadata phoneMetadata); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java new file mode 100644 index 0000000000..9380c5954d --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataBootstrappingGuard.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * Guard that ensures that metadata bootstrapping process (loading and parsing) is triggered only + * once per metadata file. + * + * @param needs to extend {@link MetadataContainer} + */ +public interface MetadataBootstrappingGuard { + + /** + * If metadata from the provided file has not yet been read, invokes loading and parsing from the + * provided file and adds the result to guarded {@link MetadataContainer}. + * + * @param phoneMetadataFile to read from + * @return guarded {@link MetadataContainer} + */ + T getOrBootstrap(String phoneMetadataFile); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java new file mode 100644 index 0000000000..3f6b21ed0e --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataContainer.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** + * A container for {@link PhoneMetadata} + */ +interface MetadataContainer { + + /** + * Adds {@link PhoneMetadata} to the container. It depends on the implementation of the interface + * what this means, for example {@link MapBackedMetadataContainer} simply adds the provided + * metadata into the backing map. Implementing classes should ensure thread-safety. + */ + void accept(PhoneMetadata phoneMetadata); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java new file mode 100644 index 0000000000..d353ce9694 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSource.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** A source of phone metadata split by different regions. */ +public interface MetadataSource extends RegionMetadataSource, NonGeographicalEntityMetadataSource { +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java new file mode 100644 index 0000000000..c3d1c7360b --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MetadataSourceImpl.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link MetadataSource} guarded by {@link MetadataBootstrappingGuard}. + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class MetadataSourceImpl implements MetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard bootstrappingGuard; + + public MetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public MetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, new CompositeMetadataContainer())); + } + + @Override + public PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { + if (GeoEntityUtility.isGeoEntity(countryCallingCode)) { + throw new IllegalArgumentException( + countryCallingCode + " calling code belongs to a geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(countryCallingCode)) + .getMetadataBy(countryCallingCode); + } + + @Override + public PhoneMetadata getMetadataForRegion(String regionCode) { + if (!GeoEntityUtility.isGeoEntity(regionCode)) { + throw new IllegalArgumentException(regionCode + " region code is a non-geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(regionCode)) + .getMetadataBy(regionCode); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java new file mode 100644 index 0000000000..c8a3270a6d --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/MultiFileModeFileNameProvider.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + + +/** + * {@link PhoneMetadataFileNameProvider} implementation which appends key as a suffix to the + * predefined metadata file name base. + */ +public final class MultiFileModeFileNameProvider implements PhoneMetadataFileNameProvider { + + private final String phoneMetadataFileNamePrefix; + + public MultiFileModeFileNameProvider(String phoneMetadataFileNameBase) { + this.phoneMetadataFileNamePrefix = phoneMetadataFileNameBase + "_"; + } + + @Override + public String getFor(Object key) { + String keyAsString = key.toString(); + if (!isAlphanumeric(keyAsString)) { + throw new IllegalArgumentException("Invalid key: " + keyAsString); + } + return phoneMetadataFileNamePrefix + key; + } + + private boolean isAlphanumeric(String key) { + if (key == null || key.length() == 0) { + return false; + } + // String#length doesn't actually return the number of + // code points in the String, it returns the number + // of char values. + int size = key.length(); + for (int charIdx = 0; charIdx < size; ) { + final int codePoint = key.codePointAt(charIdx); + if (!Character.isLetterOrDigit(codePoint)) { + return false; + } + charIdx += Character.charCount(codePoint); + } + return true; + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java new file mode 100644 index 0000000000..70db06df03 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/NonGeographicalEntityMetadataSource.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; + +/** + * A source of phone metadata for non-geographical entities. + * + *

Non-geographical entities are phone number ranges that have a country calling code, but either + * do not belong to an actual country (some international services), or belong to a region which has + * a different country calling code from the country it is part of. Examples of such ranges are + * those starting with: + * + *

    + *
  • 800 - country code assigned to the Universal International Freephone Service + *
  • 808 - country code assigned to the International Shared Cost Service + *
  • 870 - country code assigned to the Pitcairn Islands + *
  • ... + *
+ */ +public interface NonGeographicalEntityMetadataSource { + + /** + * Gets phone metadata for a non-geographical entity. + * + * @param countryCallingCode the country calling code. + * @return the phone metadata for that entity, or null if there is none. + * @throws IllegalArgumentException if provided {@code countryCallingCode} does not belong to a + * non-geographical entity + */ + PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java new file mode 100644 index 0000000000..c3d16887fb --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/PhoneMetadataFileNameProvider.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * Abstraction responsible for inferring the metadata file name. + * + *

Two implementations are available: + * + *

    + *
  • {@link SingleFileModeFileNameProvider} for single-file metadata. + *
  • {@link MultiFileModeFileNameProvider} for multi-file metadata. + *
+ */ +public interface PhoneMetadataFileNameProvider { + + /** + * Returns phone metadata file path for the given key. Assumes that key.toString() is + * well-defined. + */ + String getFor(Object key); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java new file mode 100644 index 0000000000..3cf15c206a --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSource.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; + +/** + * A source of phone metadata split by geographical regions. + */ +public interface RegionMetadataSource { + + /** + * Returns phone metadata for provided geographical region. + * + *

The {@code regionCode} must be different from {@link + * GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES}, which has a special meaning and is used to + * mark non-geographical regions (see {@link NonGeographicalEntityMetadataSource} for more + * information). + * + * @return the phone metadata for provided {@code regionCode}, or null if there is none. + * @throws IllegalArgumentException if provided {@code regionCode} is {@link + * GeoEntityUtility#REGION_CODE_FOR_NON_GEO_ENTITIES} + */ + PhoneMetadata getMetadataForRegion(String regionCode); +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java new file mode 100644 index 0000000000..0078dd9454 --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/RegionMetadataSourceImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +import com.google.i18n.phonenumbers.MetadataLoader; +import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; +import com.google.i18n.phonenumbers.internal.GeoEntityUtility; +import com.google.i18n.phonenumbers.metadata.init.MetadataParser; + +/** + * Implementation of {@link RegionMetadataSource} guarded by {@link MetadataBootstrappingGuard} + * + *

By default, a {@link BlockingMetadataBootstrappingGuard} will be used, but any custom + * implementation can be injected. + */ +public final class RegionMetadataSourceImpl implements RegionMetadataSource { + + private final PhoneMetadataFileNameProvider phoneMetadataFileNameProvider; + private final MetadataBootstrappingGuard> + bootstrappingGuard; + + public RegionMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataBootstrappingGuard> bootstrappingGuard) { + this.phoneMetadataFileNameProvider = phoneMetadataFileNameProvider; + this.bootstrappingGuard = bootstrappingGuard; + } + + public RegionMetadataSourceImpl( + PhoneMetadataFileNameProvider phoneMetadataFileNameProvider, + MetadataLoader metadataLoader, + MetadataParser metadataParser) { + this( + phoneMetadataFileNameProvider, + new BlockingMetadataBootstrappingGuard<>( + metadataLoader, metadataParser, MapBackedMetadataContainer.byRegionCode())); + } + + @Override + public PhoneMetadata getMetadataForRegion(String regionCode) { + if (!GeoEntityUtility.isGeoEntity(regionCode)) { + throw new IllegalArgumentException(regionCode + " region code is a non-geo entity"); + } + return bootstrappingGuard + .getOrBootstrap(phoneMetadataFileNameProvider.getFor(regionCode)) + .getMetadataBy(regionCode); + } +} diff --git a/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java new file mode 100644 index 0000000000..1d3d1eb81b --- /dev/null +++ b/tools/java/java-build/target/test-classes/com/google/i18n/phonenumbers/metadata/source/SingleFileModeFileNameProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 The Libphonenumber Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.i18n.phonenumbers.metadata.source; + +/** + * {@link PhoneMetadataFileNameProvider} implementation that returns the same metadata file name for + * each key + */ +public final class SingleFileModeFileNameProvider implements PhoneMetadataFileNameProvider { + + private final String phoneMetadataFileName; + + public SingleFileModeFileNameProvider(String phoneMetadataFileName) { + this.phoneMetadataFileName = phoneMetadataFileName; + } + + @Override + public String getFor(Object key) { + return phoneMetadataFileName; + } +}