Home | History | Annotate | Download | only in util
      1 package org.unicode.cldr.util;
      2 
      3 import java.io.BufferedReader;
      4 import java.io.IOException;
      5 import java.util.Collections;
      6 import java.util.HashMap;
      7 import java.util.HashSet;
      8 import java.util.List;
      9 import java.util.Locale;
     10 import java.util.Map;
     11 import java.util.Set;
     12 import java.util.TreeSet;
     13 
     14 import com.ibm.icu.util.ICUUncheckedIOException;
     15 
     16 /**
     17  * List of locale IDs which are somehow 'special'. Parses SpecialLocales.txt
     18  *
     19  * @author srl
     20  *
     21  */
     22 public class SpecialLocales {
     23     private static final String INCLUDE_SUBLOCALES = "*";
     24 
     25     public enum Type {
     26         /**
     27          * Locale may not be modified by user.
     28          */
     29         readonly,
     30         /**
     31          * Locale may be modified by user. Contents aren't part of CLDR release and may change.
     32          */
     33         scratch
     34     };
     35 
     36     /**
     37      * Get the type of this locale
     38      *
     39      * @param l
     40      * @return a Type or null
     41      */
     42     public static Type getType(CLDRLocale l) {
     43         return getInstance().getTypeInternal(l);
     44     }
     45 
     46     /**
     47      * Get all CLDRLocales matching this type. Does not include wildcard (*) sublocales.
     48      *
     49      * @param t
     50      * @return a set, or null if none found
     51      */
     52     public static Set<CLDRLocale> getByType(Type t) {
     53         return getInstance().getByTypeInternal(t);
     54     }
     55 
     56     /**
     57      * Get the comment on this locale. Strip out @ text.
     58      *
     59      * @param l
     60      * @return string or null
     61      */
     62     public static String getComment(CLDRLocale l) {
     63         return getCommentRaw(l).replaceAll("@", "");
     64     }
     65 
     66     /**
     67      * Get the comment on this locale. Include "@locale" markers.
     68      *
     69      * @param l
     70      * @return string or null
     71      */
     72     public static String getCommentRaw(CLDRLocale l) {
     73         return getInstance().getCommentInternal(l).replaceAll("@@", "@" + l.getBaseName());
     74     }
     75 
     76     /**
     77      * Singleton object
     78      */
     79     private static SpecialLocales singleton = null;
     80 
     81     /**
     82      * Internal accessor. All access is via the static functions.
     83      * @return
     84      */
     85     private static synchronized SpecialLocales getInstance() {
     86         if (singleton == null) {
     87             singleton = new SpecialLocales();
     88         }
     89         return singleton;
     90     }
     91 
     92     private Map<CLDRLocale, Type> specials = new HashMap<CLDRLocale, Type>();
     93     private Map<Type, Set<CLDRLocale>> types = new HashMap<Type, Set<CLDRLocale>>();
     94     private Map<CLDRLocale, String> comments = new HashMap<CLDRLocale, String>();
     95     private Set<CLDRLocale> specialsWildcards = new HashSet<CLDRLocale>();
     96 
     97     public Set<CLDRLocale> getByTypeInternal(Type t) {
     98         return types.get(t);
     99     }
    100 
    101     public Type getTypeInternal(CLDRLocale l) {
    102         l = findLocale(l, l);
    103         return specials.get(l);
    104     }
    105 
    106     public String getCommentInternal(CLDRLocale l) {
    107         l = findLocale(l, l);
    108         return comments.get(l);
    109     }
    110 
    111     public CLDRLocale findLocale(CLDRLocale fromLocale, CLDRLocale origLocale) {
    112         if (origLocale == fromLocale && specials.containsKey(origLocale)) {
    113             return origLocale; // explicit locale - no search.
    114         }
    115         if (fromLocale == null) {
    116             return origLocale;
    117         }
    118         if (specialsWildcards.contains(fromLocale)) {
    119             return fromLocale;
    120         }
    121         return findLocale(fromLocale.getParent(), origLocale);
    122     }
    123 
    124     /**
    125      * Internal constructor
    126      */
    127     private SpecialLocales() {
    128         // from StandardCodes.java
    129         String line;
    130         int ln = 0;
    131         try {
    132             BufferedReader lstreg = CldrUtility.getUTF8Data("SpecialLocales.txt");
    133             while (true) {
    134                 line = lstreg.readLine();
    135                 ln++;
    136                 if (line == null)
    137                     break;
    138                 int commentPos = line.indexOf('#');
    139                 if (commentPos >= 0) {
    140                     line = line.substring(0, commentPos);
    141                 }
    142                 line = line.trim();
    143                 if (line.length() == 0)
    144                     continue;
    145                 List<String> stuff = CldrUtility.splitList(line, ';', true);
    146                 String id = (String) stuff.get(0);
    147                 boolean includeSublocs = (id.endsWith(INCLUDE_SUBLOCALES));
    148                 if (includeSublocs) {
    149                     id = id.substring(0, id.length() - INCLUDE_SUBLOCALES.length());
    150                 }
    151                 String type = (String) stuff.get(1);
    152                 String comment = (String) stuff.get(2);
    153                 Type t = null;
    154 
    155                 // verify that the locale is valid
    156                 CLDRLocale l = null;
    157                 try {
    158                     l = CLDRLocale.getInstance(id);
    159                 } catch (Exception e) {
    160                     throw new IllegalArgumentException("Invalid CLDRLocale in SpecialLocales.txt:" + ln + ": " + line);
    161                 }
    162 
    163                 // verify that the type is valid
    164                 try {
    165                     t = Type.valueOf(type.toLowerCase(Locale.ENGLISH));
    166                 } catch (Exception e) {
    167                     throw new IllegalArgumentException("Invalid SpecialLocales.Type in SpecialLocales.txt:" + ln + ": "
    168                         + line);
    169                 }
    170 
    171                 Set<CLDRLocale> s = types.get(t);
    172                 if (s == null) {
    173                     s = new TreeSet<CLDRLocale>();
    174                     types.put(t, s);
    175                 }
    176                 s.add(l);
    177                 specials.put(l, t);
    178                 if (includeSublocs) {
    179                     specialsWildcards.add(l);
    180                 }
    181                 if (!comment.isEmpty()) {
    182                     comments.put(l, comment);
    183                 }
    184                 if (false) {
    185                     System.out.println(SpecialLocales.class.getSimpleName() + ": locale " + l + ", includejSublocs=" + includeSublocs + ", type=" + t
    186                         + ", comment: " + comment);
    187                 }
    188             }
    189         } catch (IOException e) {
    190             throw new ICUUncheckedIOException("Internal Error", e);
    191         }
    192         specials = Collections.unmodifiableMap(specials);
    193         specialsWildcards = Collections.unmodifiableSet(specialsWildcards);
    194         comments = Collections.unmodifiableMap(comments);
    195         types = Collections.unmodifiableMap(types);
    196     }
    197 
    198 }
    199