/** * Set the format used for formatting or parsing. If null or not available, use the * getNumberInstance(locale). * * @param format the number formatter. * @return this, for chaining. * @stable ICU 4.0 */ public TimeUnitFormat setNumberFormat(NumberFormat format) { if (format == this.format) { return this; } if (format == null) { if (locale == null) { isReady = false; return this; } else { this.format = NumberFormat.getNumberInstance(locale); } } else { this.format = format; } // reset the number formatter in the timeUnitToCountToPatterns map if (isReady == false) { return this; } for (Map<String, Object[]> countToPattern : timeUnitToCountToPatterns.values()) { for (Object[] pair : countToPattern.values()) { MessageFormat pattern = (MessageFormat) pair[FULL_NAME]; pattern.setFormatByArgumentIndex(0, format); pattern = (MessageFormat) pair[ABBREVIATED_NAME]; pattern.setFormatByArgumentIndex(0, format); } } return this; }
// srcPluralCount is the original plural count on which the pattern is // searched for. // searchPluralCount is the fallback plural count. // For example, to search for pattern for ""one" hour", // "one" is the srcPluralCount, // if the pattern is not found even in root, fallback to // using patterns of plural count "other", // then, "other" is the searchPluralCount. private void searchInTree( String resourceKey, int styl, TimeUnit timeUnit, String srcPluralCount, String searchPluralCount, Map<String, Object[]> countToPatterns) { ULocale parentLocale = locale; String srcTimeUnitName = timeUnit.toString(); while (parentLocale != null) { try { // look for pattern for srcPluralCount in locale tree ICUResourceBundle unitsRes = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, parentLocale); unitsRes = unitsRes.getWithFallback(resourceKey); ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(srcTimeUnitName); String pattern = oneUnitRes.getStringWithFallback(searchPluralCount); final MessageFormat messageFormat = new MessageFormat(pattern, locale); if (format != null) { messageFormat.setFormatByArgumentIndex(0, format); } Object[] pair = countToPatterns.get(srcPluralCount); if (pair == null) { pair = new Object[2]; countToPatterns.put(srcPluralCount, pair); } pair[styl] = messageFormat; return; } catch (MissingResourceException e) { } parentLocale = parentLocale.getFallback(); } // if no unitsShort resource was found even after fallback to root locale // then search the units resource fallback from the current level to root if (parentLocale == null && resourceKey.equals("unitsShort")) { searchInTree("units", styl, timeUnit, srcPluralCount, searchPluralCount, countToPatterns); if (countToPatterns != null && countToPatterns.get(srcPluralCount) != null && countToPatterns.get(srcPluralCount)[styl] != null) { return; } } // if not found the pattern for this plural count at all, // fall-back to plural count "other" if (searchPluralCount.equals("other")) { // set default fall back the same as the resource in root MessageFormat messageFormat = null; if (timeUnit == TimeUnit.SECOND) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_SECOND, locale); } else if (timeUnit == TimeUnit.MINUTE) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MINUTE, locale); } else if (timeUnit == TimeUnit.HOUR) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_HOUR, locale); } else if (timeUnit == TimeUnit.WEEK) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_WEEK, locale); } else if (timeUnit == TimeUnit.DAY) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_DAY, locale); } else if (timeUnit == TimeUnit.MONTH) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MONTH, locale); } else if (timeUnit == TimeUnit.YEAR) { messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, locale); } if (format != null && messageFormat != null) { messageFormat.setFormatByArgumentIndex(0, format); } Object[] pair = countToPatterns.get(srcPluralCount); if (pair == null) { pair = new Object[2]; countToPatterns.put(srcPluralCount, pair); } pair[styl] = messageFormat; } else { // fall back to rule "other", and search in parents searchInTree(resourceKey, styl, timeUnit, srcPluralCount, "other", countToPatterns); } }
private void setup( String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns, int style) { // fill timeUnitToCountToPatterns from resource file try { ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale); ICUResourceBundle unitsRes = resource.getWithFallback(resourceKey); int size = unitsRes.getSize(); for (int index = 0; index < size; ++index) { String timeUnitName = unitsRes.get(index).getKey(); TimeUnit timeUnit = null; if (timeUnitName.equals("year")) { timeUnit = TimeUnit.YEAR; } else if (timeUnitName.equals("month")) { timeUnit = TimeUnit.MONTH; } else if (timeUnitName.equals("day")) { timeUnit = TimeUnit.DAY; } else if (timeUnitName.equals("hour")) { timeUnit = TimeUnit.HOUR; } else if (timeUnitName.equals("minute")) { timeUnit = TimeUnit.MINUTE; } else if (timeUnitName.equals("second")) { timeUnit = TimeUnit.SECOND; } else if (timeUnitName.equals("week")) { timeUnit = TimeUnit.WEEK; } else { continue; } ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(timeUnitName); int count = oneUnitRes.getSize(); Map<String, Object[]> countToPatterns = timeUnitToCountToPatterns.get(timeUnit); if (countToPatterns == null) { countToPatterns = new TreeMap<String, Object[]>(); timeUnitToCountToPatterns.put(timeUnit, countToPatterns); } for (int pluralIndex = 0; pluralIndex < count; ++pluralIndex) { String pluralCount = oneUnitRes.get(pluralIndex).getKey(); String pattern = oneUnitRes.get(pluralIndex).getString(); final MessageFormat messageFormat = new MessageFormat(pattern, locale); if (format != null) { messageFormat.setFormatByArgumentIndex(0, format); } // save both full name and abbreviated name in one table // is good space-wise, but it degrades performance, // since it needs to check whether the needed space // is already allocated or not. Object[] pair = countToPatterns.get(pluralCount); if (pair == null) { pair = new Object[2]; countToPatterns.put(pluralCount, pair); } pair[style] = messageFormat; } } } catch (MissingResourceException e) { } // there should be patterns for each plural rule in each time unit. // For each time unit, // for each plural rule, following is unit pattern fall-back rule: // ( for example: "one" hour ) // look for its unit pattern in its locale tree. // if pattern is not found in its own locale, such as de_DE, // look for the pattern in its parent, such as de, // keep looking till found or till root. // if the pattern is not found in root either, // fallback to plural count "other", // look for the pattern of "other" in the locale tree: // "de_DE" to "de" to "root". // If not found, fall back to value of // static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h". // // Following is consistency check to create pattern for each // plural rule in each time unit using above fall-back rule. // final TimeUnit[] timeUnits = TimeUnit.values(); Set<String> keywords = pluralRules.getKeywords(); for (int i = 0; i < timeUnits.length; ++i) { // for each time unit, // get all the patterns for each plural rule in this locale. final TimeUnit timeUnit = timeUnits[i]; Map<String, Object[]> countToPatterns = timeUnitToCountToPatterns.get(timeUnit); if (countToPatterns == null) { countToPatterns = new TreeMap<String, Object[]>(); timeUnitToCountToPatterns.put(timeUnit, countToPatterns); } for (String pluralCount : keywords) { if (countToPatterns.get(pluralCount) == null || countToPatterns.get(pluralCount)[style] == null) { // look through parents searchInTree(resourceKey, style, timeUnit, pluralCount, pluralCount, countToPatterns); } } } }