/* * (C) 2004 - Geotechnical Software Services * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ package no.geosoft.cc.country; import java.util.*; import java.io.*; /** * A country management singelton module. Useful for presentation of * sorted list of countries in GUI like in country combo boxes etc. * <p> * The country manager instantiate country objects for the countries * listed in the <tt>countries.txt</tt> resource of this package. The file * lists ISO codes and the official english names for countries of the world. * The countries.txt file has the following layout: * * <pre> * AF; AFGHANISTAN * AL; ALBANIA * DZ; ALGERIA * AS; AMERICAN SAMOA * AD; ANDORRA * AO; ANGOLA * : * </pre> * * The country name is the defualt name used if a localized mapping is * not found, or the client askes for countries independent of locale. * <p> * TODO: Connect to an online resource to pick country ISO codes. * <p> * For internal application usage, only ISO codes for countries should * be used (i.e. for persistent storage store the ISO code rather than * a country name). * <p> * In user interfaces, localized names should be used according * to the locale of the application or preferred locale selected by the * user. Localized names are maintained in resource bundles picked from * property files with name <tt>Messages_xx_XX.properties</tt> where * <tt>xx</tt> is the language specifier and <tt>XX</tt> is the country * specifier. Provide localized country name mappings for all locales * supported by the client application. The properties files should be * located in the same package as the CountryManager. The properties * files has the following format (Messages_en_US.properties): * * <pre> * AF = Afghanistan * AL = Albania * DZ = Algeria * AS = American Samoa * AD = Andorra * AO = Angola * : * </pre> * * <p> * Typical usage: * <pre> * // Get a specific country * Country country = CountryManager.getInstance().getCountry ("AF", french); * * // Get world countries localized to french (assuming * // Messages_fr_FR.properties is available). * Locale french = new Locale ("fr", "FR"); * Collection countries = CountryManager.getInstance.getCountries (french); * * // Put countries (sorted according to locale) in a combo box * TreeSet sorted = new TreeSet (countries); * JComboBox countriesCombo = new JComboBox (new Vector (sorted)); * </pre> * * @see <a href="http://www.iso.org">ISO standard</a> * * @author <a href="mailto:info@geosoft.no">GeoSoft</a> */ public class CountryManager { private static CountryManager instance_ = new CountryManager(); private HashMap countries_; /** * Create country manager. * Private to prevent instantiation. */ private CountryManager() { countries_ = null; } /** * Retur sole instance of this class. * * @return CountryManager singleton instance. */ public static CountryManager getInstance() { return instance_; } /** * Return countries of the world (as specified in countries.txt) using * the default (official ISO name) country names. * * @return Countries of the world. */ public Collection getCountries() { if (countries_ == null) loadCountries(); return countries_.values(); } /** * Return countries of the world (as specified in countries.txt) with * names according to the specified locale. The name mappings must be * available in a Messages_xx_XX.properties file where xx and XX match * the language and country of the specified locale respectively. * <p> * If the associated properties file is not found, the country names * are set according to the default ISO standard. * * @param locale Locale to setting country names. * @return Countries of the world. */ public Collection getCountries (Locale locale) { if (countries_ == null) loadCountries(); String bundleName = getClass().getPackage().getName() + ".Messages"; ResourceBundle resourceBundle = ResourceBundle.getBundle (bundleName, locale); Collection countries = countries_.values(); Collection sorted = new TreeSet(); for (Iterator i = countries.iterator(); i.hasNext(); ) { Country country = (Country) i.next(); Country clone = new Country (country); try { String localizedName = resourceBundle.getString (country.getIsoCode()); clone.setName (localizedName); } catch (Exception exception) { } sorted.add (clone); } return sorted; } /** * Get country for specified ISO code. * * @param isoCode ISO code of country to find. * @return Requested country (with default ISO name) (or null if * ISO code is unknown). */ public Country getCountry (String isoCode) { if (countries_ == null) loadCountries(); return (Country) countries_.get (isoCode); } /** * Get country for specified ISO code. * * @param isoCode ISO code of country to find. * @param locale Locale to control name of requested country. * @return Requested country (or null if ISO code is unknown). */ public Country getCountry (String isoCode, Locale locale) { if (countries_ == null) loadCountries(); Country country = (Country) countries_.get (isoCode); Country clone = null; if (country != null) { clone = new Country (country); String bundleName = getClass().getPackage().getName() + ".Messages"; ResourceBundle resourceBundle = ResourceBundle.getBundle (bundleName, locale); try { String localizedName = resourceBundle.getString (country.getIsoCode()); clone.setName (localizedName); } catch (Exception exception) { } } return clone; } /** * Load all countries from countries.txt file. */ private void loadCountries() { countries_ = new HashMap(); String fileName = "countries.txt"; String packageName = getClass().getPackage().getName(); String packageLocation = packageName.replace ('.', '/'); String filePath = "/" + packageLocation + "/" + fileName; InputStream stream = getClass().getResourceAsStream (filePath); BufferedReader reader = new BufferedReader (new InputStreamReader (stream)); try { String line = reader.readLine(); while (line != null) { StringTokenizer tokenizer = new StringTokenizer (line, ";"); String isoCode = tokenizer.nextToken().trim(); String name = tokenizer.nextToken().trim(); Country country = new Country (isoCode); country.setName (name); countries_.put (isoCode, country); line = reader.readLine(); } } catch (IOException exception) { } finally { try {stream.close();} catch (Exception e) {} } } /** * Testing the class. * * @param args Not used. */ public static void main (String[] args) { Locale locale = new Locale ("no", "NO"); CountryManager countryManager = CountryManager.getInstance(); Collection countries = countryManager.getCountries (locale); for (Iterator i = countries.iterator(); i.hasNext(); ) { Country country = (Country) i.next(); System.out.println (country); } } }