package com.cloudhopper.commons.locale;
/*
* #%L
* ch-commons-locale
* %%
* Copyright (C) 2012 - 2013 Cloudhopper by Twitter
* %%
* 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.
* #L%
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for statically loading E.164 and performing lookups.
* @author Joe Lauer
*/
public class E164CountryCodeUtil {
private static final Logger logger = LoggerFactory.getLogger(E164CountryCodeUtil.class);
// all country codes hashed by prefix
private static HashMap<String,E164CountryCode> byPrefix;
// dynamic max prefix length in our list of prefixes -- specifically for
// speeding up lookups within the hash
private static int maxPrefixLength;
static {
// load the resource file
InputStream is = E164CountryCodeUtil.class.getResourceAsStream("e164CountryCode.txt");
if (is == null) {
throw new RuntimeException("Not able to locate e164CountryCode.txt file");
}
try {
byPrefix = parse(is);
} catch (Exception e) {
throw new RuntimeException("Error while loading or parsing e164CountryCode.txt resource", e);
} finally {
try { is.close(); } catch (Exception e) {}
}
// determine the max prefix length
maxPrefixLength = 1;
for (E164CountryCode code : byPrefix.values()) {
if (code.getPrefix().length() > maxPrefixLength) {
// update the max prefix length
maxPrefixLength = code.getPrefix().length();
}
}
}
private E164CountryCodeUtil() {
// only static
}
/**
* Looks up an E164CountryCode object by analyzing the address and returning
* the best match. For example, 12125551212 will return an entry for the US.
* @param address The address to lookup.
* @return
*/
public static E164CountryCode lookup(String address) {
// analyze just the first few chars -- max of 4 or length of address
int len = (address.length() > maxPrefixLength ? maxPrefixLength : address.length());
// search backwards first, return the first result
for (int i = len; i > 0; i--) {
String prefix = address.substring(0, i);
E164CountryCode entry = byPrefix.get(prefix);
if (entry != null) {
return entry;
}
}
// nothing found
return null;
}
public static HashMap<String,E164CountryCode> parse(InputStream is) throws IOException {
// convert into a buffered reader
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line = null; //not declared within while loop
HashMap<String,E164CountryCode> codes = new HashMap<String,E164CountryCode>();
/*
* readLine is a bit quirky :
* it returns the content of a line MINUS the newline.
* it returns null only for the END of the stream.
* it returns an empty String if two newlines appear in a row.
*/
while ((line = in.readLine()) != null) {
if (!line.equals("") && !line.startsWith("#")) {
E164CountryCode code = E164CountryCode.parse(line);
codes.put(code.getPrefix(), code);
}
}
return codes;
}
}