2 **************************************************************************************
3 * Copyright (C) 2009-2013, Google, Inc.; International Business Machines Corporation *
4 * and others. All Rights Reserved. *
5 **************************************************************************************
7 package com.ibm.icu.util;
9 import java.util.MissingResourceException;
11 import com.ibm.icu.impl.ICUResourceBundle;
12 import com.ibm.icu.text.UnicodeSet;
13 import com.ibm.icu.util.ULocale.Category;
16 * A class for accessing miscellaneous data in the locale bundles
20 public final class LocaleData {
22 // private static final String EXEMPLAR_CHARS = "ExemplarCharacters";
23 private static final String MEASUREMENT_SYSTEM = "MeasurementSystem";
24 private static final String PAPER_SIZE = "PaperSize";
25 private static final String LOCALE_DISPLAY_PATTERN = "localeDisplayPattern";
26 private static final String PATTERN = "pattern";
27 private static final String SEPARATOR = "separator";
28 private boolean noSubstitute;
29 private ICUResourceBundle bundle;
30 private ICUResourceBundle langBundle;
33 * EXType for {@link #getExemplarSet(int, int)}.
36 public static final int ES_STANDARD = 0;
39 * EXType for {@link #getExemplarSet(int, int)}.
42 public static final int ES_AUXILIARY = 1;
45 * EXType for {@link #getExemplarSet(int, int)}.
48 public static final int ES_INDEX = 2;
51 * EXType for {@link #getExemplarSet(int, int)}.
52 * Note: This type is no longer supported.
55 public static final int ES_CURRENCY = 3;
58 * EXType for {@link #getExemplarSet(int, int)}.
61 public static final int ES_PUNCTUATION = 4;
64 * Count of EXTypes for {@link #getExemplarSet(int, int)}.
67 public static final int ES_COUNT = 5;
70 * Delimiter type for {@link #getDelimiter(int)}.
73 public static final int QUOTATION_START = 0;
76 * Delimiter type for {@link #getDelimiter(int)}.
79 public static final int QUOTATION_END = 1;
82 * Delimiter type for {@link #getDelimiter(int)}.
85 public static final int ALT_QUOTATION_START = 2;
88 * Delimiter type for {@link #getDelimiter(int)}.
91 public static final int ALT_QUOTATION_END = 3;
94 * Count of delimiter types for {@link #getDelimiter(int)}.
97 public static final int DELIMITER_COUNT = 4;
99 // private constructor to prevent default construction
101 private LocaleData(){}
105 * Returns the set of exemplar characters for a locale.
107 * @param locale Locale for which the exemplar character set
108 * is to be retrieved.
109 * @param options Bitmask for options to apply to the exemplar pattern.
110 * Specify zero to retrieve the exemplar set as it is
111 * defined in the locale data. Specify
112 * UnicodeSet.CASE to retrieve a case-folded exemplar
113 * set. See {@link UnicodeSet#applyPattern(String,
114 * int)} for a complete list of valid options. The
115 * IGNORE_SPACE bit is always set, regardless of the
116 * value of 'options'.
117 * @return The set of exemplar characters for the given locale.
120 public static UnicodeSet getExemplarSet(ULocale locale, int options) {
121 return LocaleData.getInstance(locale).getExemplarSet(options, ES_STANDARD);
125 * Returns the set of exemplar characters for a locale.
127 * @param locale Locale for which the exemplar character set
128 * is to be retrieved.
129 * @param options Bitmask for options to apply to the exemplar pattern.
130 * Specify zero to retrieve the exemplar set as it is
131 * defined in the locale data. Specify
132 * UnicodeSet.CASE to retrieve a case-folded exemplar
133 * set. See {@link UnicodeSet#applyPattern(String,
134 * int)} for a complete list of valid options. The
135 * IGNORE_SPACE bit is always set, regardless of the
136 * value of 'options'.
137 * @param extype The type of exemplar character set to retrieve.
138 * @return The set of exemplar characters for the given locale.
141 public static UnicodeSet getExemplarSet(ULocale locale, int options, int extype) {
142 return LocaleData.getInstance(locale).getExemplarSet(options, extype);
146 * Returns the set of exemplar characters for a locale.
148 * @param options Bitmask for options to apply to the exemplar pattern.
149 * Specify zero to retrieve the exemplar set as it is
150 * defined in the locale data. Specify
151 * UnicodeSet.CASE to retrieve a case-folded exemplar
152 * set. See {@link UnicodeSet#applyPattern(String,
153 * int)} for a complete list of valid options. The
154 * IGNORE_SPACE bit is always set, regardless of the
155 * value of 'options'.
156 * @param extype The type of exemplar set to be retrieved,
157 * ES_STANDARD, ES_INDEX, ES_AUXILIARY, or ES_PUNCTUATION
158 * @return The set of exemplar characters for the given locale.
161 public UnicodeSet getExemplarSet(int options, int extype) {
162 String [] exemplarSetTypes = {
163 "ExemplarCharacters", "AuxExemplarCharacters",
164 "ExemplarCharactersIndex", "ExemplarCharactersCurrency",
165 "ExemplarCharactersPunctuation"
168 if (extype == ES_CURRENCY) {
169 // currency symbol exemplar is no longer available
170 return new UnicodeSet();
174 ICUResourceBundle stringBundle = (ICUResourceBundle) bundle.get(exemplarSetTypes[extype]);
176 if ( noSubstitute && (stringBundle.getLoadingStatus() == ICUResourceBundle.FROM_ROOT) )
179 String unicodeSetPattern = stringBundle.getString();
180 if (extype == ES_PUNCTUATION) {
182 return new UnicodeSet(unicodeSetPattern, UnicodeSet.IGNORE_SPACE | options);
183 } catch (IllegalArgumentException e) {
184 throw new IllegalArgumentException("Can't create exemplars for " + exemplarSetTypes[extype] + " in " + bundle.getLocale(), e);
187 return new UnicodeSet(unicodeSetPattern, UnicodeSet.IGNORE_SPACE | options);
188 }catch(MissingResourceException ex){
189 if(extype==LocaleData.ES_AUXILIARY){
190 return new UnicodeSet();
191 } else if (extype==LocaleData.ES_INDEX){
199 * Gets the LocaleData object associated with the ULocale specified in locale
201 * @param locale Locale with thich the locale data object is associated.
202 * @return A locale data object.
205 public static final LocaleData getInstance(ULocale locale) {
206 LocaleData ld = new LocaleData();
207 ld.bundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);
208 ld.langBundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_LANG_BASE_NAME, locale);
209 ld.noSubstitute = false;
214 * Gets the LocaleData object associated with the default <code>FORMAT</code> locale
216 * @return A locale data object.
217 * @see Category#FORMAT
220 public static final LocaleData getInstance() {
221 return LocaleData.getInstance(ULocale.getDefault(Category.FORMAT));
225 * Sets the "no substitute" behavior of this locale data object.
227 * @param setting Value for the no substitute behavior. If TRUE,
228 * methods of this locale data object will return
229 * an error when no data is available for that method,
230 * given the locale ID supplied to the constructor.
233 public void setNoSubstitute(boolean setting) {
234 noSubstitute = setting;
238 * Gets the "no substitute" behavior of this locale data object.
240 * @return Value for the no substitute behavior. If TRUE,
241 * methods of this locale data object will return
242 * an error when no data is available for that method,
243 * given the locale ID supplied to the constructor.
246 public boolean getNoSubstitute() {
250 private static final String [] DELIMITER_TYPES = {
253 "alternateQuotationStart",
254 "alternateQuotationEnd"
258 * Retrieves a delimiter string from the locale data.
260 * @param type The type of delimiter string desired. Currently,
261 * the valid choices are QUOTATION_START, QUOTATION_END,
262 * ALT_QUOTATION_START, or ALT_QUOTATION_END.
263 * @return The desired delimiter string.
266 public String getDelimiter(int type) {
267 ICUResourceBundle delimitersBundle = (ICUResourceBundle) bundle.get("delimiters");
268 // Only some of the quotation marks may be here. So we make sure that we do a multilevel fallback.
269 ICUResourceBundle stringBundle = delimitersBundle.getWithFallback(DELIMITER_TYPES[type]);
271 if ( noSubstitute && (stringBundle.getLoadingStatus() == ICUResourceBundle.FROM_ROOT) )
274 return stringBundle.getString();
278 * Utility for getMeasurementSystem and getPaperSize
280 private static UResourceBundle measurementTypeBundleForLocale(ULocale locale, String measurementType){
281 // Much of this is taken from getCalendarType in impl/CalendarUtil.java
282 UResourceBundle measTypeBundle = null;
283 ULocale fullLoc = ULocale.addLikelySubtags(locale);
284 String region = fullLoc.getCountry();
286 UResourceBundle rb = UResourceBundle.getBundleInstance(
287 ICUResourceBundle.ICU_BASE_NAME,
289 ICUResourceBundle.ICU_DATA_CLASS_LOADER);
290 UResourceBundle measurementData = rb.get("measurementData");
291 UResourceBundle measDataBundle = null;
293 measDataBundle = measurementData.get(region);
294 measTypeBundle = measDataBundle.get(measurementType);
295 } catch (MissingResourceException mre) {
296 // use "001" as fallback
297 measDataBundle = measurementData.get("001");
298 measTypeBundle = measDataBundle.get(measurementType);
300 } catch (MissingResourceException mre) {
303 return measTypeBundle;
308 * Enumeration for representing the measurement systems.
311 public static final class MeasurementSystem{
313 * Measurement system specified by Le Système International d'Unités (SI)
314 * otherwise known as Metric system.
317 public static final MeasurementSystem SI = new MeasurementSystem(0);
320 * Measurement system followed in the United States of America.
323 public static final MeasurementSystem US = new MeasurementSystem(1);
325 private int systemID;
326 private MeasurementSystem(int id){
330 private boolean equals(int id){
331 return systemID == id;
336 * Returns the measurement system used in the locale specified by the locale.
338 * @param locale The locale for which the measurement system to be retrieved.
339 * @return MeasurementSystem the measurement system used in the locale.
342 public static final MeasurementSystem getMeasurementSystem(ULocale locale){
343 UResourceBundle sysBundle = measurementTypeBundleForLocale(locale, MEASUREMENT_SYSTEM);
345 int system = sysBundle.getInt();
346 if(MeasurementSystem.US.equals(system)){
347 return MeasurementSystem.US;
349 if(MeasurementSystem.SI.equals(system)){
350 return MeasurementSystem.SI;
352 // return null if the object is null or is not an instance
353 // of integer indicating an error
358 * A class that represents the size of letter head
359 * used in the country
362 public static final class PaperSize{
366 private PaperSize(int h, int w){
371 * Retruns the height of the paper
375 public int getHeight(){
379 * Returns the width of the paper
383 public int getWidth(){
389 * Returns the size of paper used in the locale. The paper sizes returned are always in
390 * <em> milli-meters<em>.
391 * @param locale The locale for which the measurement system to be retrieved.
392 * @return The paper size used in the locale
395 public static final PaperSize getPaperSize(ULocale locale){
396 UResourceBundle obj = measurementTypeBundleForLocale(locale, PAPER_SIZE);
397 int[] size = obj.getIntVector();
398 return new PaperSize(size[0], size[1]);
402 * Returns LocaleDisplayPattern for this locale, e.g., {0}({1})
403 * @return locale display pattern as a String.
406 public String getLocaleDisplayPattern() {
407 ICUResourceBundle locDispBundle = (ICUResourceBundle) langBundle.get(LOCALE_DISPLAY_PATTERN);
408 String localeDisplayPattern = locDispBundle.getStringWithFallback(PATTERN);
409 return localeDisplayPattern;
413 * Returns LocaleDisplaySeparator for this locale.
414 * @return locale display separator as a char.
417 public String getLocaleSeparator() {
420 ICUResourceBundle locDispBundle = (ICUResourceBundle) langBundle.get(LOCALE_DISPLAY_PATTERN);
421 String localeSeparator = locDispBundle.getStringWithFallback(SEPARATOR);
422 int index0 = localeSeparator.indexOf(sub0);
423 int index1 = localeSeparator.indexOf(sub1);
424 if (index0 >= 0 && index1 >= 0 && index0 <= index1) {
425 return localeSeparator.substring(index0 + sub0.length(), index1);
427 return localeSeparator;
430 private static VersionInfo gCLDRVersion = null;
433 * Returns the current CLDR version
436 public static VersionInfo getCLDRVersion() {
437 // fetching this data should be idempotent.
438 if(gCLDRVersion == null) {
439 // from ZoneMeta.java
440 UResourceBundle supplementalDataBundle = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "supplementalData", ICUResourceBundle.ICU_DATA_CLASS_LOADER);
441 UResourceBundle cldrVersionBundle = supplementalDataBundle.get("cldrVersion");
442 gCLDRVersion = VersionInfo.getInstance(cldrVersionBundle.getString());