xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/tool/CountryCodeConverter.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
1 package org.unicode.cldr.tool;
2 
3 import com.ibm.icu.text.UTF16;
4 import com.ibm.icu.util.ICUUncheckedIOException;
5 import com.ibm.icu.util.ULocale;
6 import java.io.IOException;
7 import java.util.Collections;
8 import java.util.LinkedHashSet;
9 import java.util.Locale;
10 import java.util.Map;
11 import java.util.Set;
12 import java.util.TreeMap;
13 import org.unicode.cldr.util.CldrUtility;
14 import org.unicode.cldr.util.CldrUtility.LineHandler;
15 import org.unicode.cldr.util.StandardCodes;
16 
17 public class CountryCodeConverter {
18 
19     private static final boolean SHOW_SKIP = CldrUtility.getProperty("SHOW_SKIP", false);
20 
21     private static Map<String, String> nameToCountryCode =
22             new TreeMap<>(new UTF16.StringComparator(true, true, 0));
23     private static Set<String> parseErrors = new LinkedHashSet<>();
24 
getCodeFromName(String display, boolean showMissing)25     public static String getCodeFromName(String display, boolean showMissing) {
26         return getCodeFromName(display, showMissing, null);
27     }
28 
29     /**
30      * @param display
31      * @param showMissing
32      * @param missing will contain a list of missing names (if showMissing is true)
33      * @return
34      */
getCodeFromName(String display, boolean showMissing, Set<String> missing)35     public static String getCodeFromName(String display, boolean showMissing, Set<String> missing) {
36         String trial = display.trim().toLowerCase(Locale.ENGLISH);
37         if (trial.startsWith("\"") && trial.endsWith("\"")) {
38             trial = trial.substring(1, trial.length() - 2);
39         }
40         if (trial.startsWith("the ")) {
41             trial = trial.substring(4);
42         }
43         String result = nameToCountryCode.get(trial);
44         if ("skip".equals(result)) {
45             return null;
46         }
47         if (result == null) {
48             trial = reverseComma(display);
49             if (trial != null) {
50                 result = nameToCountryCode.get(trial);
51                 // if (result != null) {
52                 // addName(trial, result);
53                 // }
54             }
55         }
56         if (result == null && (showMissing || SHOW_SKIP)) {
57             System.err.println(
58                     "ERROR: CountryCodeConverter missing code for "
59                             + display
60                             + ".\n"
61                             + "To fix: add to external/alternate_country_names.txt a line such as:\n"
62                             + "\t<code>;\t<name>;\t"
63                             + display);
64             if (missing != null) {
65                 missing.add(display);
66             }
67         }
68         return result;
69     }
70 
names()71     public static Set<String> names() {
72         return nameToCountryCode.keySet();
73     }
74 
reverseComma(String display)75     private static String reverseComma(String display) {
76         String trial;
77         trial = null;
78         int comma = display.indexOf(',');
79         if (comma >= 0) {
80             trial = display.substring(comma + 1).trim() + " " + display.substring(0, comma).trim();
81         }
82         return trial;
83     }
84 
85     static {
86         try {
loadNames()87             loadNames();
88         } catch (IOException e) {
89             throw new ICUUncheckedIOException(e);
90         }
91     }
92 
loadNames()93     static void loadNames() throws IOException {
94         for (String country : ULocale.getISOCountries()) {
95             addName(ULocale.getDisplayCountry("und-" + country, "en"), country);
96         }
97         StandardCodes sc = StandardCodes.make();
98         Set<String> goodAvailableCodes = sc.getGoodAvailableCodes("territory");
99 
100         for (String country : goodAvailableCodes) {
101             String description = sc.getFullData("territory", country).get(0);
102             if (country.equals("057")) continue;
103             addName(description, country);
104         }
105         CldrUtility.handleFile(
106                 "external/alternate_country_names.txt", new MyHandler(goodAvailableCodes));
107         nameToCountryCode = CldrUtility.protectCollection(nameToCountryCode);
108         parseErrors = Collections.unmodifiableSet(parseErrors);
109     }
110 
111     static class MyHandler implements LineHandler {
112         private Set<String> goodAvailableCodes;
113 
MyHandler(Set<String> goodAvailableCodes)114         public MyHandler(Set<String> goodAvailableCodes) {
115             this.goodAvailableCodes = goodAvailableCodes;
116         }
117 
118         @Override
handle(String line)119         public boolean handle(String line) {
120             if (line.trim().length() == 0 || line.trim().startsWith("#")) {
121                 return true; // don't show skips, ignore comment lines
122             }
123             String[] pieces = line.split(";");
124             String country = pieces[0].trim();
125             if (!goodAvailableCodes.contains(country)) {
126                 // TODO- ?
127             }
128             // Note: field 1 is ignored.
129 
130             addName(pieces[2].trim(), country);
131             return true;
132         }
133     }
134 
addName(String key, String code)135     static void addName(String key, String code) {
136         addName2(key, code);
137         String trial = reverseComma(key);
138         if (trial != null) {
139             addName2(trial, code);
140         }
141     }
142 
addName2(String key, String code)143     private static void addName2(String key, String code) {
144         key = key.toLowerCase(Locale.ENGLISH);
145         if (key.startsWith("the ")) {
146             key = key.substring(4);
147         }
148         String old = nameToCountryCode.get(key);
149         if (old != null && !code.equals(old)) {
150             System.err.println("Conflict!!" + key + "\t" + old + "\t" + code);
151             return;
152         }
153         nameToCountryCode.put(key, code);
154     }
155 
getParseErrors()156     public static Set<String> getParseErrors() {
157         return parseErrors;
158     }
159 }
160