17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 3f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Copyright (C) 2011-2015, International Business Machines Corporation * 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * All Rights Reserved. * 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.util; 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.ArrayList; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collections; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.List; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TreeSet; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>Region</code> is the class representing a Unicode Region Code, also known as a 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Unicode Region Subtag, which is defined based upon the BCP 47 standard. We often think of 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "regions" as "countries" when defining the characteristics of a locale. Region codes There are different 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * types of region codes that are important to distinguish. 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Macroregion - A code for a "macro geographical (continental) region, geographical sub-region, or 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * selected economic and other grouping" as defined in 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * UN M.49 (http://unstats.un.org/unsd/methods/m49/m49regin.htm). 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * These are typically 3-digit codes, but contain some 2-letter codes, such as the LDML code QO 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * added for Outlying Oceania. Not all UNM.49 codes are defined in LDML, but most of them are. 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Macroregions are represented in ICU by one of three region types: WORLD ( region code 001 ), 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * CONTINENTS ( regions contained directly by WORLD ), and SUBCONTINENTS ( things contained directly 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * by a continent ). 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TERRITORY - A Region that is not a Macroregion. These are typically codes for countries, but also 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * include areas that are not separate countries, such as the code "AQ" for Antarctica or the code 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "HK" for Hong Kong (SAR China). Overseas dependencies of countries may or may not have separate 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * codes. The codes are typically 2-letter codes aligned with the ISO 3166 standard, but BCP47 allows 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the use of 3-digit codes in the future. 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * UNKNOWN - The code ZZ is defined by Unicode LDML for use to indicate that the Region is unknown, 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or that the value supplied as a region was invalid. 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DEPRECATED - Region codes that have been defined in the past but are no longer in modern usage, 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * usually due to a country splitting into multiple territories or changing its name. 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * GROUPING - A widely understood grouping of territories that has a well defined membership such 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that a region code has been assigned for it. Some of these are UNM.49 codes that do't fall into 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the world/continent/sub-continent hierarchy, while others are just well known groupings that have 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * their own region code. Region "EU" (European Union) is one such region code that is a grouping. 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Groupings will never be returned by the getContainingRegion() API, since a different type of region 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ( WORLD, CONTINENT, or SUBCONTINENT ) will always be the containing region instead. 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author John Emmons 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class Region implements Comparable<Region> { 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * RegionType is an enumeration defining the different types of regions. Current possible 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * values are WORLD, CONTINENT, SUBCONTINENT, TERRITORY, GROUPING, DEPRECATED, and UNKNOWN. 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public enum RegionType { 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing the unknown region. 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UNKNOWN, 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing a territory. 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert TERRITORY, 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing the whole world. 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert WORLD, 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing a continent. 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CONTINENT, 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing a sub-continent. 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert SUBCONTINENT, 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing a grouping of territories that is not to be used in 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the normal WORLD/CONTINENT/SUBCONTINENT/TERRITORY containment tree. 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert GROUPING, 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Type representing a region whose code has been deprecated, usually 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * due to a country splitting into multiple territories or changing its name. 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DEPRECATED, 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String id; 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int code; 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private RegionType type; 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Region containingRegion = null; 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Set<Region> containedRegions = new TreeSet<Region>(); 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private List<Region> preferredValues = null; 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean regionDataIsLoaded = false; 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static Map<String,Region> regionIDMap = null; // Map from ID the regions 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static Map<Integer,Region> numericCodeMap = null; // Map from numeric code to the regions 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static Map<String,Region> regionAliases = null; // Aliases 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ArrayList<Region> regions = null; // This is the main data structure where the Regions are stored. 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ArrayList<Set<Region>> availableRegions = null; 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String UNKNOWN_REGION_ID = "ZZ"; 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String OUTLYING_OCEANIA_REGION_ID = "QO"; 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final String WORLD_ID = "001"; 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Private default constructor. Use factory methods only. 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Region () {} 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initializes the region data from the ICU resource bundles. The region data 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * contains the basic relationships such as which regions are known, what the numeric 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * codes are, any known aliases, and the territory containment data. 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the region data has already loaded, then this method simply returns without doing 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * anything meaningful. 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static synchronized void loadRegionData() { 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionDataIsLoaded ) { 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionAliases = new HashMap<String,Region>(); 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionIDMap = new HashMap<String,Region>(); 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericCodeMap = new HashMap<Integer,Region>(); 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert availableRegions = new ArrayList<Set<Region>>(RegionType.values().length); 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 156f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert UResourceBundle metadataAlias = null; 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle territoryAlias = null; 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle codeMappings = null; 159bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert UResourceBundle idValidity = null; 160bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert UResourceBundle regionList = null; 161bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert UResourceBundle regionRegular = null; 162bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert UResourceBundle regionMacro = null; 163bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert UResourceBundle regionUnknown = null; 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle worldContainment = null; 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle territoryContainment = null; 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle groupingContainment = null; 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 168f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert UResourceBundle metadata = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,"metadata",ICUResourceBundle.ICU_DATA_CLASS_LOADER); 169f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert metadataAlias = metadata.get("alias"); 170f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert territoryAlias = metadataAlias.get("territory"); 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 172f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert UResourceBundle supplementalData = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,"supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER); 173f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert codeMappings = supplementalData.get("codeMappings"); 174bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert idValidity = supplementalData.get("idValidity"); 175bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionList = idValidity.get("region"); 176bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionRegular = regionList.get("regular"); 177bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionMacro = regionList.get("macroregion"); 178bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionUnknown = regionList.get("unknown"); 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 180f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert territoryContainment = supplementalData.get("territoryContainment"); 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert worldContainment = territoryContainment.get("001"); 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingContainment = territoryContainment.get("grouping"); 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] continentsArr = worldContainment.getStringArray(); 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert List<String> continents = Arrays.asList(continentsArr); 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] groupingArr = groupingContainment.getStringArray(); 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert List<String> groupings = Arrays.asList(groupingArr); 188bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert List<String> regionCodes = new ArrayList<String>(); 189bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 190bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert List<String> allRegions = new ArrayList<String>(); 191bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert allRegions.addAll(Arrays.asList(regionRegular.getStringArray())); 192bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert allRegions.addAll(Arrays.asList(regionMacro.getStringArray())); 193bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert allRegions.add(regionUnknown.getString()); 194bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 195bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for ( String r : allRegions ) { 196bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert int rangeMarkerLocation = r.indexOf("~"); 197bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert if ( rangeMarkerLocation > 0 ) { 198bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert StringBuilder regionName = new StringBuilder(r); 199bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert char endRange = regionName.charAt(rangeMarkerLocation+1); 200bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionName.setLength(rangeMarkerLocation); 201bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert char lastChar = regionName.charAt(rangeMarkerLocation-1); 202bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert while ( lastChar <= endRange ) { 203bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert String newRegion = regionName.toString(); 204bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionCodes.add(newRegion); 205bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert lastChar++; 206bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionName.setCharAt(rangeMarkerLocation-1,lastChar); 207bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 208bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } else { 209bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regionCodes.add(r); 210bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 211bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert } 212bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert 213bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert regions = new ArrayList<Region>(regionCodes.size()); 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // First process the region codes and create the master array of regions. 216bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert for ( String id : regionCodes) { 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r = new Region(); 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.id = id; 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.TERRITORY; // Only temporary - figure out the real type later once the aliases are known. 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionIDMap.put(id, r); 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( id.matches("[0-9]{3}")) { 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.code = Integer.valueOf(id).intValue(); 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericCodeMap.put(r.code, r); 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.SUBCONTINENT; 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.code = -1; 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regions.add(r); 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Process the territory aliases 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0 ; i < territoryAlias.getSize(); i++ ) { 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle res = territoryAlias.get(i); 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String aliasFrom = res.getKey(); 236f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert String aliasTo = res.get("replacement").getString(); 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(aliasTo) && !regionIDMap.containsKey(aliasFrom) ) { // This is just an alias from some string to a region 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionAliases.put(aliasFrom, regionIDMap.get(aliasTo)); 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r; 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(aliasFrom) ) { // This is a deprecated region 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(aliasFrom); 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { // Deprecated region code not in the master codes list - so need to create a deprecated region for it. 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = new Region(); 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.id = aliasFrom; 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionIDMap.put(aliasFrom, r); 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( aliasFrom.matches("[0-9]{3}")) { 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.code = Integer.valueOf(aliasFrom).intValue(); 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericCodeMap.put(r.code, r); 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.code = -1; 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regions.add(r); 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.DEPRECATED; 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert List<String> aliasToRegionStrings = Arrays.asList(aliasTo.split(" ")); 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.preferredValues = new ArrayList<Region>(); 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( String s : aliasToRegionStrings ) { 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (regionIDMap.containsKey(s)) { 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.preferredValues.add(regionIDMap.get(s)); 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Process the code mappings - This will allow us to assign numeric codes to most of the territories. 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0 ; i < codeMappings.getSize(); i++ ) { 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle mapping = codeMappings.get(i); 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( mapping.getType() == UResourceBundle.ARRAY ) { 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String [] codeMappingStrings = mapping.getStringArray(); 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String codeMappingID = codeMappingStrings[0]; 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Integer codeMappingNumber = Integer.valueOf(codeMappingStrings[1]); 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String codeMapping3Letter = codeMappingStrings[2]; 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(codeMappingID)) { 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r = regionIDMap.get(codeMappingID); 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.code = codeMappingNumber.intValue(); 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numericCodeMap.put(r.code, r); 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionAliases.put(codeMapping3Letter, r); 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Now fill in the special cases for WORLD, UNKNOWN, CONTINENTS, and GROUPINGS 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r; 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(WORLD_ID)) { 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(WORLD_ID); 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.WORLD; 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(UNKNOWN_REGION_ID)) { 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(UNKNOWN_REGION_ID); 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.UNKNOWN; 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( String continent : continents ) { 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (regionIDMap.containsKey(continent)) { 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(continent); 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.CONTINENT; 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( String grouping : groupings ) { 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (regionIDMap.containsKey(grouping)) { 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(grouping); 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.GROUPING; 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Special case: The region code "QO" (Outlying Oceania) is a subcontinent code added by CLDR 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // even though it looks like a territory code. Need to handle it here. 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( regionIDMap.containsKey(OUTLYING_OCEANIA_REGION_ID)) { 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionIDMap.get(OUTLYING_OCEANIA_REGION_ID); 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r.type = RegionType.SUBCONTINENT; 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Load territory containment info from the supplemental data. 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int i = 0 ; i < territoryContainment.getSize(); i++ ) { 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UResourceBundle mapping = territoryContainment.get(i); 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String parent = mapping.getKey(); 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parent.equals("containedGroupings") || parent.equals("deprecated")) { 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; // handle new pseudo-parent types added in ICU data per cldrbug 7808; for now just skip. 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // #11232 is to do something useful with these. 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region parentRegion = regionIDMap.get(parent); 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( int j = 0 ; j < mapping.getSize(); j++ ) { 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String child = mapping.getString(j); 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region childRegion = regionIDMap.get(child); 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( parentRegion != null && childRegion != null ) { 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Add the child region to the set of regions contained by the parent 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parentRegion.containedRegions.add(childRegion); 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set the parent region to be the containing region of the child. 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Regions of type GROUPING can't be set as the parent, since another region 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent. 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( parentRegion.getType() != RegionType.GROUPING) { 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert childRegion.containingRegion = parentRegion; 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create the availableRegions lists 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0 ; i < RegionType.values().length ; i++) { 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert availableRegions.add(new TreeSet<Region>()); 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( Region ar : regions ) { 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<Region> currentSet = availableRegions.get(ar.type.ordinal()); 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currentSet.add(ar); 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert availableRegions.set(ar.type.ordinal(),currentSet); 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert regionDataIsLoaded = true; 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Returns a Region using the given region ID. The region ID can be either a 2-letter ISO code, 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3-letter ISO code, UNM.49 numeric code, or other valid Unicode Region Code as defined by the CLDR. 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param id The id of the region to be retrieved. 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The corresponding region. 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws NullPointerException if the supplied id is null. 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the supplied ID cannot be canonicalized to a Region ID that is known by ICU. 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static Region getInstance(String id) { 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( id == null ) { 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new NullPointerException(); 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r = regionIDMap.get(id); 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r == null ) { 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionAliases.get(id); 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r == null ) { 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Unknown region id: " + id); 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r.type == RegionType.DEPRECATED && r.preferredValues.size() == 1) { 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = r.preferredValues.get(0); 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return r; 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Returns a Region using the given numeric code as defined by UNM.49 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param code The numeric code of the region to be retrieved. 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The corresponding region. 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the supplied numeric code is not recognized. 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static Region getInstance(int code) { 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Region r = numericCodeMap.get(code); 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r == null ) { // Just in case there's an alias that's numeric, try to find it. 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pad = ""; 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( code < 10 ) { 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pad = "00"; 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ( code < 100 ) { 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pad = "0"; 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String id = pad + Integer.toString(code); 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = regionAliases.get(id); 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r == null ) { 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Unknown region code: " + code); 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r.type == RegionType.DEPRECATED && r.preferredValues.size() == 1) { 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert r = r.preferredValues.get(0); 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return r; 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Used to retrieve all available regions of a specific type. 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type The type of regions to be returned ( TERRITORY, MACROREGION, etc. ) 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return An unmodifiable set of all known regions that match the given type. 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static Set<Region> getAvailable(RegionType type) { 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Collections.unmodifiableSet(availableRegions.get(type.ordinal())); 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Used to determine the macroregion that geographically contains this region. 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The region that geographically contains this region. Returns NULL if this region is 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * code "001" (World) or "ZZ" (Unknown region). For example, calling this method with region "IT" (Italy) 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * returns the region "039" (Southern Europe). 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Region getContainingRegion() { 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return containingRegion; 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Used to determine the macroregion that geographically contains this region and that matches the given type. 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The region that geographically contains this region and matches the given type. May return NULL if 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * no containing region can be found that matches the given type. For example, calling this method with region "IT" (Italy) 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and type CONTINENT returns the region "150" (Europe). 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Region getContainingRegion(RegionType type) { 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( containingRegion == null ) { 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( containingRegion.type.equals(type)) { 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return containingRegion; 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return containingRegion.getContainingRegion(type); 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Used to determine the sub-regions that are contained within this region. 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return An unmodifiable set containing all the regions that are immediate children 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of this region in the region hierarchy. These returned regions could be either macro 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * regions, territories, or a mixture of the two, depending on the containment data as defined 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in CLDR. This API may return an empty set if this region doesn't have any sub-regions. 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, calling this method with region "150" (Europe) returns a set containing 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the various sub regions of Europe - "039" (Southern Europe) - "151" (Eastern Europe) 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * - "154" (Northern Europe) and "155" (Western Europe). 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Set<Region> getContainedRegions() { 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Collections.unmodifiableSet(containedRegions); 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Used to determine all the regions that are contained within this region and that match the given type 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return An unmodifiable set containing all the regions that are children of this region 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * anywhere in the region hierarchy and match the given type. This API may return an empty set 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if this region doesn't have any sub-regions that match the given type. 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, calling this method with region "150" (Europe) and type "TERRITORY" returns a set 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * containing all the territories in Europe ( "FR" (France) - "IT" (Italy) - "DE" (Germany) etc. ) 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Set<Region> getContainedRegions(RegionType type) { 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<Region> result = new TreeSet<Region>(); 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<Region> cr = getContainedRegions(); 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( Region r : cr ) { 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( r.getType() == type ) { 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.add(r); 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.addAll(r.getContainedRegions(type)); 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Collections.unmodifiableSet(result); 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return For deprecated regions, return an unmodifiable list of the regions that are the preferred replacement regions for this region. 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns null for a non-deprecated region. For example, calling this method with region "SU" (Soviet Union) would 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return a list of the regions containing "RU" (Russia), "AM" (Armenia), "AZ" (Azerbaijan), etc... 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public List<Region> getPreferredValues() { 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( type == RegionType.DEPRECATED) { 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return Collections.unmodifiableList(preferredValues); 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Returns true if this region contains the supplied other region anywhere in the region hierarchy. 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean contains(Region other) { 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert loadRegionData(); 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (containedRegions.contains(other)) { 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (Region cr : containedRegions) { 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (cr.contains(other)) { 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Returns the string representation of this region 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The string representation of this region, which is its ID. 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toString() { 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return id; 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the numeric code for this region 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The numeric code for this region. Returns a negative value if the given region does not have a numeric 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * code assigned to it. This is a very rare case and only occurs for a few very small territories. 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getNumericCode() { 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return code; 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** Returns this region's type. 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return This region's type classification, such as MACROREGION or TERRITORY. 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public RegionType getType() { 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return type; 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int compareTo(Region other) { 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return id.compareTo(other.id); 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 607