From c778ecbb8cd520bcd2a8aa670334fcd4b3d72dd8 Mon Sep 17 00:00:00 2001 From: tijanavg Date: Tue, 22 Feb 2022 12:38:26 +0100 Subject: [PATCH] Replaced MetadataManager usages with new classes --- .../PhoneNumberToCarrierMapper.java | 10 +- .../geocoding/PhoneNumberOfflineGeocoder.java | 8 +- .../prefixmapper/PrefixFileReader.java | 13 +- .../i18n/phonenumbers/MetadataManager.java | 233 ------------------ .../i18n/phonenumbers/MetadataSource.java | 39 --- .../MultiFileMetadataSourceImpl.java | 86 ------- .../i18n/phonenumbers/PhoneNumberMatcher.java | 5 +- .../i18n/phonenumbers/PhoneNumberUtil.java | 49 ++-- .../i18n/phonenumbers/ShortNumberInfo.java | 66 ++--- .../SingleFileMetadataSourceImpl.java | 65 ----- .../DefaultMetadataDependenciesProvider.java | 41 ++- .../i18n/phonenumbers/ExampleNumbersTest.java | 75 +++--- .../phonenumbers/MetadataManagerTest.java | 88 ------- .../MultiFileMetadataSourceImplTest.java | 62 ----- .../SingleFileMetadataSourceImplTest.java | 48 ---- .../phonenumbers/TestMetadataTestCase.java | 14 +- 16 files changed, 166 insertions(+), 736 deletions(-) delete mode 100644 java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java delete mode 100644 java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataSource.java delete mode 100644 java/libphonenumber/src/com/google/i18n/phonenumbers/MultiFileMetadataSourceImpl.java delete mode 100644 java/libphonenumber/src/com/google/i18n/phonenumbers/SingleFileMetadataSourceImpl.java delete mode 100644 java/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java delete mode 100644 java/libphonenumber/test/com/google/i18n/phonenumbers/MultiFileMetadataSourceImplTest.java delete mode 100644 java/libphonenumber/test/com/google/i18n/phonenumbers/SingleFileMetadataSourceImplTest.java diff --git a/java/carrier/src/com/google/i18n/phonenumbers/PhoneNumberToCarrierMapper.java b/java/carrier/src/com/google/i18n/phonenumbers/PhoneNumberToCarrierMapper.java index b99abe6e3..ed3d6d88e 100644 --- a/java/carrier/src/com/google/i18n/phonenumbers/PhoneNumberToCarrierMapper.java +++ b/java/carrier/src/com/google/i18n/phonenumbers/PhoneNumberToCarrierMapper.java @@ -16,11 +16,10 @@ package com.google.i18n.phonenumbers; -import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; import com.google.i18n.phonenumbers.prefixmapper.PrefixFileReader; - import java.util.Locale; /** @@ -30,9 +29,7 @@ import java.util.Locale; */ public class PhoneNumberToCarrierMapper { private static PhoneNumberToCarrierMapper instance = null; - private static final String MAPPING_DATA_DIRECTORY = - "/com/google/i18n/phonenumbers/carrier/data/"; - private PrefixFileReader prefixFileReader = null; + private final PrefixFileReader prefixFileReader; private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); @@ -51,7 +48,8 @@ public class PhoneNumberToCarrierMapper { */ public static synchronized PhoneNumberToCarrierMapper getInstance() { if (instance == null) { - instance = new PhoneNumberToCarrierMapper(MAPPING_DATA_DIRECTORY); + instance = new PhoneNumberToCarrierMapper(DefaultMetadataDependenciesProvider.getInstance() + .getCarrierDataDirectory()); } return instance; } diff --git a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java index a48ed903d..f26cc1038 100644 --- a/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java +++ b/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder.java @@ -20,6 +20,7 @@ import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; import com.google.i18n.phonenumbers.prefixmapper.PrefixFileReader; import java.util.List; @@ -32,9 +33,7 @@ import java.util.Locale; */ public class PhoneNumberOfflineGeocoder { private static PhoneNumberOfflineGeocoder instance = null; - private static final String MAPPING_DATA_DIRECTORY = - "/com/google/i18n/phonenumbers/geocoding/data/"; - private PrefixFileReader prefixFileReader = null; + private final PrefixFileReader prefixFileReader; private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); @@ -54,7 +53,8 @@ public class PhoneNumberOfflineGeocoder { */ public static synchronized PhoneNumberOfflineGeocoder getInstance() { if (instance == null) { - instance = new PhoneNumberOfflineGeocoder(MAPPING_DATA_DIRECTORY); + instance = new PhoneNumberOfflineGeocoder(DefaultMetadataDependenciesProvider.getInstance() + .getGeocodingDataDirectory()); } return instance; } diff --git a/java/internal/prefixmapper/src/com/google/i18n/phonenumbers/prefixmapper/PrefixFileReader.java b/java/internal/prefixmapper/src/com/google/i18n/phonenumbers/prefixmapper/PrefixFileReader.java index 8a4fde70f..6033b6785 100644 --- a/java/internal/prefixmapper/src/com/google/i18n/phonenumbers/prefixmapper/PrefixFileReader.java +++ b/java/internal/prefixmapper/src/com/google/i18n/phonenumbers/prefixmapper/PrefixFileReader.java @@ -16,8 +16,10 @@ package com.google.i18n.phonenumbers.prefixmapper; +import com.google.i18n.phonenumbers.MetadataLoader; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; @@ -40,17 +42,17 @@ public class PrefixFileReader { private MappingFileProvider mappingFileProvider = new MappingFileProvider(); // A mapping from countryCallingCode_lang to the corresponding phone prefix map that has been // loaded. - private Map availablePhonePrefixMaps = - new HashMap(); + private Map availablePhonePrefixMaps = new HashMap<>(); + private final MetadataLoader metadataLoader; public PrefixFileReader(String phonePrefixDataDirectory) { this.phonePrefixDataDirectory = phonePrefixDataDirectory; + this.metadataLoader = DefaultMetadataDependenciesProvider.getInstance().getMetadataLoader(); loadMappingFileProvider(); } private void loadMappingFileProvider() { - InputStream source = - PrefixFileReader.class.getResourceAsStream(phonePrefixDataDirectory + "config"); + InputStream source = metadataLoader.loadMetadata(phonePrefixDataDirectory + "config"); ObjectInputStream in = null; try { in = new ObjectInputStream(source); @@ -75,8 +77,7 @@ public class PrefixFileReader { } private void loadPhonePrefixMapFromFile(String fileName) { - InputStream source = - PrefixFileReader.class.getResourceAsStream(phonePrefixDataDirectory + fileName); + InputStream source = metadataLoader.loadMetadata(phonePrefixDataDirectory + fileName); ObjectInputStream in = null; try { in = new ObjectInputStream(source); diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java deleted file mode 100644 index 5c072d6ab..000000000 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataManager.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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. - */ - -package com.google.i18n.phonenumbers; - -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.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Manager for loading metadata for alternate formats and short numbers. We also declare some - * constants for phone number metadata loading, to more easily maintain all three types of metadata - * together. - * TODO: Consider managing phone number metadata loading here too. - */ -final class MetadataManager { - static final String MULTI_FILE_PHONE_NUMBER_METADATA_FILE_PREFIX = - "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto"; - static final String SINGLE_FILE_PHONE_NUMBER_METADATA_FILE_NAME = - "/com/google/i18n/phonenumbers/data/SingleFilePhoneNumberMetadataProto"; - private static final String ALTERNATE_FORMATS_FILE_PREFIX = - "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto"; - private static final String SHORT_NUMBER_METADATA_FILE_PREFIX = - "/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto"; - - static final MetadataLoader DEFAULT_METADATA_LOADER = new MetadataLoader() { - @Override - public InputStream loadMetadata(String metadataFileName) { - return MetadataManager.class.getResourceAsStream(metadataFileName); - } - }; - - private static final Logger logger = Logger.getLogger(MetadataManager.class.getName()); - - // A mapping from a country calling code to the alternate formats for that country calling code. - private static final ConcurrentHashMap alternateFormatsMap = - new ConcurrentHashMap(); - - // A mapping from a region code to the short number metadata for that region code. - private static final ConcurrentHashMap shortNumberMetadataMap = - new ConcurrentHashMap(); - - // The set of country calling codes for which there are alternate formats. For every country - // calling code in this set there should be metadata linked into the resources. - private static final Set alternateFormatsCountryCodes = - AlternateFormatsCountryCodeSet.getCountryCodeSet(); - - // The set of region codes for which there are short number metadata. For every region code in - // this set there should be metadata linked into the resources. - private static final Set shortNumberMetadataRegionCodes = - ShortNumbersRegionCodeSet.getRegionCodeSet(); - - private MetadataManager() {} - - static PhoneMetadata getAlternateFormatsForCountry(int countryCallingCode) { - if (!alternateFormatsCountryCodes.contains(countryCallingCode)) { - return null; - } - return getMetadataFromMultiFilePrefix(countryCallingCode, alternateFormatsMap, - ALTERNATE_FORMATS_FILE_PREFIX, DEFAULT_METADATA_LOADER); - } - - static PhoneMetadata getShortNumberMetadataForRegion(String regionCode) { - if (!shortNumberMetadataRegionCodes.contains(regionCode)) { - return null; - } - return getMetadataFromMultiFilePrefix(regionCode, shortNumberMetadataMap, - SHORT_NUMBER_METADATA_FILE_PREFIX, DEFAULT_METADATA_LOADER); - } - - static Set getSupportedShortNumberRegions() { - return Collections.unmodifiableSet(shortNumberMetadataRegionCodes); - } - - /** - * @param key the lookup key for the provided map, typically a region code or a country calling - * code - * @param map the map containing mappings of already loaded metadata from their {@code key}. If - * this {@code key}'s metadata isn't already loaded, it will be added to this map after - * loading - * @param filePrefix the prefix of the file to load metadata from - * @param metadataLoader the metadata loader used to inject alternative metadata sources - */ - static PhoneMetadata getMetadataFromMultiFilePrefix(T key, - ConcurrentHashMap map, String filePrefix, MetadataLoader metadataLoader) { - PhoneMetadata metadata = map.get(key); - if (metadata != null) { - return metadata; - } - // We assume key.toString() is well-defined. - String fileName = filePrefix + "_" + key; - List metadataList = getMetadataFromSingleFileName(fileName, metadataLoader); - if (metadataList.size() > 1) { - logger.log(Level.WARNING, "more than one metadata in file " + fileName); - } - metadata = metadataList.get(0); - PhoneMetadata oldValue = map.putIfAbsent(key, metadata); - return (oldValue != null) ? oldValue : metadata; - } - - // Loader and holder for the metadata maps loaded from a single file. - static class SingleFileMetadataMaps { - static SingleFileMetadataMaps load(String fileName, MetadataLoader metadataLoader) { - List metadataList = getMetadataFromSingleFileName(fileName, metadataLoader); - Map regionCodeToMetadata = new HashMap(); - Map countryCallingCodeToMetadata = - new HashMap(); - for (PhoneMetadata metadata : metadataList) { - String regionCode = metadata.getId(); - if (PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode)) { - // regionCode belongs to a non-geographical entity. - countryCallingCodeToMetadata.put(metadata.getCountryCode(), metadata); - } else { - regionCodeToMetadata.put(regionCode, metadata); - } - } - return new SingleFileMetadataMaps(regionCodeToMetadata, countryCallingCodeToMetadata); - } - - // A map from a region code to the PhoneMetadata for that region. - // For phone number metadata, the region code "001" is excluded, since that is used for the - // non-geographical phone number entities. - private final Map regionCodeToMetadata; - - // A map from a country calling code to the PhoneMetadata for that country calling code. - // Examples of the country calling codes include 800 (International Toll Free Service) and 808 - // (International Shared Cost Service). - // For phone number metadata, only the non-geographical phone number entities' country calling - // codes are present. - private final Map countryCallingCodeToMetadata; - - private SingleFileMetadataMaps(Map regionCodeToMetadata, - Map countryCallingCodeToMetadata) { - this.regionCodeToMetadata = Collections.unmodifiableMap(regionCodeToMetadata); - this.countryCallingCodeToMetadata = Collections.unmodifiableMap(countryCallingCodeToMetadata); - } - - PhoneMetadata get(String regionCode) { - return regionCodeToMetadata.get(regionCode); - } - - PhoneMetadata get(int countryCallingCode) { - return countryCallingCodeToMetadata.get(countryCallingCode); - } - } - - // Manages the atomic reference lifecycle of a SingleFileMetadataMaps encapsulation. - static SingleFileMetadataMaps getSingleFileMetadataMaps( - AtomicReference ref, String fileName, MetadataLoader metadataLoader) { - SingleFileMetadataMaps maps = ref.get(); - if (maps != null) { - return maps; - } - maps = SingleFileMetadataMaps.load(fileName, metadataLoader); - ref.compareAndSet(null, maps); - return ref.get(); - } - - private static List getMetadataFromSingleFileName(String fileName, - MetadataLoader metadataLoader) { - InputStream source = metadataLoader.loadMetadata(fileName); - if (source == null) { - // Sanity check; this would only happen if we packaged jars incorrectly. - throw new IllegalStateException("missing metadata: " + fileName); - } - PhoneMetadataCollection metadataCollection = loadMetadataAndCloseInput(source); - List metadataList = metadataCollection.getMetadataList(); - if (metadataList.size() == 0) { - // Sanity check; this should not happen since we build with non-empty metadata. - throw new IllegalStateException("empty metadata: " + fileName); - } - return metadataList; - } - - /** - * Loads and returns the metadata from the given stream and closes the stream. - * - * @param source the non-null stream from which metadata is to be read - * @return the loaded metadata - */ - private static PhoneMetadataCollection loadMetadataAndCloseInput(InputStream source) { - ObjectInputStream ois = null; - try { - try { - ois = new ObjectInputStream(source); - } catch (IOException e) { - throw new RuntimeException("cannot load/parse metadata", e); - } - PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection(); - try { - metadataCollection.readExternal(ois); - } catch (IOException e) { - throw new RuntimeException("cannot load/parse metadata", e); - } - return metadataCollection; - } finally { - try { - if (ois != null) { - // This will close all underlying streams as well, including source. - ois.close(); - } else { - source.close(); - } - } catch (IOException e) { - logger.log(Level.WARNING, "error closing input stream (ignored)", e); - } - } - } -} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataSource.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataSource.java deleted file mode 100644 index f5ffcad8d..000000000 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataSource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 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; - -/** - * A source for phone metadata for all regions. - */ -interface MetadataSource { - - /** - * Gets phone metadata for a region. - * @param regionCode the region code. - * @return the phone metadata for that region, or null if there is none. - */ - PhoneMetadata getMetadataForRegion(String regionCode); - - /** - * Gets phone metadata for a non-geographical region. - * @param countryCallingCode the country calling code. - * @return the phone metadata for that region, or null if there is none. - */ - PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode); -} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/MultiFileMetadataSourceImpl.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/MultiFileMetadataSourceImpl.java deleted file mode 100644 index 9a0b8e690..000000000 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/MultiFileMetadataSourceImpl.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2015 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 java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Implementation of {@link MetadataSource} that reads from multiple resource files. - */ -final class MultiFileMetadataSourceImpl implements MetadataSource { - // The prefix of the binary files containing phone number metadata for different regions. - // This enables us to set up with different metadata, such as for testing. - private final String phoneNumberMetadataFilePrefix; - - // The {@link MetadataLoader} used to inject alternative metadata sources. - private final MetadataLoader metadataLoader; - - // A mapping from a region code to the phone number metadata for that region code. - // Unlike the mappings for alternate formats and short number metadata, the phone number metadata - // is loaded from a non-statically determined file prefix; therefore this map is bound to the - // instance and not static. - private final ConcurrentHashMap geographicalRegions = - new ConcurrentHashMap(); - - // A mapping from a country calling code for a non-geographical entity to the phone number - // metadata for that country calling code. Examples of the country calling codes include 800 - // (International Toll Free Service) and 808 (International Shared Cost Service). - // Unlike the mappings for alternate formats and short number metadata, the phone number metadata - // is loaded from a non-statically determined file prefix; therefore this map is bound to the - // instance and not static. - private final ConcurrentHashMap nonGeographicalRegions = - new ConcurrentHashMap(); - - // It is assumed that metadataLoader is not null. Checks should happen before passing it in here. - // @VisibleForTesting - MultiFileMetadataSourceImpl(String phoneNumberMetadataFilePrefix, MetadataLoader metadataLoader) { - this.phoneNumberMetadataFilePrefix = phoneNumberMetadataFilePrefix; - this.metadataLoader = metadataLoader; - } - - // It is assumed that metadataLoader is not null. Checks should happen before passing it in here. - MultiFileMetadataSourceImpl(MetadataLoader metadataLoader) { - this(MetadataManager.MULTI_FILE_PHONE_NUMBER_METADATA_FILE_PREFIX, metadataLoader); - } - - @Override - public PhoneMetadata getMetadataForRegion(String regionCode) { - return MetadataManager.getMetadataFromMultiFilePrefix(regionCode, geographicalRegions, - phoneNumberMetadataFilePrefix, metadataLoader); - } - - @Override - public PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { - if (!isNonGeographical(countryCallingCode)) { - // The given country calling code was for a geographical region. - return null; - } - return MetadataManager.getMetadataFromMultiFilePrefix(countryCallingCode, nonGeographicalRegions, - phoneNumberMetadataFilePrefix, metadataLoader); - } - - // A country calling code is non-geographical if it only maps to the non-geographical region code, - // i.e. "001". - private boolean isNonGeographical(int countryCallingCode) { - List regionCodes = - CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap().get(countryCallingCode); - return (regionCodes.size() == 1 - && PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCodes.get(0))); - } -} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java index c7bde8e13..b812551db 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java @@ -24,6 +24,7 @@ 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; @@ -575,7 +576,9 @@ final class PhoneNumberMatcher implements Iterator { } // If this didn't pass, see if there are any alternate formats that match, and try them instead. PhoneMetadata alternateFormats = - MetadataManager.getAlternateFormatsForCountry(number.getCountryCode()); + DefaultMetadataDependenciesProvider.getInstance() + .getAlternateFormatsMetadataSource() + .getFormattingMetadataForCountryCallingCode(number.getCountryCode()); String nationalSignificantNumber = util.getNationalSignificantNumber(number); if (alternateFormats != null) { for (NumberFormat alternateFormat : alternateFormats.getNumberFormatList()) { diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java index 646b13450..8c5c10a47 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java @@ -24,11 +24,12 @@ 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.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -121,16 +122,16 @@ public class PhoneNumberUtil { private static final Map ALL_PLUS_NUMBER_GROUPING_SYMBOLS; static { - HashMap mobileTokenMap = new HashMap(); + HashMap mobileTokenMap = new HashMap<>(); mobileTokenMap.put(54, "9"); MOBILE_TOKEN_MAPPINGS = Collections.unmodifiableMap(mobileTokenMap); - HashSet geoMobileCountriesWithoutMobileAreaCodes = new HashSet(); + HashSet geoMobileCountriesWithoutMobileAreaCodes = new HashSet<>(); geoMobileCountriesWithoutMobileAreaCodes.add(86); // China GEO_MOBILE_COUNTRIES_WITHOUT_MOBILE_AREA_CODES = Collections.unmodifiableSet(geoMobileCountriesWithoutMobileAreaCodes); - HashSet geoMobileCountries = new HashSet(); + HashSet geoMobileCountries = new HashSet<>(); geoMobileCountries.add(52); // Mexico geoMobileCountries.add(54); // Argentina geoMobileCountries.add(55); // Brazil @@ -140,7 +141,7 @@ public class PhoneNumberUtil { // Simple ASCII digits map used to populate ALPHA_PHONE_MAPPINGS and // ALL_PLUS_NUMBER_GROUPING_SYMBOLS. - HashMap asciiDigitMappings = new HashMap(); + HashMap asciiDigitMappings = new HashMap<>(); asciiDigitMappings.put('0', '0'); asciiDigitMappings.put('1', '1'); asciiDigitMappings.put('2', '2'); @@ -152,7 +153,7 @@ public class PhoneNumberUtil { asciiDigitMappings.put('8', '8'); asciiDigitMappings.put('9', '9'); - HashMap alphaMap = new HashMap(40); + HashMap alphaMap = new HashMap<>(40); alphaMap.put('A', '2'); alphaMap.put('B', '2'); alphaMap.put('C', '2'); @@ -181,19 +182,19 @@ public class PhoneNumberUtil { alphaMap.put('Z', '9'); ALPHA_MAPPINGS = Collections.unmodifiableMap(alphaMap); - HashMap combinedMap = new HashMap(100); + HashMap combinedMap = new HashMap<>(100); combinedMap.putAll(ALPHA_MAPPINGS); combinedMap.putAll(asciiDigitMappings); ALPHA_PHONE_MAPPINGS = Collections.unmodifiableMap(combinedMap); - HashMap diallableCharMap = new HashMap(); + 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(); + 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); @@ -308,8 +309,8 @@ public class PhoneNumberUtil { // version. private static final String EXTN_PATTERNS_FOR_PARSING = createExtnPattern(true); static final String EXTN_PATTERNS_FOR_MATCHING = createExtnPattern(false); - - /** + + /** * Helper method for constructing regular expressions for parsing. Creates an expression that * captures up to maxLength digits. */ @@ -659,7 +660,7 @@ public class PhoneNumberUtil { // 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); + 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 @@ -669,11 +670,11 @@ public class PhoneNumberUtil { // 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); + 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(); + private final Set countryCodesForNonGeographicalRegion = new HashSet<>(); /** * This class implements a singleton, the constructor is only visible to facilitate testing. @@ -1089,7 +1090,7 @@ public class PhoneNumberUtil { * be non-null. */ private Set getSupportedTypesForMetadata(PhoneMetadata metadata) { - Set types = new TreeSet(); + 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 @@ -1149,7 +1150,9 @@ public class PhoneNumberUtil { */ public static synchronized PhoneNumberUtil getInstance() { if (instance == null) { - setInstance(createInstance(MetadataManager.DEFAULT_METADATA_LOADER)); + MetadataLoader metadataLoader = DefaultMetadataDependenciesProvider.getInstance() + .getMetadataLoader(); + setInstance(createInstance(metadataLoader)); } return instance; } @@ -1170,7 +1173,11 @@ public class PhoneNumberUtil { if (metadataLoader == null) { throw new IllegalArgumentException("metadataLoader could not be null."); } - return createInstance(new MultiFileMetadataSourceImpl(metadataLoader)); + return createInstance(new MetadataSourceImpl( + DefaultMetadataDependenciesProvider.getInstance().getPhoneNumberMetadataFileNameProvider(), + metadataLoader, + DefaultMetadataDependenciesProvider.getInstance().getMetadataParser() + )); } /** @@ -1699,7 +1706,7 @@ public class PhoneNumberUtil { NumberFormat.Builder numFormatCopy = NumberFormat.newBuilder(); numFormatCopy.mergeFrom(formatRule); numFormatCopy.clearNationalPrefixFormattingRule(); - List numberFormats = new ArrayList(1); + List numberFormats = new ArrayList<>(1); numberFormats.add(numFormatCopy.build()); formattedNumber = formatByPattern(number, PhoneNumberFormat.NATIONAL, numberFormats); break; @@ -2585,7 +2592,7 @@ public class PhoneNumberUtil { 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); + 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. @@ -2599,7 +2606,7 @@ public class PhoneNumberUtil { if (localLengths.isEmpty()) { localLengths = mobileDesc.getPossibleLengthLocalOnlyList(); } else { - localLengths = new ArrayList(localLengths); + localLengths = new ArrayList<>(localLengths); localLengths.addAll(mobileDesc.getPossibleLengthLocalOnlyList()); Collections.sort(localLengths); } diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java index 3e7df59e9..7ce2972ba 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java @@ -22,6 +22,8 @@ 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; @@ -44,12 +46,13 @@ public class ShortNumberInfo { private static final Logger logger = Logger.getLogger(ShortNumberInfo.class.getName()); private static final ShortNumberInfo INSTANCE = - new ShortNumberInfo(RegexBasedMatcher.create()); + 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(); + 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"); @@ -61,7 +64,7 @@ public class ShortNumberInfo { TOLL_FREE, STANDARD_RATE, PREMIUM_RATE, - UNKNOWN_COST; + UNKNOWN_COST } /** Returns the singleton instance of the ShortNumberInfo. */ @@ -79,9 +82,13 @@ public class ShortNumberInfo { // first. private final Map> countryCallingCodeToRegionCodeMap; + private final RegionMetadataSource shortNumberMetadataSource; + // @VisibleForTesting - ShortNumberInfo(MatcherApi matcherApi) { + ShortNumberInfo(MatcherApi matcherApi, + RegionMetadataSource shortNumberMetadataSource) { this.matcherApi = matcherApi; + this.shortNumberMetadataSource = shortNumberMetadataSource; // TODO: Create ShortNumberInfo for a given map this.countryCallingCodeToRegionCodeMap = CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap(); @@ -108,6 +115,21 @@ public class ShortNumberInfo { 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}. @@ -120,8 +142,7 @@ public class ShortNumberInfo { if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { return false; } - PhoneMetadata phoneMetadata = - MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); if (phoneMetadata == null) { return false; } @@ -142,7 +163,7 @@ public class ShortNumberInfo { List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); int shortNumberLength = getNationalSignificantNumber(number).length(); for (String region : regionCodes) { - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(region); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(region); if (phoneMetadata == null) { continue; } @@ -166,8 +187,7 @@ public class ShortNumberInfo { if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { return false; } - PhoneMetadata phoneMetadata = - MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); if (phoneMetadata == null) { return false; } @@ -228,8 +248,7 @@ public class ShortNumberInfo { return ShortNumberCost.UNKNOWN_COST; } // Note that regionDialingFrom may be null, in which case phoneMetadata will also be null. - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion( - regionDialingFrom); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); if (phoneMetadata == null) { return ShortNumberCost.UNKNOWN_COST; } @@ -326,7 +345,7 @@ public class ShortNumberInfo { } String nationalNumber = getNationalSignificantNumber(number); for (String regionCode : regionCodes) { - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); if (phoneMetadata != null && matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getShortCode())) { // The number is valid for this region. @@ -336,13 +355,6 @@ public class ShortNumberInfo { return null; } - /** - * Convenience method to get a list of what regions the library has metadata for. - */ - Set getSupportedRegions() { - return MetadataManager.getSupportedShortNumberRegions(); - } - /** * Gets a valid short number for the specified region. * @@ -352,7 +364,7 @@ public class ShortNumberInfo { */ // @VisibleForTesting String getExampleShortNumber(String regionCode) { - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return ""; } @@ -373,7 +385,7 @@ public class ShortNumberInfo { */ // @VisibleForTesting String getExampleShortNumberForCost(String regionCode, ShortNumberCost cost) { - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); if (phoneMetadata == null) { return ""; } @@ -441,7 +453,7 @@ public class ShortNumberInfo { // add additional logic here to handle it. return false; } - PhoneMetadata metadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); + PhoneMetadata metadata = getShortNumberMetadataForRegion(regionCode); if (metadata == null || !metadata.hasEmergency()) { return false; } @@ -468,7 +480,7 @@ public class ShortNumberInfo { List regionCodes = getRegionCodesForCountryCode(number.getCountryCode()); String regionCode = getRegionCodeForShortNumberFromRegionList(number, regionCodes); String nationalNumber = getNationalSignificantNumber(number); - PhoneMetadata phoneMetadata = MetadataManager.getShortNumberMetadataForRegion(regionCode); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionCode); return (phoneMetadata != null) && (matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getCarrierSpecific())); @@ -492,8 +504,7 @@ public class ShortNumberInfo { return false; } String nationalNumber = getNationalSignificantNumber(number); - PhoneMetadata phoneMetadata = - MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); return (phoneMetadata != null) && (matchesPossibleNumberAndNationalNumber(nationalNumber, phoneMetadata.getCarrierSpecific())); @@ -516,8 +527,7 @@ public class ShortNumberInfo { if (!regionDialingFromMatchesNumber(number, regionDialingFrom)) { return false; } - PhoneMetadata phoneMetadata = - MetadataManager.getShortNumberMetadataForRegion(regionDialingFrom); + PhoneMetadata phoneMetadata = getShortNumberMetadataForRegion(regionDialingFrom); return phoneMetadata != null && matchesPossibleNumberAndNationalNumber(getNationalSignificantNumber(number), phoneMetadata.getSmsServices()); diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/SingleFileMetadataSourceImpl.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/SingleFileMetadataSourceImpl.java deleted file mode 100644 index a988a543e..000000000 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/SingleFileMetadataSourceImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2015 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 java.util.concurrent.atomic.AtomicReference; - -/** - * Implementation of {@link MetadataSource} that reads from a single resource file. - */ -final class SingleFileMetadataSourceImpl implements MetadataSource { - // The name of the binary file containing phone number metadata for different regions. - // This enables us to set up with different metadata, such as for testing. - private final String phoneNumberMetadataFileName; - - // The {@link MetadataLoader} used to inject alternative metadata sources. - private final MetadataLoader metadataLoader; - - private final AtomicReference phoneNumberMetadataRef = - new AtomicReference(); - - // It is assumed that metadataLoader is not null. Checks should happen before passing it in here. - // @VisibleForTesting - SingleFileMetadataSourceImpl(String phoneNumberMetadataFileName, MetadataLoader metadataLoader) { - this.phoneNumberMetadataFileName = phoneNumberMetadataFileName; - this.metadataLoader = metadataLoader; - } - - // It is assumed that metadataLoader is not null. Checks should happen before passing it in here. - SingleFileMetadataSourceImpl(MetadataLoader metadataLoader) { - this(MetadataManager.SINGLE_FILE_PHONE_NUMBER_METADATA_FILE_NAME, metadataLoader); - } - - @Override - public PhoneMetadata getMetadataForRegion(String regionCode) { - return MetadataManager.getSingleFileMetadataMaps(phoneNumberMetadataRef, - phoneNumberMetadataFileName, metadataLoader).get(regionCode); - } - - @Override - public PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) { - // A country calling code is non-geographical if it only maps to the non-geographical region - // code, i.e. "001". If this is not true of the given country calling code, then we will return - // null here. If not for the atomic reference, such as if we were loading in multiple stages, we - // would check that the passed in country calling code was indeed non-geographical to avoid - // loading costs for a null result. Here though we do not check this since the entire data must - // be loaded anyway if any of it is needed at some point in the life cycle of this class. - return MetadataManager.getSingleFileMetadataMaps(phoneNumberMetadataRef, - phoneNumberMetadataFileName, metadataLoader).get(countryCallingCode); - } -} diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java index b3b88f202..06fd6ad62 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java @@ -23,9 +23,10 @@ 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; -import com.google.i18n.phonenumbers.metadata.source.SingleFileModeFileNameProvider; /** * Provides metadata init & source dependencies when metadata is stored in multi-file mode and @@ -39,26 +40,36 @@ public final class DefaultMetadataDependenciesProvider { return INSTANCE; } - private DefaultMetadataDependenciesProvider() {} + private DefaultMetadataDependenciesProvider() { + } - private final MetadataParser metadataParser = MetadataParser.newStrictParser(); + 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( - new SingleFileModeFileNameProvider( - "/com/google/i18n/phonenumbers/buildtools/PhoneNumberMetadataProto"), + phoneNumberMetadataFileNameProvider, metadataLoader, metadataParser); + + private final PhoneMetadataFileNameProvider shortNumberMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto"); private final RegionMetadataSource shortNumberMetadataSource = new RegionMetadataSourceImpl( - new SingleFileModeFileNameProvider( - "/com/google/i18n/phonenumbers/buildtools/ShortNumberMetadataProto"), + shortNumberMetadataFileNameProvider, metadataLoader, metadataParser); + + private final PhoneMetadataFileNameProvider alternateFormatsMetadataFileNameProvider = + new MultiFileModeFileNameProvider( + "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto"); private final FormattingMetadataSource alternateFormatsMetadataSource = new FormattingMetadataSourceImpl( - new SingleFileModeFileNameProvider( - "/com/google/i18n/phonenumbers/buildtools/PhoneNumberAlternateFormatsProto"), + alternateFormatsMetadataFileNameProvider, metadataLoader, metadataParser); @@ -70,14 +81,26 @@ public final class DefaultMetadataDependenciesProvider { 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; } diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java index ebea7b7d3..e98470bfa 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ExampleNumbersTest.java @@ -19,15 +19,15 @@ package com.google.i18n.phonenumbers; import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType; import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc; import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; - -import junit.framework.TestCase; - +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import junit.framework.TestCase; /** * Verifies all of the example numbers in the metadata are valid and of the correct type. If no @@ -37,10 +37,14 @@ import java.util.logging.Logger; */ public class ExampleNumbersTest extends TestCase { private static final Logger logger = Logger.getLogger(ExampleNumbersTest.class.getName()); - private PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); - private ShortNumberInfo shortNumberInfo = ShortNumberInfo.getInstance(); - private List invalidCases = new ArrayList(); - private List wrongTypeCases = new ArrayList(); + private final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); + private final ShortNumberInfo shortNumberInfo = ShortNumberInfo.getInstance(); + private final RegionMetadataSource shortNumberMetadataSource = + DefaultMetadataDependenciesProvider.getInstance().getShortNumberMetadataSource(); + + private final List invalidCases = new ArrayList<>(); + private final List wrongTypeCases = new ArrayList<>(); + private final Set shortNumberSupportedRegions = ShortNumbersRegionCodeSet.getRegionCodeSet(); /** * @param exampleNumberRequestedType type we are requesting an example number for @@ -55,14 +59,14 @@ public class ExampleNumbersTest extends TestCase { if (exampleNumber != null) { if (!phoneNumberUtil.isValidNumber(exampleNumber)) { invalidCases.add(exampleNumber); - logger.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString()); + logger.log(Level.SEVERE, "Failed validation for " + exampleNumber); } else { // We know the number is valid, now we check the type. PhoneNumberType exampleNumberType = phoneNumberUtil.getNumberType(exampleNumber); if (!possibleExpectedTypes.contains(exampleNumberType)) { wrongTypeCases.add(exampleNumber); logger.log(Level.SEVERE, "Wrong type for " - + exampleNumber.toString() + + exampleNumber + ": got " + exampleNumberType); logger.log(Level.WARNING, "Expected types: "); for (PhoneNumberType type : possibleExpectedTypes) { @@ -74,7 +78,7 @@ public class ExampleNumbersTest extends TestCase { } } - public void testFixedLine() throws Exception { + public void testFixedLine() { Set fixedLineTypes = EnumSet.of(PhoneNumberType.FIXED_LINE, PhoneNumberType.FIXED_LINE_OR_MOBILE); checkNumbersValidAndCorrectType(PhoneNumberType.FIXED_LINE, fixedLineTypes); @@ -82,7 +86,7 @@ public class ExampleNumbersTest extends TestCase { assertEquals(0, wrongTypeCases.size()); } - public void testMobile() throws Exception { + public void testMobile() { Set mobileTypes = EnumSet.of(PhoneNumberType.MOBILE, PhoneNumberType.FIXED_LINE_OR_MOBILE); checkNumbersValidAndCorrectType(PhoneNumberType.MOBILE, mobileTypes); @@ -90,56 +94,56 @@ public class ExampleNumbersTest extends TestCase { assertEquals(0, wrongTypeCases.size()); } - public void testTollFree() throws Exception { + public void testTollFree() { Set tollFreeTypes = EnumSet.of(PhoneNumberType.TOLL_FREE); checkNumbersValidAndCorrectType(PhoneNumberType.TOLL_FREE, tollFreeTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testPremiumRate() throws Exception { + public void testPremiumRate() { Set premiumRateTypes = EnumSet.of(PhoneNumberType.PREMIUM_RATE); checkNumbersValidAndCorrectType(PhoneNumberType.PREMIUM_RATE, premiumRateTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testVoip() throws Exception { + public void testVoip() { Set voipTypes = EnumSet.of(PhoneNumberType.VOIP); checkNumbersValidAndCorrectType(PhoneNumberType.VOIP, voipTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testPager() throws Exception { + public void testPager() { Set pagerTypes = EnumSet.of(PhoneNumberType.PAGER); checkNumbersValidAndCorrectType(PhoneNumberType.PAGER, pagerTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testUan() throws Exception { + public void testUan() { Set uanTypes = EnumSet.of(PhoneNumberType.UAN); checkNumbersValidAndCorrectType(PhoneNumberType.UAN, uanTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testVoicemail() throws Exception { + public void testVoicemail() { Set voicemailTypes = EnumSet.of(PhoneNumberType.VOICEMAIL); checkNumbersValidAndCorrectType(PhoneNumberType.VOICEMAIL, voicemailTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testSharedCost() throws Exception { + public void testSharedCost() { Set sharedCostTypes = EnumSet.of(PhoneNumberType.SHARED_COST); checkNumbersValidAndCorrectType(PhoneNumberType.SHARED_COST, sharedCostTypes); assertEquals(0, invalidCases.size()); assertEquals(0, wrongTypeCases.size()); } - public void testCanBeInternationallyDialled() throws Exception { + public void testCanBeInternationallyDialled() { for (String regionCode : phoneNumberUtil.getSupportedRegions()) { PhoneNumber exampleNumber = null; PhoneNumberDesc desc = @@ -153,41 +157,41 @@ public class ExampleNumbersTest extends TestCase { } if (exampleNumber != null && phoneNumberUtil.canBeInternationallyDialled(exampleNumber)) { wrongTypeCases.add(exampleNumber); - logger.log(Level.SEVERE, "Number " + exampleNumber.toString() + logger.log(Level.SEVERE, "Number " + exampleNumber + " should not be internationally diallable"); } } assertEquals(0, wrongTypeCases.size()); } - public void testGlobalNetworkNumbers() throws Exception { + public void testGlobalNetworkNumbers() { for (Integer callingCode : phoneNumberUtil.getSupportedGlobalNetworkCallingCodes()) { PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumberForNonGeoEntity(callingCode); assertNotNull("No example phone number for calling code " + callingCode, exampleNumber); if (!phoneNumberUtil.isValidNumber(exampleNumber)) { invalidCases.add(exampleNumber); - logger.log(Level.SEVERE, "Failed validation for " + exampleNumber.toString()); + logger.log(Level.SEVERE, "Failed validation for " + exampleNumber); } } assertEquals(0, invalidCases.size()); } - public void testEveryRegionHasAnExampleNumber() throws Exception { + public void testEveryRegionHasAnExampleNumber() { for (String regionCode : phoneNumberUtil.getSupportedRegions()) { PhoneNumber exampleNumber = phoneNumberUtil.getExampleNumber(regionCode); assertNotNull("No example number found for region " + regionCode, exampleNumber); } } - public void testEveryRegionHasAnInvalidExampleNumber() throws Exception { + public void testEveryRegionHasAnInvalidExampleNumber() { for (String regionCode : phoneNumberUtil.getSupportedRegions()) { PhoneNumber exampleNumber = phoneNumberUtil.getInvalidExampleNumber(regionCode); assertNotNull("No invalid example number found for region " + regionCode, exampleNumber); } } - public void testEveryTypeHasAnExampleNumber() throws Exception { + public void testEveryTypeHasAnExampleNumber() { for (PhoneNumberUtil.PhoneNumberType type : PhoneNumberUtil.PhoneNumberType.values()) { if (type == PhoneNumberType.UNKNOWN) { continue; @@ -198,8 +202,8 @@ public class ExampleNumbersTest extends TestCase { } public void testShortNumbersValidAndCorrectCost() throws Exception { - List invalidStringCases = new ArrayList(); - for (String regionCode : shortNumberInfo.getSupportedRegions()) { + List invalidStringCases = new ArrayList<>(); + for (String regionCode : shortNumberSupportedRegions) { String exampleShortNumber = shortNumberInfo.getExampleShortNumber(regionCode); if (!shortNumberInfo.isValidShortNumberForRegion( phoneNumberUtil.parse(exampleShortNumber, regionCode), regionCode)) { @@ -211,7 +215,7 @@ public class ExampleNumbersTest extends TestCase { PhoneNumber phoneNumber = phoneNumberUtil.parse(exampleShortNumber, regionCode); if (!shortNumberInfo.isValidShortNumber(phoneNumber)) { invalidCases.add(phoneNumber); - logger.log(Level.SEVERE, "Failed validation for " + phoneNumber.toString()); + logger.log(Level.SEVERE, "Failed validation for " + phoneNumber); } for (ShortNumberInfo.ShortNumberCost cost : ShortNumberInfo.ShortNumberCost.values()) { @@ -236,9 +240,8 @@ public class ExampleNumbersTest extends TestCase { public void testEmergency() throws Exception { int wrongTypeCounter = 0; - for (String regionCode : shortNumberInfo.getSupportedRegions()) { - PhoneNumberDesc desc = - MetadataManager.getShortNumberMetadataForRegion(regionCode).getEmergency(); + for (String regionCode : shortNumberSupportedRegions) { + PhoneNumberDesc desc = shortNumberMetadataSource.getMetadataForRegion(regionCode).getEmergency(); if (desc.hasExampleNumber()) { String exampleNumber = desc.getExampleNumber(); PhoneNumber phoneNumber = phoneNumberUtil.parse(exampleNumber, regionCode); @@ -258,9 +261,8 @@ public class ExampleNumbersTest extends TestCase { public void testCarrierSpecificShortNumbers() throws Exception { int wrongTagCounter = 0; - for (String regionCode : shortNumberInfo.getSupportedRegions()) { - PhoneNumberDesc desc = - MetadataManager.getShortNumberMetadataForRegion(regionCode).getCarrierSpecific(); + for (String regionCode : shortNumberSupportedRegions) { + PhoneNumberDesc desc = shortNumberMetadataSource.getMetadataForRegion(regionCode).getCarrierSpecific(); if (desc.hasExampleNumber()) { String exampleNumber = desc.getExampleNumber(); PhoneNumber carrierSpecificNumber = phoneNumberUtil.parse(exampleNumber, regionCode); @@ -276,9 +278,8 @@ public class ExampleNumbersTest extends TestCase { public void testSmsServiceShortNumbers() throws Exception { int wrongTagCounter = 0; - for (String regionCode : shortNumberInfo.getSupportedRegions()) { - PhoneNumberDesc desc = - MetadataManager.getShortNumberMetadataForRegion(regionCode).getSmsServices(); + for (String regionCode : shortNumberSupportedRegions) { + PhoneNumberDesc desc = shortNumberMetadataSource.getMetadataForRegion(regionCode).getSmsServices(); if (desc.hasExampleNumber()) { String exampleNumber = desc.getExampleNumber(); PhoneNumber smsServiceNumber = phoneNumberUtil.parse(exampleNumber, regionCode); diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java deleted file mode 100644 index 91b2f3950..000000000 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/MetadataManagerTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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. - */ - -package com.google.i18n.phonenumbers; - -import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata; -import java.util.concurrent.ConcurrentHashMap; -import junit.framework.TestCase; - -/** - * Some basic tests to check that metadata can be correctly loaded. - */ -public class MetadataManagerTest extends TestCase { - public void testAlternateFormatsLoadCorrectly() { - // We should have some data for Germany. - PhoneMetadata germanyMetadata = MetadataManager.getAlternateFormatsForCountry(49); - assertNotNull(germanyMetadata); - assertTrue(germanyMetadata.getNumberFormatCount() > 0); - } - - public void testAlternateFormatsFailsGracefully() throws Exception { - PhoneMetadata noAlternateFormats = MetadataManager.getAlternateFormatsForCountry(999); - assertNull(noAlternateFormats); - } - - public void testShortNumberMetadataLoadCorrectly() throws Exception { - // We should have some data for France. - PhoneMetadata franceMetadata = MetadataManager.getShortNumberMetadataForRegion("FR"); - assertNotNull(franceMetadata); - assertTrue(franceMetadata.hasShortCode()); - } - - public void testShortNumberMetadataFailsGracefully() throws Exception { - PhoneMetadata noShortNumberMetadata = MetadataManager.getShortNumberMetadataForRegion("XXX"); - assertNull(noShortNumberMetadata); - } - - public void testGetMetadataFromMultiFilePrefix_regionCode() { - ConcurrentHashMap map = new ConcurrentHashMap(); - PhoneMetadata metadata = MetadataManager.getMetadataFromMultiFilePrefix("CA", map, - "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting", - MetadataManager.DEFAULT_METADATA_LOADER); - assertEquals(metadata, map.get("CA")); - } - - public void testGetMetadataFromMultiFilePrefix_countryCallingCode() { - ConcurrentHashMap map = new ConcurrentHashMap(); - PhoneMetadata metadata = MetadataManager.getMetadataFromMultiFilePrefix(800, map, - "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting", - MetadataManager.DEFAULT_METADATA_LOADER); - assertEquals(metadata, map.get(800)); - } - - public void testGetMetadataFromMultiFilePrefix_missingMetadataFileThrowsRuntimeException() { - // In normal usage we should never get a state where we are asking to load metadata that doesn't - // exist. However if the library is packaged incorrectly in the jar, this could happen and the - // best we can do is make sure the exception has the file name in it. - try { - MetadataManager.getMetadataFromMultiFilePrefix("XX", - new ConcurrentHashMap(), "no/such/file", - MetadataManager.DEFAULT_METADATA_LOADER); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file_XX")); - } - try { - MetadataManager.getMetadataFromMultiFilePrefix(123, - new ConcurrentHashMap(), "no/such/file", - MetadataManager.DEFAULT_METADATA_LOADER); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file_123")); - } - } -} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/MultiFileMetadataSourceImplTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/MultiFileMetadataSourceImplTest.java deleted file mode 100644 index 7c9b0fafe..000000000 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/MultiFileMetadataSourceImplTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 junit.framework.TestCase; - -/** - * Unit tests for MultiFileMetadataSourceImpl.java. - */ -public class MultiFileMetadataSourceImplTest extends TestCase { - private static final MultiFileMetadataSourceImpl SOURCE = - new MultiFileMetadataSourceImpl(MetadataManager.DEFAULT_METADATA_LOADER); - private static final MultiFileMetadataSourceImpl MISSING_FILE_SOURCE = - new MultiFileMetadataSourceImpl("no/such/file", MetadataManager.DEFAULT_METADATA_LOADER); - - public void testGeoPhoneNumberMetadataLoadCorrectly() { - // We should have some data for the UAE. - PhoneMetadata uaeMetadata = SOURCE.getMetadataForRegion("AE"); - assertEquals(uaeMetadata.getCountryCode(), 971); - assertTrue(uaeMetadata.hasGeneralDesc()); - } - - public void testGeoPhoneNumberMetadataLoadFromMissingFileThrowsException() throws Exception { - try { - MISSING_FILE_SOURCE.getMetadataForRegion("AE"); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file")); - } - } - - public void testNonGeoPhoneNumberMetadataLoadCorrectly() { - // We should have some data for international toll-free numbers. - PhoneMetadata intlMetadata = SOURCE.getMetadataForNonGeographicalRegion(800); - assertEquals(intlMetadata.getId(), "001"); - assertTrue(intlMetadata.hasGeneralDesc()); - } - - public void testNonGeoPhoneNumberMetadataLoadFromMissingFileThrowsException() throws Exception { - try { - MISSING_FILE_SOURCE.getMetadataForNonGeographicalRegion(800); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file")); - } - } -} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/SingleFileMetadataSourceImplTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/SingleFileMetadataSourceImplTest.java deleted file mode 100644 index 664fc52d5..000000000 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/SingleFileMetadataSourceImplTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 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 junit.framework.TestCase; - -/** - * Unit tests for SingleFileMetadataSourceImpl.java. - * - *

- * We do not package single file metadata files, so it is only possible to test failures here. - */ -public class SingleFileMetadataSourceImplTest extends TestCase { - private static final SingleFileMetadataSourceImpl MISSING_FILE_SOURCE = - new SingleFileMetadataSourceImpl("no/such/file", MetadataManager.DEFAULT_METADATA_LOADER); - - public void testGeoPhoneNumberMetadataLoadFromMissingFileThrowsException() throws Exception { - try { - MISSING_FILE_SOURCE.getMetadataForRegion("AE"); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file")); - } - } - - public void testNonGeoPhoneNumberMetadataLoadFromMissingFileThrowsException() throws Exception { - try { - MISSING_FILE_SOURCE.getMetadataForNonGeographicalRegion(800); - fail("expected exception"); - } catch (RuntimeException e) { - assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file")); - } - } -} diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java index 51360d71a..5dfb56e96 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java @@ -16,6 +16,9 @@ package com.google.i18n.phonenumbers; +import com.google.i18n.phonenumbers.metadata.DefaultMetadataDependenciesProvider; +import com.google.i18n.phonenumbers.metadata.source.MetadataSourceImpl; +import com.google.i18n.phonenumbers.metadata.source.MultiFileModeFileNameProvider; import junit.framework.TestCase; /** @@ -33,15 +36,20 @@ import junit.framework.TestCase; * @author Shaopeng Jia */ public class TestMetadataTestCase extends TestCase { + private static final String TEST_METADATA_FILE_PREFIX = "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting"; - /** An instance of PhoneNumberUtil that uses test metadata. */ + /** + * An instance of PhoneNumberUtil that uses test metadata. + */ protected final PhoneNumberUtil phoneUtil; public TestMetadataTestCase() { - phoneUtil = new PhoneNumberUtil(new MultiFileMetadataSourceImpl(TEST_METADATA_FILE_PREFIX, - MetadataManager.DEFAULT_METADATA_LOADER), + phoneUtil = new PhoneNumberUtil( + new MetadataSourceImpl(new MultiFileModeFileNameProvider(TEST_METADATA_FILE_PREFIX), + DefaultMetadataDependenciesProvider.getInstance().getMetadataLoader(), + DefaultMetadataDependenciesProvider.getInstance().getMetadataParser()), CountryCodeToRegionCodeMapForTesting.getCountryCodeToRegionCodeMap()); }