src/share/classes/java/time/format/DateTimeTextProvider.java

Print this page

        

*** 68,77 **** --- 68,78 ---- import java.time.chrono.Chronology; import java.time.chrono.IsoChronology; import java.time.chrono.JapaneseChronology; import java.time.temporal.ChronoField; + import java.time.temporal.IsoFields; import java.time.temporal.TemporalField; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections;
*** 80,93 **** --- 81,97 ---- import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; + import java.util.ResourceBundle; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import sun.util.locale.provider.CalendarDataUtility; + import sun.util.locale.provider.LocaleProviderAdapter; + import sun.util.locale.provider.LocaleResources; /** * A provider to obtain the textual form of a date-time field. * * <h3>Specification for implementors</h3>
*** 139,157 **** return ((LocaleStore) store).getText(value, style); } return null; } - private static int toStyle(TextStyle style) { - if (style == TextStyle.FULL) { - return Calendar.LONG_FORMAT; - } else if (style == TextStyle.SHORT) { - return Calendar.SHORT_FORMAT; - } - return Calendar.NARROW_STANDALONE; - } - /** * Gets the text for the specified chrono, field, locale and style * for the purpose of formatting. * <p> * The text associated with the value is returned. --- 143,152 ----
*** 198,209 **** fieldIndex = Calendar.AM_PM; fieldValue = (int) value; } else { return null; } ! return CalendarDataUtility.retrieveCldrFieldValueName( ! chrono.getCalendarType(), fieldIndex, fieldValue, toStyle(style), locale); } /** * Gets an iterator of text to field for the specified field, locale and style * for the purpose of parsing. --- 193,204 ---- fieldIndex = Calendar.AM_PM; fieldValue = (int) value; } else { return null; } ! return CalendarDataUtility.retrieveJavaTimeFieldValueName( ! chrono.getCalendarType(), fieldIndex, fieldValue, style.toCalendarStyle(), locale); } /** * Gets an iterator of text to field for the specified field, locale and style * for the purpose of parsing.
*** 268,311 **** break; default: return null; } ! Map<String, Integer> map = CalendarDataUtility.retrieveCldrFieldValueNames( ! chrono.getCalendarType(), fieldIndex, toStyle(style), locale); if (map == null) { return null; } - List<Entry<String, Long>> list = new ArrayList<>(map.size()); switch (fieldIndex) { case Calendar.ERA: ! for (String key : map.keySet()) { ! int era = map.get(key); if (chrono == JapaneseChronology.INSTANCE) { if (era == 0) { era = -999; } else { era -= 2; } } ! list.add(createEntry(key, (long) era)); } break; case Calendar.MONTH: ! for (String key : map.keySet()) { ! list.add(createEntry(key, (long)(map.get(key) + 1))); } break; case Calendar.DAY_OF_WEEK: ! for (String key : map.keySet()) { ! list.add(createEntry(key, (long)toWeekDay(map.get(key)))); } break; default: ! for (String key : map.keySet()) { ! list.add(createEntry(key, (long)map.get(key))); } break; } return list.iterator(); } --- 263,306 ---- break; default: return null; } ! int calendarStyle = (style == null) ? Calendar.ALL_STYLES : style.toCalendarStyle(); ! Map<String, Integer> map = CalendarDataUtility.retrieveJavaTimeFieldValueNames( ! chrono.getCalendarType(), fieldIndex, calendarStyle, locale); if (map == null) { return null; } List<Entry<String, Long>> list = new ArrayList<>(map.size()); switch (fieldIndex) { case Calendar.ERA: ! for (Map.Entry<String, Integer> entry : map.entrySet()) { ! int era = entry.getValue(); if (chrono == JapaneseChronology.INSTANCE) { if (era == 0) { era = -999; } else { era -= 2; } } ! list.add(createEntry(entry.getKey(), (long)era)); } break; case Calendar.MONTH: ! for (Map.Entry<String, Integer> entry : map.entrySet()) { ! list.add(createEntry(entry.getKey(), (long)(entry.getValue() + 1))); } break; case Calendar.DAY_OF_WEEK: ! for (Map.Entry<String, Integer> entry : map.entrySet()) { ! list.add(createEntry(entry.getKey(), (long)toWeekDay(entry.getValue()))); } break; default: ! for (Map.Entry<String, Integer> entry : map.entrySet()) { ! list.add(createEntry(entry.getKey(), (long)entry.getValue())); } break; } return list.iterator(); }
*** 331,419 **** private Object createStore(TemporalField field, Locale locale) { Map<TextStyle, Map<Long, String>> styleMap = new HashMap<>(); if (field == ERA) { for (TextStyle textStyle : TextStyle.values()) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.ERA, toStyle(textStyle), locale).entrySet()) { map.put((long) entry.getValue(), entry.getKey()); } if (!map.isEmpty()) { styleMap.put(textStyle, map); } } return new LocaleStore(styleMap); } if (field == MONTH_OF_YEAR) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.MONTH, Calendar.LONG_FORMAT, locale).entrySet()) { map.put((long) (entry.getValue() + 1), entry.getKey()); } - styleMap.put(TextStyle.FULL, map); ! map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.MONTH, Calendar.SHORT_FORMAT, locale).entrySet()) { ! map.put((long) (entry.getValue() + 1), entry.getKey()); ! } ! styleMap.put(TextStyle.SHORT, map); ! ! map = new HashMap<>(); for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) { String name; ! name = CalendarDataUtility.retrieveCldrFieldValueName( ! "gregory", Calendar.MONTH, month, Calendar.NARROW_STANDALONE, locale); ! if (name != null) { ! map.put((long)(month + 1), name); } } if (!map.isEmpty()) { ! styleMap.put(TextStyle.NARROW, map); } return new LocaleStore(styleMap); } if (field == DAY_OF_WEEK) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.DAY_OF_WEEK, Calendar.LONG_FORMAT, locale).entrySet()) { map.put((long)toWeekDay(entry.getValue()), entry.getKey()); } ! styleMap.put(TextStyle.FULL, map); ! map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.DAY_OF_WEEK, Calendar.SHORT_FORMAT, locale).entrySet()) { ! map.put((long) toWeekDay(entry.getValue()), entry.getKey()); ! } ! styleMap.put(TextStyle.SHORT, map); ! map = new HashMap<>(); for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) { ! map.put((long) toWeekDay(wday), ! CalendarDataUtility.retrieveCldrFieldValueName( ! "gregory", Calendar.DAY_OF_WEEK, wday, Calendar.NARROW_FORMAT, locale)); } - styleMap.put(TextStyle.NARROW, map); return new LocaleStore(styleMap); } if (field == AMPM_OF_DAY) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : ! CalendarDataUtility.retrieveCldrFieldValueNames( ! "gregory", Calendar.AM_PM, Calendar.LONG_FORMAT, locale).entrySet()) { map.put((long) entry.getValue(), entry.getKey()); } ! styleMap.put(TextStyle.FULL, map); ! styleMap.put(TextStyle.SHORT, map); // re-use, as we don't have different data return new LocaleStore(styleMap); } return ""; // null marker for map } --- 326,455 ---- private Object createStore(TemporalField field, Locale locale) { Map<TextStyle, Map<Long, String>> styleMap = new HashMap<>(); if (field == ERA) { for (TextStyle textStyle : TextStyle.values()) { + if (textStyle.isStandalone()) { + // Stand-alone isn't applicable to era names. + continue; + } + Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.ERA, textStyle.toCalendarStyle(), locale); + if (displayNames != null) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : displayNames.entrySet()) { map.put((long) entry.getValue(), entry.getKey()); } if (!map.isEmpty()) { styleMap.put(textStyle, map); } } + } return new LocaleStore(styleMap); } if (field == MONTH_OF_YEAR) { + for (TextStyle textStyle : TextStyle.values()) { + Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale); Map<Long, String> map = new HashMap<>(); ! if (displayNames != null) { ! for (Entry<String, Integer> entry : displayNames.entrySet()) { map.put((long) (entry.getValue() + 1), entry.getKey()); } ! } else { ! // Narrow names may have duplicated names, such as "J" for January, Jun, July. ! // Get names one by one in that case. for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) { String name; ! name = CalendarDataUtility.retrieveJavaTimeFieldValueName( ! "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale); ! if (name == null) { ! break; ! } ! map.put((long) (month + 1), name); } } if (!map.isEmpty()) { ! styleMap.put(textStyle, map); ! } } return new LocaleStore(styleMap); } if (field == DAY_OF_WEEK) { + for (TextStyle textStyle : TextStyle.values()) { + Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale); Map<Long, String> map = new HashMap<>(); ! if (displayNames != null) { ! for (Entry<String, Integer> entry : displayNames.entrySet()) { map.put((long)toWeekDay(entry.getValue()), entry.getKey()); } ! ! } else { ! // Narrow names may have duplicated names, such as "S" for Sunday and Saturday. ! // Get names one by one in that case. for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) { ! String name; ! name = CalendarDataUtility.retrieveJavaTimeFieldValueName( ! "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale); ! if (name == null) { ! break; ! } ! map.put((long)toWeekDay(wday), name); ! } ! } ! if (!map.isEmpty()) { ! styleMap.put(textStyle, map); ! } } return new LocaleStore(styleMap); } if (field == AMPM_OF_DAY) { + for (TextStyle textStyle : TextStyle.values()) { + if (textStyle.isStandalone()) { + // Stand-alone isn't applicable to AM/PM. + continue; + } + Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames( + "gregory", Calendar.AM_PM, textStyle.toCalendarStyle(), locale); + if (displayNames != null) { Map<Long, String> map = new HashMap<>(); ! for (Entry<String, Integer> entry : displayNames.entrySet()) { map.put((long) entry.getValue(), entry.getKey()); } ! if (!map.isEmpty()) { ! styleMap.put(textStyle, map); ! } ! } ! } ! return new LocaleStore(styleMap); ! } ! ! if (field == IsoFields.QUARTER_OF_YEAR) { ! // The order of keys must correspond to the TextStyle.values() order. ! final String[] keys = { ! "QuarterNames", ! "standalone.QuarterNames", ! "QuarterAbbreviations", ! "standalone.QuarterAbbreviations", ! "QuarterNarrows", ! "standalone.QuarterNarrows", ! }; ! for (int i = 0; i < keys.length; i++) { ! String[] names = getLocalizedResource(keys[i], locale); ! if (names != null) { ! Map<Long, String> map = new HashMap<>(); ! for (int q = 0; q < names.length; q++) { ! map.put((long) (q + 1), names[q]); ! } ! styleMap.put(TextStyle.values()[i], map); ! } ! } return new LocaleStore(styleMap); } return ""; // null marker for map }
*** 428,437 **** --- 464,490 ---- private static <A, B> Entry<A, B> createEntry(A text, B field) { return new SimpleImmutableEntry<>(text, field); } /** + * Returns the localized resource of the given key and locale, or null + * if no localized resource is available. + * + * @param key the key of the localized resource, not null + * @param locale the locale, not null + * @return the localized resource, or null if not available + * @throws NullPointerException if key or locale is null + */ + @SuppressWarnings("unchecked") + static <T> T getLocalizedResource(String key, Locale locale) { + LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased() + .getLocaleResources(locale); + ResourceBundle rb = lr.getJavaTimeFormatData(); + return rb.containsKey(key) ? (T) rb.getObject(key) : null; + } + + /** * Stores the text for a single locale. * <p> * Some fields have a textual representation, such as day-of-week or month-of-year. * These textual representations can be captured in this class for printing * and parsing.
*** 455,475 **** */ LocaleStore(Map<TextStyle, Map<Long, String>> valueTextMap) { this.valueTextMap = valueTextMap; Map<TextStyle, List<Entry<String, Long>>> map = new HashMap<>(); List<Entry<String, Long>> allList = new ArrayList<>(); ! for (TextStyle style : valueTextMap.keySet()) { Map<String, Entry<String, Long>> reverse = new HashMap<>(); ! for (Map.Entry<Long, String> entry : valueTextMap.get(style).entrySet()) { if (reverse.put(entry.getValue(), createEntry(entry.getValue(), entry.getKey())) != null) { // TODO: BUG: this has no effect continue; // not parsable, try next style } } List<Entry<String, Long>> list = new ArrayList<>(reverse.values()); Collections.sort(list, COMPARATOR); ! map.put(style, list); allList.addAll(list); map.put(null, allList); } Collections.sort(allList, COMPARATOR); this.parsable = map; --- 508,528 ---- */ LocaleStore(Map<TextStyle, Map<Long, String>> valueTextMap) { this.valueTextMap = valueTextMap; Map<TextStyle, List<Entry<String, Long>>> map = new HashMap<>(); List<Entry<String, Long>> allList = new ArrayList<>(); ! for (Map.Entry<TextStyle, Map<Long, String>> vtmEntry : valueTextMap.entrySet()) { Map<String, Entry<String, Long>> reverse = new HashMap<>(); ! for (Map.Entry<Long, String> entry : vtmEntry.getValue().entrySet()) { if (reverse.put(entry.getValue(), createEntry(entry.getValue(), entry.getKey())) != null) { // TODO: BUG: this has no effect continue; // not parsable, try next style } } List<Entry<String, Long>> list = new ArrayList<>(reverse.values()); Collections.sort(list, COMPARATOR); ! map.put(vtmEntry.getKey(), list); allList.addAll(list); map.put(null, allList); } Collections.sort(allList, COMPARATOR); this.parsable = map;