14b867acb917b73e699a596df94445c634c916519Shaopeng Jia/*
24b867acb917b73e699a596df94445c634c916519Shaopeng Jia * Copyright (C) 2012 The Libphonenumber Authors
34b867acb917b73e699a596df94445c634c916519Shaopeng Jia *
44b867acb917b73e699a596df94445c634c916519Shaopeng Jia * Licensed under the Apache License, Version 2.0 (the "License");
54b867acb917b73e699a596df94445c634c916519Shaopeng Jia * you may not use this file except in compliance with the License.
64b867acb917b73e699a596df94445c634c916519Shaopeng Jia * You may obtain a copy of the License at
74b867acb917b73e699a596df94445c634c916519Shaopeng Jia *
84b867acb917b73e699a596df94445c634c916519Shaopeng Jia * http://www.apache.org/licenses/LICENSE-2.0
94b867acb917b73e699a596df94445c634c916519Shaopeng Jia *
104b867acb917b73e699a596df94445c634c916519Shaopeng Jia * Unless required by applicable law or agreed to in writing, software
114b867acb917b73e699a596df94445c634c916519Shaopeng Jia * distributed under the License is distributed on an "AS IS" BASIS,
124b867acb917b73e699a596df94445c634c916519Shaopeng Jia * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b867acb917b73e699a596df94445c634c916519Shaopeng Jia * See the License for the specific language governing permissions and
144b867acb917b73e699a596df94445c634c916519Shaopeng Jia * limitations under the License.
154b867acb917b73e699a596df94445c634c916519Shaopeng Jia */
164b867acb917b73e699a596df94445c634c916519Shaopeng Jia
174b867acb917b73e699a596df94445c634c916519Shaopeng Jiapackage com.android.i18n.phonenumbers;
184b867acb917b73e699a596df94445c634c916519Shaopeng Jia
194b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport com.android.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
204b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport com.android.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
214b867acb917b73e699a596df94445c634c916519Shaopeng Jia
224b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.io.IOException;
234b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.io.InputStream;
244b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.io.ObjectInputStream;
254b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.Collections;
264b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.HashMap;
274b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.Iterator;
28bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jiaimport java.util.List;
294b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.Map;
304b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.Set;
314b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.logging.Level;
324b867acb917b73e699a596df94445c634c916519Shaopeng Jiaimport java.util.logging.Logger;
334b867acb917b73e699a596df94445c634c916519Shaopeng Jia
344b867acb917b73e699a596df94445c634c916519Shaopeng Jia/**
354b867acb917b73e699a596df94445c634c916519Shaopeng Jia * Class encapsulating loading of PhoneNumber Metadata information. Currently this is used only for
364b867acb917b73e699a596df94445c634c916519Shaopeng Jia * additional data files such as PhoneNumberAlternateFormats, but in the future it is envisaged it
37bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia * would handle the main metadata file (PhoneNumberMetadata.xml) as well.
384b867acb917b73e699a596df94445c634c916519Shaopeng Jia */
394b867acb917b73e699a596df94445c634c916519Shaopeng Jiaclass MetadataManager {
404b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private static final String ALTERNATE_FORMATS_FILE_PREFIX =
414b867acb917b73e699a596df94445c634c916519Shaopeng Jia      "/com/android/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto";
42bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private static final String SHORT_NUMBER_METADATA_FILE_PREFIX =
43bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      "/com/android/i18n/phonenumbers/data/ShortNumberMetadataProto";
444b867acb917b73e699a596df94445c634c916519Shaopeng Jia
454b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private static final Logger LOGGER = Logger.getLogger(MetadataManager.class.getName());
464b867acb917b73e699a596df94445c634c916519Shaopeng Jia
474b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private static final Map<Integer, PhoneMetadata> callingCodeToAlternateFormatsMap =
484b867acb917b73e699a596df94445c634c916519Shaopeng Jia      Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
49bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private static final Map<String, PhoneMetadata> regionCodeToShortNumberMetadataMap =
50bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
514b867acb917b73e699a596df94445c634c916519Shaopeng Jia
524b867acb917b73e699a596df94445c634c916519Shaopeng Jia  // A set of which country calling codes there are alternate format data for. If the set has an
534b867acb917b73e699a596df94445c634c916519Shaopeng Jia  // entry for a code, then there should be data for that code linked into the resources.
544b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private static final Set<Integer> countryCodeSet =
554b867acb917b73e699a596df94445c634c916519Shaopeng Jia      AlternateFormatsCountryCodeSet.getCountryCodeSet();
564b867acb917b73e699a596df94445c634c916519Shaopeng Jia
57bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  // A set of which region codes there are short number data for. If the set has an entry for a
58bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  // code, then there should be data for that code linked into the resources.
59bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private static final Set<String> regionCodeSet = ShortNumbersRegionCodeSet.getRegionCodeSet();
60bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia
614b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private MetadataManager() {
624b867acb917b73e699a596df94445c634c916519Shaopeng Jia  }
634b867acb917b73e699a596df94445c634c916519Shaopeng Jia
644b867acb917b73e699a596df94445c634c916519Shaopeng Jia  private static void close(InputStream in) {
654b867acb917b73e699a596df94445c634c916519Shaopeng Jia    if (in != null) {
664b867acb917b73e699a596df94445c634c916519Shaopeng Jia      try {
674b867acb917b73e699a596df94445c634c916519Shaopeng Jia        in.close();
684b867acb917b73e699a596df94445c634c916519Shaopeng Jia      } catch (IOException e) {
694b867acb917b73e699a596df94445c634c916519Shaopeng Jia        LOGGER.log(Level.WARNING, e.toString());
704b867acb917b73e699a596df94445c634c916519Shaopeng Jia      }
714b867acb917b73e699a596df94445c634c916519Shaopeng Jia    }
724b867acb917b73e699a596df94445c634c916519Shaopeng Jia  }
734b867acb917b73e699a596df94445c634c916519Shaopeng Jia
74bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private static void loadAlternateFormatsMetadataFromFile(int countryCallingCode) {
754b867acb917b73e699a596df94445c634c916519Shaopeng Jia    InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
764b867acb917b73e699a596df94445c634c916519Shaopeng Jia        ALTERNATE_FORMATS_FILE_PREFIX + "_" + countryCallingCode);
774b867acb917b73e699a596df94445c634c916519Shaopeng Jia    ObjectInputStream in = null;
784b867acb917b73e699a596df94445c634c916519Shaopeng Jia    try {
794b867acb917b73e699a596df94445c634c916519Shaopeng Jia      in = new ObjectInputStream(source);
804b867acb917b73e699a596df94445c634c916519Shaopeng Jia      PhoneMetadataCollection alternateFormats = new PhoneMetadataCollection();
814b867acb917b73e699a596df94445c634c916519Shaopeng Jia      alternateFormats.readExternal(in);
824b867acb917b73e699a596df94445c634c916519Shaopeng Jia      for (PhoneMetadata metadata : alternateFormats.getMetadataList()) {
834b867acb917b73e699a596df94445c634c916519Shaopeng Jia        callingCodeToAlternateFormatsMap.put(metadata.getCountryCode(), metadata);
844b867acb917b73e699a596df94445c634c916519Shaopeng Jia      }
854b867acb917b73e699a596df94445c634c916519Shaopeng Jia    } catch (IOException e) {
864b867acb917b73e699a596df94445c634c916519Shaopeng Jia      LOGGER.log(Level.WARNING, e.toString());
874b867acb917b73e699a596df94445c634c916519Shaopeng Jia    } finally {
884b867acb917b73e699a596df94445c634c916519Shaopeng Jia      close(in);
894b867acb917b73e699a596df94445c634c916519Shaopeng Jia    }
904b867acb917b73e699a596df94445c634c916519Shaopeng Jia  }
914b867acb917b73e699a596df94445c634c916519Shaopeng Jia
924b867acb917b73e699a596df94445c634c916519Shaopeng Jia  static PhoneMetadata getAlternateFormatsForCountry(int countryCallingCode) {
934b867acb917b73e699a596df94445c634c916519Shaopeng Jia    if (!countryCodeSet.contains(countryCallingCode)) {
944b867acb917b73e699a596df94445c634c916519Shaopeng Jia      return null;
954b867acb917b73e699a596df94445c634c916519Shaopeng Jia    }
964b867acb917b73e699a596df94445c634c916519Shaopeng Jia    synchronized (callingCodeToAlternateFormatsMap) {
974b867acb917b73e699a596df94445c634c916519Shaopeng Jia      if (!callingCodeToAlternateFormatsMap.containsKey(countryCallingCode)) {
98bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        loadAlternateFormatsMetadataFromFile(countryCallingCode);
994b867acb917b73e699a596df94445c634c916519Shaopeng Jia      }
1004b867acb917b73e699a596df94445c634c916519Shaopeng Jia    }
1014b867acb917b73e699a596df94445c634c916519Shaopeng Jia    return callingCodeToAlternateFormatsMap.get(countryCallingCode);
1024b867acb917b73e699a596df94445c634c916519Shaopeng Jia  }
103bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia
104bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  private static void loadShortNumberMetadataFromFile(String regionCode) {
105bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
106bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        SHORT_NUMBER_METADATA_FILE_PREFIX + "_" + regionCode);
107bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    ObjectInputStream in = null;
108bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    try {
109bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      in = new ObjectInputStream(source);
110bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      PhoneMetadataCollection shortNumberMetadata = new PhoneMetadataCollection();
111bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      shortNumberMetadata.readExternal(in);
112bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      for (PhoneMetadata metadata : shortNumberMetadata.getMetadataList()) {
113bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        regionCodeToShortNumberMetadataMap.put(regionCode, metadata);
114bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      }
115bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    } catch (IOException e) {
116bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      LOGGER.log(Level.WARNING, e.toString());
117bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    } finally {
118bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      close(in);
119bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    }
120bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  }
121bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia
122bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  // @VisibleForTesting
123bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  static Set<String> getShortNumberMetadataSupportedRegions() {
124bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    return regionCodeSet;
125bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  }
126bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia
127bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  static PhoneMetadata getShortNumberMetadataForRegion(String regionCode) {
128bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    if (!regionCodeSet.contains(regionCode)) {
129bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      return null;
130bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    }
131bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    synchronized (regionCodeToShortNumberMetadataMap) {
132bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      if (!regionCodeToShortNumberMetadataMap.containsKey(regionCode)) {
133bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia        loadShortNumberMetadataFromFile(regionCode);
134bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia      }
135bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    }
136bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia    return regionCodeToShortNumberMetadataMap.get(regionCode);
137bb78ce92eae2d5de9aa06b27ed3b87bc496c79eeShaopeng Jia  }
1384b867acb917b73e699a596df94445c634c916519Shaopeng Jia}
139