Home | History | Annotate | Download | only in phonenumbers
      1 /*
      2  * Copyright (C) 2012 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.android.i18n.phonenumbers;
     18 
     19 import com.android.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
     20 import com.android.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.Iterator;
     28 import java.util.List;
     29 import java.util.Map;
     30 import java.util.Set;
     31 import java.util.logging.Level;
     32 import java.util.logging.Logger;
     33 
     34 /**
     35  * Class encapsulating loading of PhoneNumber Metadata information. Currently this is used only for
     36  * additional data files such as PhoneNumberAlternateFormats, but in the future it is envisaged it
     37  * would handle the main metadata file (PhoneNumberMetadata.xml) as well.
     38  */
     39 class MetadataManager {
     40   private static final String ALTERNATE_FORMATS_FILE_PREFIX =
     41       "/com/android/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto";
     42   private static final String SHORT_NUMBER_METADATA_FILE_PREFIX =
     43       "/com/android/i18n/phonenumbers/data/ShortNumberMetadataProto";
     44 
     45   private static final Logger LOGGER = Logger.getLogger(MetadataManager.class.getName());
     46 
     47   private static final Map<Integer, PhoneMetadata> callingCodeToAlternateFormatsMap =
     48       Collections.synchronizedMap(new HashMap<Integer, PhoneMetadata>());
     49   private static final Map<String, PhoneMetadata> regionCodeToShortNumberMetadataMap =
     50       Collections.synchronizedMap(new HashMap<String, PhoneMetadata>());
     51 
     52   // A set of which country calling codes there are alternate format data for. If the set has an
     53   // entry for a code, then there should be data for that code linked into the resources.
     54   private static final Set<Integer> countryCodeSet =
     55       AlternateFormatsCountryCodeSet.getCountryCodeSet();
     56 
     57   // A set of which region codes there are short number data for. If the set has an entry for a
     58   // code, then there should be data for that code linked into the resources.
     59   private static final Set<String> regionCodeSet = ShortNumbersRegionCodeSet.getRegionCodeSet();
     60 
     61   private MetadataManager() {
     62   }
     63 
     64   private static void close(InputStream in) {
     65     if (in != null) {
     66       try {
     67         in.close();
     68       } catch (IOException e) {
     69         LOGGER.log(Level.WARNING, e.toString());
     70       }
     71     }
     72   }
     73 
     74   private static void loadAlternateFormatsMetadataFromFile(int countryCallingCode) {
     75     InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
     76         ALTERNATE_FORMATS_FILE_PREFIX + "_" + countryCallingCode);
     77     ObjectInputStream in = null;
     78     try {
     79       in = new ObjectInputStream(source);
     80       PhoneMetadataCollection alternateFormats = new PhoneMetadataCollection();
     81       alternateFormats.readExternal(in);
     82       for (PhoneMetadata metadata : alternateFormats.getMetadataList()) {
     83         callingCodeToAlternateFormatsMap.put(metadata.getCountryCode(), metadata);
     84       }
     85     } catch (IOException e) {
     86       LOGGER.log(Level.WARNING, e.toString());
     87     } finally {
     88       close(in);
     89     }
     90   }
     91 
     92   static PhoneMetadata getAlternateFormatsForCountry(int countryCallingCode) {
     93     if (!countryCodeSet.contains(countryCallingCode)) {
     94       return null;
     95     }
     96     synchronized (callingCodeToAlternateFormatsMap) {
     97       if (!callingCodeToAlternateFormatsMap.containsKey(countryCallingCode)) {
     98         loadAlternateFormatsMetadataFromFile(countryCallingCode);
     99       }
    100     }
    101     return callingCodeToAlternateFormatsMap.get(countryCallingCode);
    102   }
    103 
    104   private static void loadShortNumberMetadataFromFile(String regionCode) {
    105     InputStream source = PhoneNumberMatcher.class.getResourceAsStream(
    106         SHORT_NUMBER_METADATA_FILE_PREFIX + "_" + regionCode);
    107     ObjectInputStream in = null;
    108     try {
    109       in = new ObjectInputStream(source);
    110       PhoneMetadataCollection shortNumberMetadata = new PhoneMetadataCollection();
    111       shortNumberMetadata.readExternal(in);
    112       for (PhoneMetadata metadata : shortNumberMetadata.getMetadataList()) {
    113         regionCodeToShortNumberMetadataMap.put(regionCode, metadata);
    114       }
    115     } catch (IOException e) {
    116       LOGGER.log(Level.WARNING, e.toString());
    117     } finally {
    118       close(in);
    119     }
    120   }
    121 
    122   // @VisibleForTesting
    123   static Set<String> getShortNumberMetadataSupportedRegions() {
    124     return regionCodeSet;
    125   }
    126 
    127   static PhoneMetadata getShortNumberMetadataForRegion(String regionCode) {
    128     if (!regionCodeSet.contains(regionCode)) {
    129       return null;
    130     }
    131     synchronized (regionCodeToShortNumberMetadataMap) {
    132       if (!regionCodeToShortNumberMetadataMap.containsKey(regionCode)) {
    133         loadShortNumberMetadataFromFile(regionCode);
    134       }
    135     }
    136     return regionCodeToShortNumberMetadataMap.get(regionCode);
    137   }
    138 }
    139