Home | History | Annotate | Download | only in tool
      1 package org.unicode.cldr.tool;
      2 
      3 import java.util.Arrays;
      4 import java.util.Collections;
      5 import java.util.Date;
      6 import java.util.HashMap;
      7 import java.util.List;
      8 import java.util.Map;
      9 import java.util.Set;
     10 import java.util.TreeSet;
     11 
     12 import org.unicode.cldr.util.Builder;
     13 import org.unicode.cldr.util.LanguageTagParser;
     14 import org.unicode.cldr.util.SupplementalDataInfo;
     15 import org.unicode.cldr.util.SupplementalDataInfo.BasicLanguageData;
     16 import org.unicode.cldr.util.SupplementalDataInfo.BasicLanguageData.Type;
     17 import org.unicode.cldr.util.SupplementalDataInfo.CurrencyDateInfo;
     18 import org.unicode.cldr.util.SupplementalDataInfo.PopulationData;
     19 
     20 import com.ibm.icu.impl.Row;
     21 import com.ibm.icu.impl.Row.R2;
     22 
     23 public class LikelySubtags {
     24     static final boolean DEBUG = true;
     25     static final String TAG_SEPARATOR = "_";
     26 
     27     private Map<String, String> toMaximized;
     28     private boolean favorRegion = false;
     29     private SupplementalDataInfo supplementalDataInfo;
     30     private Map<String, String> currencyToLikelyTerritory = new HashMap<String, String>();
     31 
     32     /**
     33      * Create the likely subtags.
     34      *
     35      * @param toMaximized
     36      */
     37     public LikelySubtags(Map<String, String> toMaximized) {
     38         this(SupplementalDataInfo.getInstance(), toMaximized);
     39     }
     40 
     41     /**
     42      * Create the likely subtags.
     43      *
     44      * @param toMaximized
     45      */
     46     public LikelySubtags(SupplementalDataInfo supplementalDataInfo) {
     47         this(supplementalDataInfo, supplementalDataInfo.getLikelySubtags());
     48     }
     49 
     50     /**
     51      * Create the likely subtags.
     52      *
     53      * @param toMaximized
     54      */
     55     public LikelySubtags(SupplementalDataInfo supplementalDataInfo, Map<String, String> toMaximized) {
     56         this.supplementalDataInfo = supplementalDataInfo;
     57         this.toMaximized = toMaximized;
     58 
     59         Date now = new Date();
     60         Set<Row.R2<Double, String>> sorted = new TreeSet<Row.R2<Double, String>>();
     61         for (String territory : supplementalDataInfo.getTerritoriesWithPopulationData()) {
     62             PopulationData pop = supplementalDataInfo.getPopulationDataForTerritory(territory);
     63             double population = pop.getPopulation();
     64             sorted.add(Row.of(-population, territory));
     65         }
     66         for (R2<Double, String> item : sorted) {
     67             String territory = item.get1();
     68             Set<CurrencyDateInfo> targetCurrencyInfo = supplementalDataInfo.getCurrencyDateInfo(territory);
     69             if (targetCurrencyInfo == null) {
     70                 continue;
     71             }
     72             for (CurrencyDateInfo cdi : targetCurrencyInfo) {
     73                 String currency = cdi.getCurrency();
     74                 if (!currencyToLikelyTerritory.containsKey(currency) && cdi.getStart().before(now)
     75                     && cdi.getEnd().after(now) && cdi.isLegalTender()) {
     76                     currencyToLikelyTerritory.put(currency, territory);
     77                 }
     78             }
     79         }
     80         // System.out.println("Currency to Territory:\n\t" +
     81         // CollectionUtilities.join(currencyToLikelyTerritory.entrySet(), "\n\t"));
     82     }
     83 
     84     /**
     85      * Create the likely subtags.
     86      *
     87      * @param toMaximized
     88      */
     89     public LikelySubtags() {
     90         this(SupplementalDataInfo.getInstance());
     91     }
     92 
     93     public boolean isFavorRegion() {
     94         return favorRegion;
     95     }
     96 
     97     public LikelySubtags setFavorRegion(boolean favorRegion) {
     98         this.favorRegion = favorRegion;
     99         return this;
    100     }
    101 
    102     public Map<String, String> getToMaximized() {
    103         return toMaximized;
    104     }
    105 
    106     public LikelySubtags setToMaximized(Map<String, String> toMaximized) {
    107         this.toMaximized = toMaximized;
    108         return this;
    109     }
    110 
    111     public static String maximize(String languageTag, Map<String, String> toMaximized) {
    112         return new LikelySubtags(toMaximized).maximize(languageTag);
    113     }
    114 
    115     public static String minimize(String input, Map<String, String> toMaximized, boolean favorRegion) {
    116         return new LikelySubtags(toMaximized).setFavorRegion(favorRegion).minimize(input);
    117     }
    118 
    119     // TODO Old, crufty code, needs reworking.
    120     public synchronized String maximize(String languageTag) {
    121         if (languageTag == null) {
    122             return null;
    123         }
    124         LanguageTagParser ltp = new LanguageTagParser();
    125         if (DEBUG && languageTag.equals("es" + TAG_SEPARATOR + "Hans" + TAG_SEPARATOR + "CN")) {
    126             System.out.print(""); // debug
    127         }
    128         // clean up the input by removing Zzzz, ZZ, and changing "" into und.
    129         ltp.set(languageTag);
    130         String language = ltp.getLanguage();
    131         String region = ltp.getRegion();
    132         String script = ltp.getScript();
    133         List<String> variants = ltp.getVariants();
    134         Map<String, String> extensions = ltp.getExtensions();
    135         Map<String, String> localeExtensions = ltp.getLocaleExtensions();
    136 
    137         if (language.equals("")) {
    138             ltp.setLanguage(language = "und");
    139         }
    140         if (script.equals("Zzzz")) {
    141             ltp.setScript(script = "");
    142         }
    143         if (region.equals("ZZ")) {
    144             ltp.setRegion(region = "");
    145         }
    146         if (variants.size() != 0) {
    147             ltp.setVariants(Collections.<String> emptySet());
    148         }
    149         if (extensions.size() != 0) {
    150             ltp.setExtensions(Collections.<String, String> emptyMap());
    151         }
    152         if (localeExtensions.size() != 0) {
    153             ltp.setExtensions(Collections.<String, String> emptyMap());
    154         }
    155 
    156         // check whole
    157         String result = toMaximized.get(ltp.toString());
    158         if (result != null) {
    159             return ltp.set(result)
    160                 .setVariants(variants)
    161                 .setExtensions(extensions)
    162                 .setLocaleExtensions(localeExtensions)
    163                 .toString();
    164         }
    165 
    166         boolean noLanguage = language.equals("und");
    167         boolean noScript = script.isEmpty();
    168         boolean noRegion = region.isEmpty();
    169 
    170         // not efficient, but simple to match spec.
    171         for (String region2 : noRegion ? Arrays.asList(region) : Arrays.asList(region, "")) {
    172             ltp.setRegion(region2);
    173             for (String script2 : noScript ? Arrays.asList(script) : Arrays.asList(script, "")) {
    174                 ltp.setScript(script2);
    175 
    176                 result = toMaximized.get(ltp.toString());
    177                 if (result != null) {
    178                     ltp.set(result);
    179                     if (!noLanguage) {
    180                         ltp.setLanguage(language);
    181                     }
    182                     if (!noScript) {
    183                         ltp.setScript(script);
    184                     }
    185                     if (!noRegion) {
    186                         ltp.setRegion(region);
    187                     }
    188                     return ltp.setVariants(variants)
    189                         .setExtensions(extensions)
    190                         .setLocaleExtensions(localeExtensions)
    191                         .toString();
    192                 }
    193             }
    194         }
    195 
    196         // now check und_script
    197         if (!noScript) {
    198             ltp.setLanguage("und");
    199             ltp.setScript(script);
    200             result = toMaximized.get(ltp.toString());
    201             if (result != null) {
    202                 ltp.set(result);
    203                 if (!noLanguage) {
    204                     ltp.setLanguage(language);
    205                 }
    206                 if (!noScript) {
    207                     ltp.setScript(script);
    208                 }
    209                 if (!noRegion) {
    210                     ltp.setRegion(region);
    211                 }
    212                 return ltp.setVariants(variants)
    213                     .setExtensions(extensions)
    214                     .setLocaleExtensions(localeExtensions)
    215                     .toString();
    216             }
    217         }
    218 
    219         return null; // couldn't maximize
    220     }
    221 
    222     // TODO, optimize if needed by adding private routine that maximizes a LanguageTagParser instead of multiple parsings
    223     // TODO Old, crufty code, needs reworking.
    224     public synchronized String minimize(String input) {
    225         String maximized = maximize(input, toMaximized);
    226         if (maximized == null) {
    227             return null;
    228         }
    229         if (DEBUG && maximized.equals("sr" + TAG_SEPARATOR + "Latn" + TAG_SEPARATOR + "RS")) {
    230             System.out.print(""); // debug
    231         }
    232         LanguageTagParser ltp = new LanguageTagParser().set(maximized);
    233         String language = ltp.getLanguage();
    234         String region = ltp.getRegion();
    235         String script = ltp.getScript();
    236 
    237         // handle variants
    238         List<String> variants = ltp.getVariants();
    239         Map<String, String> extensions = ltp.getExtensions();
    240         Map<String, String> localeExtensions = ltp.getLocaleExtensions();
    241 
    242         String maximizedCheck = maximized;
    243         if (!variants.isEmpty() || !extensions.isEmpty() || !localeExtensions.isEmpty()) {
    244             maximizedCheck = ltp.toLSR();
    245         }
    246         // try building up from shorter to longer, and find the first that matches
    247         // could be more optimized, but for this code we want simplest
    248         String[] trials = { language,
    249             language + TAG_SEPARATOR + (favorRegion ? region : script),
    250             language + TAG_SEPARATOR + (!favorRegion ? region : script) };
    251         for (String trial : trials) {
    252             String newMaximized = maximize(trial, toMaximized);
    253             if (maximizedCheck.equals(newMaximized)) {
    254                 if (variants.isEmpty() && extensions.isEmpty() && localeExtensions.isEmpty()) {
    255                     return trial;
    256                 }
    257                 return ltp.set(trial)
    258                     .setVariants(variants)
    259                     .setExtensions(extensions)
    260                     .setLocaleExtensions(extensions)
    261                     .toString();
    262             }
    263         }
    264         return maximized;
    265     }
    266 
    267     static final Map<String, String> EXTRA_SCRIPTS = Builder.with(new HashMap<String, String>())
    268         .on("crs", "pcm", "tlh").put("Latn")
    269         .freeze();
    270 
    271     public String getLikelyScript(String code) {
    272         String max = this.maximize(code);
    273 
    274         String script = null;
    275         if (max != null) {
    276             script = new LanguageTagParser().set(max).getScript();
    277         } else {
    278             Map<Type, BasicLanguageData> data = supplementalDataInfo.getBasicLanguageDataMap(code);
    279             if (data != null) {
    280                 for (BasicLanguageData item : data.values()) {
    281                     Set<String> scripts = item.getScripts();
    282                     if (scripts == null || scripts.size() == 0) continue;
    283                     script = scripts.iterator().next();
    284                     Type type = item.getType();
    285                     if (type == Type.primary) {
    286                         break;
    287                     }
    288                 }
    289             }
    290             if (script == null) {
    291                 script = EXTRA_SCRIPTS.get(code);
    292                 if (script == null) {
    293                     script = "Zzzz";
    294                 }
    295             }
    296         }
    297         return script;
    298     }
    299 
    300     public String getLikelyTerritoryFromCurrency(String code) {
    301         return currencyToLikelyTerritory.get(code);
    302     }
    303 }
    304