phonelib 0.4.9 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +14 -3
  3. data/data/extended_data.dat +0 -0
  4. data/data/libphonenumber/README.md +5 -1
  5. data/data/libphonenumber/cpp/src/phonenumbers/lite_metadata.cc +10195 -10134
  6. data/data/libphonenumber/cpp/src/phonenumbers/metadata.cc +11081 -11017
  7. data/data/libphonenumber/cpp/src/phonenumbers/short_metadata.cc +1514 -1509
  8. data/data/libphonenumber/cpp/src/phonenumbers/shortnumberinfo.cc +22 -0
  9. data/data/libphonenumber/cpp/src/phonenumbers/shortnumberinfo.h +3 -0
  10. data/data/libphonenumber/cpp/src/phonenumbers/test_metadata.cc +128 -120
  11. data/data/libphonenumber/cpp/test/phonenumbers/shortnumberinfo_test.cc +13 -0
  12. data/data/libphonenumber/java/carrier/pom.xml +4 -4
  13. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/230_en +0 -0
  14. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/235_en +0 -0
  15. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/239_en +0 -0
  16. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/263_en +0 -0
  17. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/41_en +0 -0
  18. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/509_en +0 -0
  19. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/61_en +0 -0
  20. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/91_en +0 -0
  21. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/976_en +0 -0
  22. data/data/libphonenumber/java/carrier/src/com/google/i18n/phonenumbers/carrier/data/config +0 -0
  23. data/data/libphonenumber/java/demo/pom.xml +5 -5
  24. data/data/libphonenumber/java/geocoder/pom.xml +4 -4
  25. data/data/libphonenumber/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/263_en +0 -0
  26. data/data/libphonenumber/java/geocoder/src/com/google/i18n/phonenumbers/geocoding/data/config +0 -0
  27. data/data/libphonenumber/java/geocoder/src/com/google/i18n/phonenumbers/timezones/data/map_data +0 -0
  28. data/data/libphonenumber/java/internal/prefixmapper/pom.xml +3 -3
  29. data/data/libphonenumber/java/libphonenumber/pom.xml +2 -2
  30. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/MetadataSource.java +38 -0
  31. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/MultiFileMetadataSourceImpl.java +155 -0
  32. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java +31 -109
  33. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/ShortNumberInfo.java +19 -0
  34. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AR +0 -0
  35. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_AU +0 -0
  36. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BY +0 -0
  37. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_CR +0 -0
  38. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_DZ +0 -0
  39. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_EH +0 -0
  40. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ES +0 -0
  41. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HK +0 -0
  42. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_HT +0 -0
  43. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_IN +0 -0
  44. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_JO +0 -0
  45. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MN +0 -0
  46. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MU +0 -0
  47. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_MX +0 -0
  48. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_PL +0 -0
  49. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ST +0 -0
  50. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_SZ +0 -0
  51. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TD +0 -0
  52. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_TT +0 -0
  53. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_YT +0 -0
  54. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_ZW +0 -0
  55. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_HK +0 -0
  56. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_KR +0 -0
  57. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_MX +0 -0
  58. data/data/libphonenumber/java/libphonenumber/src/com/google/i18n/phonenumbers/data/ShortNumberMetadataProto_ZW +0 -0
  59. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java +6 -2
  60. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/MultiFileMetadataSourceImplTest.java +51 -0
  61. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java +0 -20
  62. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java +11 -0
  63. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/TestMetadataTestCase.java +3 -2
  64. data/data/libphonenumber/java/libphonenumber/test/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting_SE +0 -0
  65. data/data/libphonenumber/java/pom.xml +1 -1
  66. data/data/libphonenumber/java/release_notes.txt +16 -0
  67. data/data/libphonenumber/javascript/i18n/phonenumbers/demo-compiled.js +135 -133
  68. data/data/libphonenumber/javascript/i18n/phonenumbers/metadata.js +54 -48
  69. data/data/libphonenumber/javascript/i18n/phonenumbers/metadatafortesting.js +14 -0
  70. data/data/libphonenumber/javascript/i18n/phonenumbers/metadatalite.js +54 -48
  71. data/data/libphonenumber/resources/PhoneNumberMetadata.xml +366 -256
  72. data/data/libphonenumber/resources/PhoneNumberMetadataForTesting.xml +4 -0
  73. data/data/libphonenumber/resources/ShortNumberMetadata.xml +52 -15
  74. data/data/libphonenumber/resources/carrier/en/230.txt +2 -0
  75. data/data/libphonenumber/resources/carrier/en/235.txt +1 -0
  76. data/data/libphonenumber/resources/carrier/en/239.txt +1 -0
  77. data/data/libphonenumber/resources/carrier/en/263.txt +1 -0
  78. data/data/libphonenumber/resources/carrier/en/41.txt +1 -1
  79. data/data/libphonenumber/resources/carrier/en/509.txt +24 -0
  80. data/data/libphonenumber/resources/carrier/en/61.txt +1 -0
  81. data/data/libphonenumber/resources/carrier/en/91.txt +1726 -830
  82. data/data/libphonenumber/resources/carrier/en/976.txt +18 -0
  83. data/data/libphonenumber/resources/geocoding/en/263.txt +40 -22
  84. data/data/libphonenumber/resources/timezones/map_data.txt +24 -11
  85. data/data/libphonenumber/tools/java/cpp-build/pom.xml +1 -1
  86. data/data/libphonenumber/tools/java/cpp-build/target/cpp-build-1.0-SNAPSHOT-jar-with-dependencies.jar +0 -0
  87. data/data/libphonenumber/tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar +0 -0
  88. data/data/phone_data.dat +0 -0
  89. data/lib/phonelib.rb +1 -0
  90. data/lib/phonelib/core.rb +1 -0
  91. data/lib/phonelib/data_importer_helper.rb +1 -0
  92. data/lib/phonelib/phone.rb +61 -78
  93. data/lib/phonelib/phone_analyzer.rb +1 -1
  94. data/lib/phonelib/phone_extended_data.rb +68 -0
  95. data/lib/phonelib/version.rb +1 -1
  96. metadata +11 -2
@@ -3,14 +3,14 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.googlecode.libphonenumber</groupId>
5
5
  <artifactId>prefixmapper</artifactId>
6
- <version>2.25-SNAPSHOT</version>
6
+ <version>2.27-SNAPSHOT</version>
7
7
  <packaging>jar</packaging>
8
8
  <url>https://github.com/googlei18n/libphonenumber/</url>
9
9
 
10
10
  <parent>
11
11
  <groupId>com.googlecode.libphonenumber</groupId>
12
12
  <artifactId>libphonenumber-parent</artifactId>
13
- <version>7.0.9-SNAPSHOT</version>
13
+ <version>7.0.11-SNAPSHOT</version>
14
14
  <relativePath>../../pom.xml</relativePath>
15
15
  </parent>
16
16
 
@@ -29,7 +29,7 @@
29
29
  <dependency>
30
30
  <groupId>com.googlecode.libphonenumber</groupId>
31
31
  <artifactId>libphonenumber</artifactId>
32
- <version>7.0.9-SNAPSHOT</version>
32
+ <version>7.0.11-SNAPSHOT</version>
33
33
  </dependency>
34
34
  </dependencies>
35
35
 
@@ -3,14 +3,14 @@
3
3
  <modelVersion>4.0.0</modelVersion>
4
4
  <groupId>com.googlecode.libphonenumber</groupId>
5
5
  <artifactId>libphonenumber</artifactId>
6
- <version>7.0.9-SNAPSHOT</version>
6
+ <version>7.0.11-SNAPSHOT</version>
7
7
  <packaging>jar</packaging>
8
8
  <url>https://github.com/googlei18n/libphonenumber/</url>
9
9
 
10
10
  <parent>
11
11
  <groupId>com.googlecode.libphonenumber</groupId>
12
12
  <artifactId>libphonenumber-parent</artifactId>
13
- <version>7.0.9-SNAPSHOT</version>
13
+ <version>7.0.11-SNAPSHOT</version>
14
14
  </parent>
15
15
 
16
16
  <build>
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Copyright (C) 2015 The Libphonenumber Authors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ package com.google.i18n.phonenumbers;
18
+
19
+ import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
20
+
21
+ /**
22
+ * A source for phone metadata from resources.
23
+ */
24
+ interface MetadataSource {
25
+ /**
26
+ * Gets phone metadata for a region.
27
+ * @param regionCode the region code.
28
+ * @return the phone metadata for that region, or null if there is none.
29
+ */
30
+ PhoneMetadata getMetadataForRegion(String regionCode);
31
+
32
+ /**
33
+ * Gets phone metadata for a non-geographical region.
34
+ * @param countryCallingCode the country calling code.
35
+ * @return the phone metadata for that region, or null if there is none.
36
+ */
37
+ PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode);
38
+ }
@@ -0,0 +1,155 @@
1
+ /*
2
+ * Copyright (C) 2015 The Libphonenumber Authors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ package com.google.i18n.phonenumbers;
18
+
19
+ import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
20
+ import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
21
+
22
+ import java.io.IOException;
23
+ import java.io.InputStream;
24
+ import java.io.ObjectInputStream;
25
+ import java.util.Collections;
26
+ import java.util.HashMap;
27
+ import java.util.List;
28
+ import java.util.Map;
29
+ import java.util.logging.Level;
30
+ import java.util.logging.Logger;
31
+
32
+ /**
33
+ * Implementation of {@link MetadataSource} that reads from multiple resource files.
34
+ */
35
+ final class MultiFileMetadataSourceImpl implements MetadataSource {
36
+
37
+ private static final Logger logger =
38
+ Logger.getLogger(MultiFileMetadataSourceImpl.class.getName());
39
+
40
+ private static final String META_DATA_FILE_PREFIX =
41
+ "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto";
42
+
43
+ // A mapping from a region code to the PhoneMetadata for that region.
44
+ // Note: Synchronization, though only needed for the Android version of the library, is used in
45
+ // all versions for consistency.
46
+ private final Map<String, PhoneMetadata> regionToMetadataMap =
47
+ Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
48
+
49
+ // A mapping from a country calling code for a non-geographical entity to the PhoneMetadata for
50
+ // that country calling code. Examples of the country calling codes include 800 (International
51
+ // Toll Free Service) and 808 (International Shared Cost Service).
52
+ // Note: Synchronization, though only needed for the Android version of the library, is used in
53
+ // all versions for consistency.
54
+ private final Map<Integer, PhoneMetadata> countryCodeToNonGeographicalMetadataMap =
55
+ Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
56
+
57
+ // The prefix of the metadata files from which region data is loaded.
58
+ private final String currentFilePrefix;
59
+
60
+ // The metadata loader used to inject alternative metadata sources.
61
+ private final MetadataLoader metadataLoader;
62
+
63
+ // It is assumed that metadataLoader is not null.
64
+ public MultiFileMetadataSourceImpl(String currentFilePrefix, MetadataLoader metadataLoader) {
65
+ this.currentFilePrefix = currentFilePrefix;
66
+ this.metadataLoader = metadataLoader;
67
+ }
68
+
69
+ // It is assumed that metadataLoader is not null.
70
+ public MultiFileMetadataSourceImpl(MetadataLoader metadataLoader) {
71
+ this(META_DATA_FILE_PREFIX, metadataLoader);
72
+ }
73
+
74
+ @Override
75
+ public PhoneMetadata getMetadataForRegion(String regionCode) {
76
+ synchronized (regionToMetadataMap) {
77
+ if (!regionToMetadataMap.containsKey(regionCode)) {
78
+ // The regionCode here will be valid and won't be '001', so we don't need to worry about
79
+ // what to pass in for the country calling code.
80
+ loadMetadataFromFile(currentFilePrefix, regionCode, 0, metadataLoader);
81
+ }
82
+ }
83
+ return regionToMetadataMap.get(regionCode);
84
+ }
85
+
86
+ @Override
87
+ public PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) {
88
+ synchronized (countryCodeToNonGeographicalMetadataMap) {
89
+ if (!countryCodeToNonGeographicalMetadataMap.containsKey(countryCallingCode)) {
90
+ loadMetadataFromFile(currentFilePrefix, PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY,
91
+ countryCallingCode, metadataLoader);
92
+ }
93
+ }
94
+ return countryCodeToNonGeographicalMetadataMap.get(countryCallingCode);
95
+ }
96
+
97
+ // @VisibleForTesting
98
+ void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode,
99
+ MetadataLoader metadataLoader) {
100
+ boolean isNonGeoRegion = PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode);
101
+ String fileName = filePrefix + "_" +
102
+ (isNonGeoRegion ? String.valueOf(countryCallingCode) : regionCode);
103
+ InputStream source = metadataLoader.loadMetadata(fileName);
104
+ if (source == null) {
105
+ logger.log(Level.SEVERE, "missing metadata: " + fileName);
106
+ throw new IllegalStateException("missing metadata: " + fileName);
107
+ }
108
+ ObjectInputStream in = null;
109
+ try {
110
+ in = new ObjectInputStream(source);
111
+ PhoneMetadataCollection metadataCollection = loadMetadataAndCloseInput(in);
112
+ List<PhoneMetadata> metadataList = metadataCollection.getMetadataList();
113
+ if (metadataList.isEmpty()) {
114
+ logger.log(Level.SEVERE, "empty metadata: " + fileName);
115
+ throw new IllegalStateException("empty metadata: " + fileName);
116
+ }
117
+ if (metadataList.size() > 1) {
118
+ logger.log(Level.WARNING, "invalid metadata (too many entries): " + fileName);
119
+ }
120
+ PhoneMetadata metadata = metadataList.get(0);
121
+ if (isNonGeoRegion) {
122
+ countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata);
123
+ } else {
124
+ regionToMetadataMap.put(regionCode, metadata);
125
+ }
126
+ } catch (IOException e) {
127
+ logger.log(Level.SEVERE, "cannot load/parse metadata: " + fileName, e);
128
+ throw new RuntimeException("cannot load/parse metadata: " + fileName, e);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Loads the metadata protocol buffer from the given stream and closes the stream afterwards. Any
134
+ * exceptions that occur while reading the stream are propagated (though exceptions that occur
135
+ * when the stream is closed will be ignored).
136
+ *
137
+ * @param source the non-null stream from which metadata is to be read.
138
+ * @return the loaded metadata protocol buffer.
139
+ */
140
+ private static PhoneMetadataCollection loadMetadataAndCloseInput(ObjectInputStream source) {
141
+ PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection();
142
+ try {
143
+ metadataCollection.readExternal(source);
144
+ } catch (IOException e) {
145
+ logger.log(Level.WARNING, "error reading input (ignored)", e);
146
+ } finally {
147
+ try {
148
+ source.close();
149
+ } catch (IOException e) {
150
+ logger.log(Level.WARNING, "error closing input stream (ignored)", e);
151
+ }
152
+ }
153
+ return metadataCollection;
154
+ }
155
+ }
@@ -18,15 +18,11 @@ package com.google.i18n.phonenumbers;
18
18
 
19
19
  import com.google.i18n.phonenumbers.Phonemetadata.NumberFormat;
20
20
  import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
21
- import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
22
21
  import com.google.i18n.phonenumbers.Phonemetadata.PhoneNumberDesc;
23
22
  import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
24
23
  import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource;
25
24
 
26
- import java.io.IOException;
27
25
  import java.io.InputStream;
28
- import java.io.ObjectInput;
29
- import java.io.ObjectInputStream;
30
26
  import java.util.ArrayList;
31
27
  import java.util.Arrays;
32
28
  import java.util.Collections;
@@ -78,9 +74,6 @@ public class PhoneNumberUtil {
78
74
  // input from overflowing the regular-expression engine.
79
75
  private static final int MAX_INPUT_STRING_LENGTH = 250;
80
76
 
81
- private static final String META_DATA_FILE_PREFIX =
82
- "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto";
83
-
84
77
  // Region-code for the unknown region.
85
78
  private static final String UNKNOWN_REGION = "ZZ";
86
79
 
@@ -535,6 +528,9 @@ public class PhoneNumberUtil {
535
528
  abstract boolean verify(PhoneNumber number, String candidate, PhoneNumberUtil util);
536
529
  }
537
530
 
531
+ // A source of metadata for different regions.
532
+ private final MetadataSource metadataSource;
533
+
538
534
  // A mapping from a country calling code to the region codes which denote the region represented
539
535
  // by that country calling code. In the case of multiple regions sharing a calling code, such as
540
536
  // the NANPA regions, the one indicated with "isMainCountryForCode" in the metadata should be
@@ -546,20 +542,6 @@ public class PhoneNumberUtil {
546
542
  // We set the initial capacity of the HashSet to 35 to offer a load factor of roughly 0.75.
547
543
  private final Set<String> nanpaRegions = new HashSet<String>(35);
548
544
 
549
- // A mapping from a region code to the PhoneMetadata for that region.
550
- // Note: Synchronization, though only needed for the Android version of the library, is used in
551
- // all versions for consistency.
552
- private final Map<String, PhoneMetadata> regionToMetadataMap =
553
- Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
554
-
555
- // A mapping from a country calling code for a non-geographical entity to the PhoneMetadata for
556
- // that country calling code. Examples of the country calling codes include 800 (International
557
- // Toll Free Service) and 808 (International Shared Cost Service).
558
- // Note: Synchronization, though only needed for the Android version of the library, is used in
559
- // all versions for consistency.
560
- private final Map<Integer, PhoneMetadata> countryCodeToNonGeographicalMetadataMap =
561
- Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
562
-
563
545
  // A cache for frequently used region-specific regular expressions.
564
546
  // The initial capacity is set to 100 as this seems to be an optimal value for Android, based on
565
547
  // performance measurements.
@@ -574,19 +556,13 @@ public class PhoneNumberUtil {
574
556
  // currently contains < 12 elements so the default capacity of 16 (load factor=0.75) is fine.
575
557
  private final Set<Integer> countryCodesForNonGeographicalRegion = new HashSet<Integer>();
576
558
 
577
- // The prefix of the metadata files from which region data is loaded.
578
- private final String currentFilePrefix;
579
- // The metadata loader used to inject alternative metadata sources.
580
- private final MetadataLoader metadataLoader;
581
-
582
559
  /**
583
560
  * This class implements a singleton, the constructor is only visible to facilitate testing.
584
561
  */
585
562
  // @VisibleForTesting
586
- PhoneNumberUtil(String filePrefix, MetadataLoader metadataLoader,
563
+ PhoneNumberUtil(MetadataSource metadataSource,
587
564
  Map<Integer, List<String>> countryCallingCodeToRegionCodeMap) {
588
- this.currentFilePrefix = filePrefix;
589
- this.metadataLoader = metadataLoader;
565
+ this.metadataSource = metadataSource;
590
566
  this.countryCallingCodeToRegionCodeMap = countryCallingCodeToRegionCodeMap;
591
567
  for (Map.Entry<Integer, List<String>> entry : countryCallingCodeToRegionCodeMap.entrySet()) {
592
568
  List<String> regionCodes = entry.getValue();
@@ -610,65 +586,6 @@ public class PhoneNumberUtil {
610
586
  nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE));
611
587
  }
612
588
 
613
- // @VisibleForTesting
614
- void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode,
615
- MetadataLoader metadataLoader) {
616
- boolean isNonGeoRegion = REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode);
617
- String fileName = filePrefix + "_" +
618
- (isNonGeoRegion ? String.valueOf(countryCallingCode) : regionCode);
619
- InputStream source = metadataLoader.loadMetadata(fileName);
620
- if (source == null) {
621
- logger.log(Level.SEVERE, "missing metadata: " + fileName);
622
- throw new IllegalStateException("missing metadata: " + fileName);
623
- }
624
- ObjectInputStream in = null;
625
- try {
626
- in = new ObjectInputStream(source);
627
- PhoneMetadataCollection metadataCollection = loadMetadataAndCloseInput(in);
628
- List<PhoneMetadata> metadataList = metadataCollection.getMetadataList();
629
- if (metadataList.isEmpty()) {
630
- logger.log(Level.SEVERE, "empty metadata: " + fileName);
631
- throw new IllegalStateException("empty metadata: " + fileName);
632
- }
633
- if (metadataList.size() > 1) {
634
- logger.log(Level.WARNING, "invalid metadata (too many entries): " + fileName);
635
- }
636
- PhoneMetadata metadata = metadataList.get(0);
637
- if (isNonGeoRegion) {
638
- countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata);
639
- } else {
640
- regionToMetadataMap.put(regionCode, metadata);
641
- }
642
- } catch (IOException e) {
643
- logger.log(Level.SEVERE, "cannot load/parse metadata: " + fileName, e);
644
- throw new RuntimeException("cannot load/parse metadata: " + fileName, e);
645
- }
646
- }
647
-
648
- /**
649
- * Loads the metadata protocol buffer from the given stream and closes the stream afterwards. Any
650
- * exceptions that occur while reading the stream are propagated (though exceptions that occur
651
- * when the stream is closed will be ignored).
652
- *
653
- * @param source the non-null stream from which metadata is to be read.
654
- * @return the loaded metadata protocol buffer.
655
- */
656
- private static PhoneMetadataCollection loadMetadataAndCloseInput(ObjectInputStream source) {
657
- PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection();
658
- try {
659
- metadataCollection.readExternal(source);
660
- } catch (IOException e) {
661
- logger.log(Level.WARNING, "error reading input (ignored)", e);
662
- } finally {
663
- try {
664
- source.close();
665
- } catch (IOException e) {
666
- logger.log(Level.WARNING, "error closing input stream (ignored)", e);
667
- }
668
- }
669
- return metadataCollection;
670
- }
671
-
672
589
  /**
673
590
  * Attempts to extract a possible number from the string passed in. This currently strips all
674
591
  * leading characters that cannot be used to start a phone number. Characters that can be used to
@@ -1019,6 +936,26 @@ public class PhoneNumberUtil {
1019
936
  return instance;
1020
937
  }
1021
938
 
939
+ /**
940
+ * Create a new {@link PhoneNumberUtil} instance to carry out international phone number
941
+ * formatting, parsing, or validation. The instance is loaded with all metadata by
942
+ * using the metadataSource specified.
943
+ *
944
+ * This method should only be used in the rare case in which you want to manage your own
945
+ * metadata loading. Calling this method multiple times is very expensive, as each time
946
+ * a new instance is created from scratch. When in doubt, use {@link #getInstance}.
947
+ *
948
+ * @param metadataSource Customized metadata source. This should not be null.
949
+ * @return a PhoneNumberUtil instance
950
+ */
951
+ public static PhoneNumberUtil createInstance(MetadataSource metadataSource) {
952
+ if (metadataSource == null) {
953
+ throw new IllegalArgumentException("metadataSource could not be null.");
954
+ }
955
+ return new PhoneNumberUtil(metadataSource,
956
+ CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap());
957
+ }
958
+
1022
959
  /**
1023
960
  * Create a new {@link PhoneNumberUtil} instance to carry out international phone number
1024
961
  * formatting, parsing, or validation. The instance is loaded with all metadata by
@@ -1028,16 +965,14 @@ public class PhoneNumberUtil {
1028
965
  * metadata loading. Calling this method multiple times is very expensive, as each time
1029
966
  * a new instance is created from scratch. When in doubt, use {@link #getInstance}.
1030
967
  *
1031
- * @param metadataLoader Customized metadata loader. If null, default metadata loader will
1032
- * be used. This should not be null.
968
+ * @param metadataLoader Customized metadata loader. This should not be null.
1033
969
  * @return a PhoneNumberUtil instance
1034
970
  */
1035
971
  public static PhoneNumberUtil createInstance(MetadataLoader metadataLoader) {
1036
972
  if (metadataLoader == null) {
1037
973
  throw new IllegalArgumentException("metadataLoader could not be null.");
1038
974
  }
1039
- return new PhoneNumberUtil(META_DATA_FILE_PREFIX, metadataLoader,
1040
- CountryCodeToRegionCodeMap.getCountryCodeToRegionCodeMap());
975
+ return createInstance(new MultiFileMetadataSourceImpl(metadataLoader));
1041
976
  }
1042
977
 
1043
978
  /**
@@ -2038,27 +1973,14 @@ public class PhoneNumberUtil {
2038
1973
  if (!isValidRegionCode(regionCode)) {
2039
1974
  return null;
2040
1975
  }
2041
- synchronized (regionToMetadataMap) {
2042
- if (!regionToMetadataMap.containsKey(regionCode)) {
2043
- // The regionCode here will be valid and won't be '001', so we don't need to worry about
2044
- // what to pass in for the country calling code.
2045
- loadMetadataFromFile(currentFilePrefix, regionCode, 0, metadataLoader);
2046
- }
2047
- }
2048
- return regionToMetadataMap.get(regionCode);
1976
+ return metadataSource.getMetadataForRegion(regionCode);
2049
1977
  }
2050
1978
 
2051
1979
  PhoneMetadata getMetadataForNonGeographicalRegion(int countryCallingCode) {
2052
- synchronized (countryCodeToNonGeographicalMetadataMap) {
2053
- if (!countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode)) {
2054
- return null;
2055
- }
2056
- if (!countryCodeToNonGeographicalMetadataMap.containsKey(countryCallingCode)) {
2057
- loadMetadataFromFile(
2058
- currentFilePrefix, REGION_CODE_FOR_NON_GEO_ENTITY, countryCallingCode, metadataLoader);
2059
- }
1980
+ if (!countryCallingCodeToRegionCodeMap.containsKey(countryCallingCode)) {
1981
+ return null;
2060
1982
  }
2061
- return countryCodeToNonGeographicalMetadataMap.get(countryCallingCode);
1983
+ return metadataSource.getMetadataForNonGeographicalRegion(countryCallingCode);
2062
1984
  }
2063
1985
 
2064
1986
  boolean isNumberPossibleForDesc(String nationalNumber, PhoneNumberDesc numberDesc) {