1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 **************************************************************************************
6 * Copyright (C) 2009-2016, International Business Machines Corporation,
7 * Google, Inc. and others. All Rights Reserved.
8 **************************************************************************************
9 */
10package android.icu.util;
11
12import java.util.MissingResourceException;
13
14import android.icu.impl.ICUData;
15import android.icu.impl.ICUResourceBundle;
16import android.icu.text.UnicodeSet;
17import android.icu.util.ULocale.Category;
18
19/**
20 * A class for accessing miscellaneous data in the locale bundles
21 * @author ram
22 */
23public final class LocaleData {
24
25    //    private static final String EXEMPLAR_CHARS      = "ExemplarCharacters";
26    private static final String MEASUREMENT_SYSTEM  = "MeasurementSystem";
27    private static final String PAPER_SIZE          = "PaperSize";
28    private static final String LOCALE_DISPLAY_PATTERN  = "localeDisplayPattern";
29    private static final String PATTERN             = "pattern";
30    private static final String SEPARATOR           = "separator";
31    private boolean noSubstitute;
32    private ICUResourceBundle bundle;
33    private ICUResourceBundle langBundle;
34
35    /**
36     * EXType for {@link #getExemplarSet(int, int)}.
37     * Corresponds to the 'main' (aka 'standard') CLDR exemplars in
38     * <a href="http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements">
39     *   http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements</a>.
40     * @hide unsupported on Android
41     */
42    public static final int ES_STANDARD = 0;
43
44    /**
45     * EXType for {@link #getExemplarSet(int, int)}.
46     * Corresponds to the 'auxiliary' CLDR exemplars in
47     * <a href="http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements">
48     *   http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements</a>.
49     * @hide unsupported on Android
50     */
51    public static final int ES_AUXILIARY = 1;
52
53    /**
54     * EXType for {@link #getExemplarSet(int, int)}.
55     * Corresponds to the 'index' CLDR exemplars in
56     * <a href="http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements">
57     *   http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements</a>.
58     * @hide unsupported on Android
59     */
60    public static final int ES_INDEX = 2;
61
62    /**
63     * EXType for {@link #getExemplarSet(int, int)}.
64     * Corresponds to the 'currencySymbol' CLDR exemplars in
65     * <a href="http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements">
66     *   http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements</a>.
67     * Note: This type is no longer supported.
68     * @deprecated ICU 51
69     * @hide original deprecated declaration
70     */
71    @Deprecated
72    public static final int ES_CURRENCY = 3;
73
74    /**
75     * Corresponds to the 'punctuation' CLDR exemplars in
76     * <a href="http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements">
77     *   http://www.unicode.org/reports/tr35/tr35-general.html#Character_Elements</a>.
78     * EXType for {@link #getExemplarSet(int, int)}.
79     * @hide unsupported on Android
80     */
81    public static final int ES_PUNCTUATION = 4;
82
83    /**
84     * Count of EXTypes for {@link #getExemplarSet(int, int)}.
85     * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
86     * @hide original deprecated declaration
87     */
88    @Deprecated
89    public static final int ES_COUNT = 5;
90
91    /**
92     * Delimiter type for {@link #getDelimiter(int)}.
93     */
94    public static final int QUOTATION_START = 0;
95
96    /**
97     * Delimiter type for {@link #getDelimiter(int)}.
98     */
99    public static final int QUOTATION_END = 1;
100
101    /**
102     * Delimiter type for {@link #getDelimiter(int)}.
103     */
104    public static final int ALT_QUOTATION_START = 2;
105
106    /**
107     * Delimiter type for {@link #getDelimiter(int)}.
108     */
109    public static final int ALT_QUOTATION_END = 3;
110
111    /**
112     * Count of delimiter types for {@link #getDelimiter(int)}.
113     * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
114     * @hide original deprecated declaration
115     */
116    @Deprecated
117    public static final int DELIMITER_COUNT = 4;
118
119    // private constructor to prevent default construction
120    ///CLOVER:OFF
121    private LocaleData(){}
122    ///CLOVER:ON
123
124    /**
125     * Returns the set of exemplar characters for a locale. Equivalent to calling {@link #getExemplarSet(ULocale, int, int)} with
126     * the extype == {@link #ES_STANDARD}.
127     *
128     * @param locale    Locale for which the exemplar character set
129     *                  is to be retrieved.
130     * @param options   Bitmask for options to apply to the exemplar pattern.
131     *                  Specify zero to retrieve the exemplar set as it is
132     *                  defined in the locale data.  Specify
133     *                  UnicodeSet.CASE to retrieve a case-folded exemplar
134     *                  set.  See {@link UnicodeSet#applyPattern(String,
135     *                  int)} for a complete list of valid options.  The
136     *                  IGNORE_SPACE bit is always set, regardless of the
137     *                  value of 'options'.
138     * @return          The set of exemplar characters for the given locale.
139     * @hide unsupported on Android
140     */
141    public static UnicodeSet getExemplarSet(ULocale locale, int options) {
142        return LocaleData.getInstance(locale).getExemplarSet(options, ES_STANDARD);
143    }
144
145    /**
146     * Returns the set of exemplar characters for a locale.
147     * Equivalent to calling new LocaleData(locale).{@link #getExemplarSet(int, int)}.
148     *
149     * @param locale    Locale for which the exemplar character set
150     *                  is to be retrieved.
151     * @param options   Bitmask for options to apply to the exemplar pattern.
152     *                  Specify zero to retrieve the exemplar set as it is
153     *                  defined in the locale data.  Specify
154     *                  UnicodeSet.CASE to retrieve a case-folded exemplar
155     *                  set.  See {@link UnicodeSet#applyPattern(String,
156     *                  int)} for a complete list of valid options.  The
157     *                  IGNORE_SPACE bit is always set, regardless of the
158     *                  value of 'options'.
159     * @param extype    The type of exemplar character set to retrieve.
160     * @return          The set of exemplar characters for the given locale.
161     * @hide unsupported on Android
162     */
163    public static UnicodeSet getExemplarSet(ULocale locale, int options, int extype) {
164        return LocaleData.getInstance(locale).getExemplarSet(options, extype);
165    }
166
167    /**
168     * Returns the set of exemplar characters for a locale.
169     *
170     * @param options   Bitmask for options to apply to the exemplar pattern.
171     *                  Specify zero to retrieve the exemplar set as it is
172     *                  defined in the locale data.  Specify
173     *                  UnicodeSet.CASE to retrieve a case-folded exemplar
174     *                  set.  See {@link UnicodeSet#applyPattern(String,
175     *                  int)} for a complete list of valid options.  The
176     *                  IGNORE_SPACE bit is always set, regardless of the
177     *                  value of 'options'.
178     * @param extype    The type of exemplar set to be retrieved,
179     *                  ES_STANDARD, ES_INDEX, ES_AUXILIARY, or ES_PUNCTUATION
180     * @return          The set of exemplar characters for the given locale.
181     *                  If there is nothing available for the locale,
182     *                  then null is returned if {@link #getNoSubstitute()} is true, otherwise the
183     *                  root value is returned (which may be UnicodeSet.EMPTY).
184     * @exception       RuntimeException if the extype is invalid.
185     * @hide unsupported on Android
186     */
187    public UnicodeSet getExemplarSet(int options, int extype) {
188        String [] exemplarSetTypes = {
189                "ExemplarCharacters",
190                "AuxExemplarCharacters",
191                "ExemplarCharactersIndex",
192                "ExemplarCharactersCurrency",
193                "ExemplarCharactersPunctuation"
194        };
195
196        if (extype == ES_CURRENCY) {
197            // currency symbol exemplar is no longer available
198            return noSubstitute ? null : UnicodeSet.EMPTY;
199        }
200
201        try{
202            final String aKey = exemplarSetTypes[extype]; // will throw an out-of-bounds exception
203            ICUResourceBundle stringBundle = (ICUResourceBundle) bundle.get(aKey);
204
205            if (noSubstitute && !bundle.isRoot() && stringBundle.isRoot()) {
206                return null;
207            }
208            String unicodeSetPattern = stringBundle.getString();
209            return new UnicodeSet(unicodeSetPattern, UnicodeSet.IGNORE_SPACE | options);
210        } catch (ArrayIndexOutOfBoundsException aiooe) {
211            throw new IllegalArgumentException(aiooe);
212        } catch (Exception ex){
213            return noSubstitute ? null : UnicodeSet.EMPTY;
214        }
215    }
216
217    /**
218     * Gets the LocaleData object associated with the ULocale specified in locale
219     *
220     * @param locale    Locale with thich the locale data object is associated.
221     * @return          A locale data object.
222     */
223    public static final LocaleData getInstance(ULocale locale) {
224        LocaleData ld = new LocaleData();
225        ld.bundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
226        ld.langBundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_LANG_BASE_NAME, locale);
227        ld.noSubstitute = false;
228        return ld;
229    }
230
231    /**
232     * Gets the LocaleData object associated with the default <code>FORMAT</code> locale
233     *
234     * @return          A locale data object.
235     * @see Category#FORMAT
236     */
237    public static final LocaleData getInstance() {
238        return LocaleData.getInstance(ULocale.getDefault(Category.FORMAT));
239    }
240
241    /**
242     * Sets the "no substitute" behavior of this locale data object.
243     *
244     * @param setting   Value for the no substitute behavior.  If TRUE,
245     *                  methods of this locale data object will return
246     *                  an error when no data is available for that method,
247     *                  given the locale ID supplied to the constructor.
248     */
249    public void setNoSubstitute(boolean setting) {
250        noSubstitute = setting;
251    }
252
253    /**
254     * Gets the "no substitute" behavior of this locale data object.
255     *
256     * @return          Value for the no substitute behavior.  If TRUE,
257     *                  methods of this locale data object will return
258     *                  an error when no data is available for that method,
259     *                  given the locale ID supplied to the constructor.
260     */
261    public boolean getNoSubstitute() {
262        return noSubstitute;
263    }
264
265    private static final String [] DELIMITER_TYPES = {
266        "quotationStart",
267        "quotationEnd",
268        "alternateQuotationStart",
269        "alternateQuotationEnd"
270    };
271
272    /**
273     * Retrieves a delimiter string from the locale data.
274     *
275     * @param type      The type of delimiter string desired.  Currently,
276     *                  the valid choices are QUOTATION_START, QUOTATION_END,
277     *                  ALT_QUOTATION_START, or ALT_QUOTATION_END.
278     * @return          The desired delimiter string.
279     */
280    public String getDelimiter(int type) {
281        ICUResourceBundle delimitersBundle = (ICUResourceBundle) bundle.get("delimiters");
282        // Only some of the quotation marks may be here. So we make sure that we do a multilevel fallback.
283        ICUResourceBundle stringBundle = delimitersBundle.getWithFallback(DELIMITER_TYPES[type]);
284
285        if (noSubstitute && !bundle.isRoot() && stringBundle.isRoot()) {
286            return null;
287        }
288        return stringBundle.getString();
289    }
290
291    /**
292     * Utility for getMeasurementSystem and getPaperSize
293     */
294    private static UResourceBundle measurementTypeBundleForLocale(ULocale locale, String measurementType){
295        // Much of this is taken from getCalendarType in impl/CalendarUtil.java
296        UResourceBundle measTypeBundle = null;
297        String region = ULocale.getRegionForSupplementalData(locale, true);
298        try {
299            UResourceBundle rb = UResourceBundle.getBundleInstance(
300                    ICUData.ICU_BASE_NAME,
301                    "supplementalData",
302                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
303            UResourceBundle measurementData = rb.get("measurementData");
304            UResourceBundle measDataBundle = null;
305            try {
306                measDataBundle = measurementData.get(region);
307                measTypeBundle = measDataBundle.get(measurementType);
308            } catch (MissingResourceException mre) {
309                // use "001" as fallback
310                measDataBundle = measurementData.get("001");
311                measTypeBundle = measDataBundle.get(measurementType);
312            }
313        } catch (MissingResourceException mre) {
314            // fall through
315        }
316        return measTypeBundle;
317    }
318
319
320    /**
321     * Enumeration for representing the measurement systems.
322     */
323    public static final class MeasurementSystem{
324        /**
325         * Measurement system specified by Le Syst&#x00E8;me International d'Unit&#x00E9;s (SI)
326         * otherwise known as Metric system.
327         */
328        public static final MeasurementSystem SI = new MeasurementSystem();
329
330        /**
331         * Measurement system followed in the United States of America.
332         */
333        public static final MeasurementSystem US = new MeasurementSystem();
334
335        /**
336         * Mix of metric and imperial units used in Great Britain.
337         */
338        public static final MeasurementSystem UK = new MeasurementSystem();
339
340        private MeasurementSystem() {}
341    }
342
343    /**
344     * Returns the measurement system used in the locale specified by the locale.
345     *
346     * @param locale      The locale for which the measurement system to be retrieved.
347     * @return MeasurementSystem the measurement system used in the locale.
348     */
349    public static final MeasurementSystem getMeasurementSystem(ULocale locale){
350        UResourceBundle sysBundle = measurementTypeBundleForLocale(locale, MEASUREMENT_SYSTEM);
351
352        switch (sysBundle.getInt()) {
353        case 0: return MeasurementSystem.SI;
354        case 1: return MeasurementSystem.US;
355        case 2: return MeasurementSystem.UK;
356        default:
357            // return null if the object is null or is not an instance
358            // of integer indicating an error
359            return null;
360        }
361    }
362
363    /**
364     * A class that represents the size of letter head
365     * used in the country
366     */
367    public static final class PaperSize{
368        private int height;
369        private int width;
370
371        private PaperSize(int h, int w){
372            height = h;
373            width = w;
374        }
375        /**
376         * Retruns the height of the paper
377         * @return the height
378         */
379        public int getHeight(){
380            return height;
381        }
382        /**
383         * Returns the width of the paper
384         * @return the width
385         */
386        public int getWidth(){
387            return width;
388        }
389    }
390
391    /**
392     * Returns the size of paper used in the locale. The paper sizes returned are always in
393     * <em>milli-meters</em>.
394     * @param locale The locale for which the measurement system to be retrieved.
395     * @return The paper size used in the locale
396     */
397    public static final PaperSize getPaperSize(ULocale locale){
398        UResourceBundle obj = measurementTypeBundleForLocale(locale, PAPER_SIZE);
399        int[] size = obj.getIntVector();
400        return new PaperSize(size[0], size[1]);
401    }
402
403    /**
404     * Returns LocaleDisplayPattern for this locale, e.g., {0}({1})
405     * @return locale display pattern as a String.
406     * @hide unsupported on Android
407     */
408    public String getLocaleDisplayPattern() {
409        ICUResourceBundle locDispBundle = (ICUResourceBundle) langBundle.get(LOCALE_DISPLAY_PATTERN);
410        String localeDisplayPattern = locDispBundle.getStringWithFallback(PATTERN);
411        return localeDisplayPattern;
412    }
413
414    /**
415     * Returns LocaleDisplaySeparator for this locale.
416     * @return locale display separator as a char.
417     * @hide unsupported on Android
418     */
419    public String getLocaleSeparator() {
420        String sub0 = "{0}";
421        String sub1 = "{1}";
422        ICUResourceBundle locDispBundle = (ICUResourceBundle) langBundle.get(LOCALE_DISPLAY_PATTERN);
423        String  localeSeparator = locDispBundle.getStringWithFallback(SEPARATOR);
424        int index0 = localeSeparator.indexOf(sub0);
425        int index1 = localeSeparator.indexOf(sub1);
426        if (index0 >= 0 && index1 >= 0 && index0 <= index1) {
427            return localeSeparator.substring(index0 + sub0.length(), index1);
428        }
429        return localeSeparator;
430    }
431
432    private static VersionInfo gCLDRVersion = null;
433
434    /**
435     * Returns the current CLDR version
436     */
437    public static VersionInfo getCLDRVersion() {
438        // fetching this data should be idempotent.
439        if(gCLDRVersion == null) {
440            // from ZoneMeta.java
441            UResourceBundle supplementalDataBundle = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER);
442            UResourceBundle cldrVersionBundle = supplementalDataBundle.get("cldrVersion");
443            gCLDRVersion = VersionInfo.getInstance(cldrVersionBundle.getString());
444        }
445        return gCLDRVersion;
446    }
447}
448