/* * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. * * 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 org.javamoney.currencies.internal.data; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.annotation.PostConstruct; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * Mapping provider that is able to map ISO textual and ISO nuemeric codes and * vice versa. * * @author Anatole Tresch */ public final class IsoCountryMappingProvider { private static final Logger LOGGER = LoggerFactory .getLogger(IsoCountryMappingProvider.class); private static final IsoCountryMappingProvider INSTANCE = new IsoCountryMappingProvider(); private SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); private Map<String, String> nameToCodeMap = new HashMap<String, String>(); private Map<String, String> codeToNameMap = new HashMap<String, String>(); private IsoCountryMappingProvider() { saxParserFactory.setNamespaceAware(false); saxParserFactory.setValidating(false); new Thread() { public void run() { loadCountries(); }; }.start(); } public static IsoCountryMappingProvider getInstance() { return INSTANCE; } @PostConstruct public void loadCountries() { Map<String, String> newNameToCodeMap = new HashMap<String, String>(); Map<String, String> newCodeToNameMap = new HashMap<String, String>(); try { URL url = new URL( "http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_xml.htm"); SAXParser parser = saxParserFactory.newSAXParser(); parser.parse(url.openStream(), new CountryHandler(newNameToCodeMap, newCodeToNameMap)); nameToCodeMap = newNameToCodeMap; codeToNameMap = newCodeToNameMap; } catch (Exception e) { LOGGER.error("Error", e); } } public Set<String> getIsoAlpha2Codes() { return this.codeToNameMap.keySet(); } public Set<String> getIsoNames() { return this.nameToCodeMap.keySet(); } public String getNameFromCode(String code) { return this.codeToNameMap.get(code); } public String getCodeFromName(String name) { return this.nameToCodeMap.get(name); } private class CountryHandler extends DefaultHandler { // <ISO_3166-1_List_en xml:lang="en"> // <ISO_3166-1_Entry> // <ISO_3166-1_Country_name>AFGHANISTAN</ISO_3166-1_Country_name> // <ISO_3166-1_Alpha-2_Code_element>AF</ISO_3166-1_Alpha-2_Code_element> // </ISO_3166-1_Entry> // ... // </ISO_3166-1_List_en xml:lang="en"> private String name; private String alpha2Code; private StringBuilder text = new StringBuilder(); private Map<String, String> nameToCodeMap; private Map<String, String> codeToNameMap; public CountryHandler(Map<String, String> nameToCodeMap, Map<String, String> codeToNameMap) { this.nameToCodeMap = nameToCodeMap; this.codeToNameMap = codeToNameMap; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("ISO_3166-1_Entry".equals(qName)) { name = null; alpha2Code = null; } else if ("ISO_3166-1_Country_name".equals(qName)) { text.setLength(0); } else if ("ISO_3166-1_Alpha-2_Code_element".equals(qName)) { text.setLength(0); } super.startElement(uri, localName, qName, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { text.append(ch, start, length); super.characters(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("ISO_3166-1_Entry".equals(qName)) { nameToCodeMap.put(name, alpha2Code); codeToNameMap.put(alpha2Code, name); } else if ("ISO_3166-1_Country_name".equals(qName)) { name = text.toString(); } else if ("ISO_3166-1_Alpha-2_Code_element".equals(qName)) { alpha2Code = text.toString(); } super.endElement(uri, localName, qName); } } }