diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 246acf3e3aa..c35bb29989c 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -206,6 +206,7 @@ JAVA_JAVA_java = \ sun/util/locale/provider/BreakIteratorProviderImpl.java \ sun/util/locale/provider/CalendarDataProviderImpl.java \ sun/util/locale/provider/CalendarDataUtility.java \ + sun/util/locale/provider/CalendarNameProviderImpl.java \ sun/util/locale/provider/CollationRules.java \ sun/util/locale/provider/CollatorProviderImpl.java \ sun/util/locale/provider/CurrencyNameProviderImpl.java \ @@ -396,6 +397,7 @@ JAVA_JAVA_java = \ java/util/prefs/Base64.java \ java/util/prefs/XmlSupport.java \ java/util/spi/CalendarDataProvider.java \ + java/util/spi/CalendarNameProvider.java \ java/util/spi/CurrencyNameProvider.java \ java/util/spi/LocaleNameProvider.java \ java/util/spi/LocaleServiceProvider.java \ diff --git a/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java index 6a6aec83b89..f571512d30b 100644 --- a/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java +++ b/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.TimeZoneNameProvider; @@ -323,6 +324,30 @@ public class HostLocaleProviderAdapterImpl { return isSupportedCalendarLocale(locale); } + @Override + public int getFirstDayOfWeek(Locale locale) { + return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK); + } + + @Override + public int getMinimalDaysInFirstWeek(Locale locale) { + return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK); + } + }; + } + + public static CalendarNameProvider getCalendarNameProvider() { + return new CalendarNameProvider() { + @Override + public Locale[] getAvailableLocales() { + return getSupportedCalendarLocales(); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return isSupportedCalendarLocale(locale); + } + @Override public String getDisplayName(String calType, int field, int value, int style, Locale locale) { @@ -334,16 +359,6 @@ public class HostLocaleProviderAdapterImpl { int field, int style, Locale locale) { return null; } - - @Override - public int getFirstDayOfWeek(Locale locale) { - return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK); - } - - @Override - public int getMinimalDaysInFirstWeek(Locale locale) { - return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK); - } }; } diff --git a/jdk/src/share/classes/java/util/Calendar.java b/jdk/src/share/classes/java/util/Calendar.java index bae9cacfc60..f641a37e632 100644 --- a/jdk/src/share/classes/java/util/Calendar.java +++ b/jdk/src/share/classes/java/util/Calendar.java @@ -2699,12 +2699,9 @@ public abstract class Calendar implements Serializable, Cloneable, ComparableCalendar Types - * - *

Calendar types are used to specify calendar systems for which the {@link - * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link - * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide - * calendar field value names. See {@link Calendar#getCalendarType()} for details. - * - *

Calendar Fields - * - *

Calendar fields are specified with the constants defined in {@link - * Calendar}. The following are calendar-common fields and their values to be - * supported for each calendar system. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
FieldValueDescription
{@link Calendar#MONTH}{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}Month numbering is 0-based (e.g., 0 - January, ..., 11 - - * December). Some calendar systems have 13 months. Month - * names need to be supported in both the formatting and - * stand-alone forms if required by the supported locales. If there's - * no distinction in the two forms, the same names should be returned - * in both of the forms.
{@link Calendar#DAY_OF_WEEK}{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday, - * ..., 7 - Saturday).
{@link Calendar#AM_PM}{@link Calendar#AM} to {@link Calendar#PM}0 - AM, 1 - PM
- * - *

The following are calendar-specific fields and their values to be supported. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Calendar TypeFieldValueDescription
{@code "gregory"}{@link Calendar#ERA}0{@link java.util.GregorianCalendar#BC} (BCE)
1{@link java.util.GregorianCalendar#AD} (CE)
{@code "buddhist"}{@link Calendar#ERA}0BC (BCE)
1B.E. (Buddhist Era)
{@code "japanese"}{@link Calendar#ERA}0Seireki (Before Meiji)
1Meiji
2Taisho
3Showa
4Heisei
{@link Calendar#YEAR}1the first year in each era. It should be returned when a long - * style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is - * specified. See also the - * Year representation in {@code SimpleDateFormat}.
- * - *

Calendar field value names for {@code "gregory"} must be consistent with - * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}. - * - *

Time zone names are supported by {@link TimeZoneNameProvider}. + * An abstract class for service providers that provide locale-dependent {@link + * Calendar} parameters. * * @author Masayoshi Okutsu * @since 1.8 - * @see Locale#getUnicodeLocaleType(String) + * @see CalendarNameProvider */ public abstract class CalendarDataProvider extends LocaleServiceProvider { @@ -188,112 +78,4 @@ public abstract class CalendarDataProvider extends LocaleServiceProvider { * @see java.util.Calendar#getMinimalDaysInFirstWeek() */ public abstract int getMinimalDaysInFirstWeek(Locale locale); - - /** - * Returns the string representation (display name) of the calendar - * field value in the given style and - * locale. If no string representation is - * applicable, null is returned. - * - *

{@code field} is a {@code Calendar} field index, such as {@link - * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and - * {@link Calendar#DST_OFFSET}, are not supported by this - * method. {@code null} must be returned if any time zone fields are - * specified. - * - *

{@code value} is the numeric representation of the {@code field} value. - * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid - * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY} - * (inclusive). - * - *

{@code style} gives the style of the string representation. It is one - * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), - * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} - * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}. - * - *

For example, the following call will return {@code "Sunday"}. - *

-     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
-     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
-     * 
- * - * @param calendarType - * the calendar type. (Any calendar type given by {@code locale} - * is ignored.) - * @param field - * the {@code Calendar} field index, - * such as {@link Calendar#DAY_OF_WEEK} - * @param value - * the value of the {@code Calendar field}, - * such as {@link Calendar#MONDAY} - * @param style - * the string representation style: one of {@link - * Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), - * {@link Calendar#SHORT_STANDALONE}, {@link - * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or - * {@link Calendar#LONG_STANDALONE} - * @param locale - * the desired locale - * @return the string representation of the {@code field value}, or {@code - * null} if the string representation is not applicable or - * the given calendar type is unknown - * @throws IllegalArgumentException - * if {@code field} or {@code style} is invalid - * @throws NullPointerException if {@code locale} is {@code null} - * @see TimeZoneNameProvider - * @see java.util.Calendar#get(int) - * @see java.util.Calendar#getDisplayName(int, int, Locale) - */ - public abstract String getDisplayName(String calendarType, - int field, int value, - int style, Locale locale); - - /** - * Returns a {@code Map} containing all string representations (display - * names) of the {@code Calendar} {@code field} in the given {@code style} - * and {@code locale} and their corresponding field values. - * - *

{@code field} is a {@code Calendar} field index, such as {@link - * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and - * {@link Calendar#DST_OFFSET}, are not supported by this - * method. {@code null} must be returned if any time zone fields are specified. - * - *

{@code style} gives the style of the string representation. It must be - * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link - * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link - * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link - * Calendar#LONG_STANDALONE}. - * - *

For example, the following call will return a {@code Map} containing - * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link - * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY}, - * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on. - *

-     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
-     * 
- * - * @param calendarType - * the calendar type. (Any calendar type given by {@code locale} - * is ignored.) - * @param field - * the calendar field for which the display names are returned - * @param style - * the style applied to the display names; one of - * {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} - * ({@link Calendar#SHORT SHORT}), {@link - * Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} - * ({@link Calendar#LONG LONG}), or {@link - * Calendar#LONG_STANDALONE}. - * @param locale - * the desired locale - * @return a {@code Map} containing all display names of {@code field} in - * {@code style} and {@code locale} and their {@code field} values, - * or {@code null} if no display names are defined for {@code field} - * @throws NullPointerException - * if {@code locale} is {@code null} - * @see Calendar#getDisplayNames(int, int, Locale) - */ - public abstract Map getDisplayNames(String calendarType, - int field, int style, - Locale locale); } diff --git a/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java b/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java new file mode 100644 index 00000000000..20122cf5466 --- /dev/null +++ b/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.spi; + +import java.util.Calendar; +import java.util.Locale; +import java.util.Map; + +/** + * An abstract class for service providers that provide localized string + * representations (display names) of {@code Calendar} field values. + * + *

Calendar Types + * + *

Calendar types are used to specify calendar systems for which the {@link + * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link + * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide + * calendar field value names. See {@link Calendar#getCalendarType()} for details. + * + *

Calendar Fields + * + *

Calendar fields are specified with the constants defined in {@link + * Calendar}. The following are calendar-common fields and their values to be + * supported for each calendar system. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FieldValueDescription
{@link Calendar#MONTH}{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}Month numbering is 0-based (e.g., 0 - January, ..., 11 - + * December). Some calendar systems have 13 months. Month + * names need to be supported in both the formatting and + * stand-alone forms if required by the supported locales. If there's + * no distinction in the two forms, the same names should be returned + * in both of the forms.
{@link Calendar#DAY_OF_WEEK}{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday, + * ..., 7 - Saturday).
{@link Calendar#AM_PM}{@link Calendar#AM} to {@link Calendar#PM}0 - AM, 1 - PM
+ * + *

The following are calendar-specific fields and their values to be supported. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Calendar TypeFieldValueDescription
{@code "gregory"}{@link Calendar#ERA}0{@link java.util.GregorianCalendar#BC} (BCE)
1{@link java.util.GregorianCalendar#AD} (CE)
{@code "buddhist"}{@link Calendar#ERA}0BC (BCE)
1B.E. (Buddhist Era)
{@code "japanese"}{@link Calendar#ERA}0Seireki (Before Meiji)
1Meiji
2Taisho
3Showa
4Heisei
{@link Calendar#YEAR}1the first year in each era. It should be returned when a long + * style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is + * specified. See also the + * Year representation in {@code SimpleDateFormat}.
+ * + *

Calendar field value names for {@code "gregory"} must be consistent with + * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}. + * + *

Time zone names are supported by {@link TimeZoneNameProvider}. + * + * @author Masayoshi Okutsu + * @since 1.8 + * @see CalendarDataProvider + * @see Locale#getUnicodeLocaleType(String) + */ +public abstract class CalendarNameProvider extends LocaleServiceProvider { + /** + * Sole constructor. (For invocation by subclass constructors, typically + * implicit.) + */ + protected CalendarNameProvider() { + } + + /** + * Returns the string representation (display name) of the calendar + * field value in the given style and + * locale. If no string representation is + * applicable, null is returned. + * + *

{@code field} is a {@code Calendar} field index, such as {@link + * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and + * {@link Calendar#DST_OFFSET}, are not supported by this + * method. {@code null} must be returned if any time zone fields are + * specified. + * + *

{@code value} is the numeric representation of the {@code field} value. + * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid + * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY} + * (inclusive). + * + *

{@code style} gives the style of the string representation. It is one + * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), + * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} + * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}. + * + *

For example, the following call will return {@code "Sunday"}. + *

+     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
+     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
+     * 
+ * + * @param calendarType + * the calendar type. (Any calendar type given by {@code locale} + * is ignored.) + * @param field + * the {@code Calendar} field index, + * such as {@link Calendar#DAY_OF_WEEK} + * @param value + * the value of the {@code Calendar field}, + * such as {@link Calendar#MONDAY} + * @param style + * the string representation style: one of {@link + * Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), + * {@link Calendar#SHORT_STANDALONE}, {@link + * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or + * {@link Calendar#LONG_STANDALONE} + * @param locale + * the desired locale + * @return the string representation of the {@code field value}, or {@code + * null} if the string representation is not applicable or + * the given calendar type is unknown + * @throws IllegalArgumentException + * if {@code field} or {@code style} is invalid + * @throws NullPointerException if {@code locale} is {@code null} + * @see TimeZoneNameProvider + * @see java.util.Calendar#get(int) + * @see java.util.Calendar#getDisplayName(int, int, Locale) + */ + public abstract String getDisplayName(String calendarType, + int field, int value, + int style, Locale locale); + + /** + * Returns a {@code Map} containing all string representations (display + * names) of the {@code Calendar} {@code field} in the given {@code style} + * and {@code locale} and their corresponding field values. + * + *

{@code field} is a {@code Calendar} field index, such as {@link + * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and + * {@link Calendar#DST_OFFSET}, are not supported by this + * method. {@code null} must be returned if any time zone fields are specified. + * + *

{@code style} gives the style of the string representation. It must be + * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link + * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link + * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link + * Calendar#LONG_STANDALONE}. + * + *

For example, the following call will return a {@code Map} containing + * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link + * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY}, + * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on. + *

+     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
+     * 
+ * + * @param calendarType + * the calendar type. (Any calendar type given by {@code locale} + * is ignored.) + * @param field + * the calendar field for which the display names are returned + * @param style + * the style applied to the display names; one of + * {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} + * ({@link Calendar#SHORT SHORT}), {@link + * Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} + * ({@link Calendar#LONG LONG}), or {@link + * Calendar#LONG_STANDALONE}. + * @param locale + * the desired locale + * @return a {@code Map} containing all display names of {@code field} in + * {@code style} and {@code locale} and their {@code field} values, + * or {@code null} if no display names are defined for {@code field} + * @throws NullPointerException + * if {@code locale} is {@code null} + * @see Calendar#getDisplayNames(int, int, Locale) + */ + public abstract Map getDisplayNames(String calendarType, + int field, int style, + Locale locale); +} diff --git a/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java index 9afb8b04b01..a68a8ba956d 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java @@ -38,6 +38,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -135,6 +136,10 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { return getLocaleServiceProvider(CalendarDataProvider.class); } + @Override + public CalendarNameProvider getCalendarNameProvider() { + return getLocaleServiceProvider(CalendarNameProvider.class); + } @Override public LocaleResources getLocaleResources(Locale locale) { diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java index 48ef4712ee5..16d08b3cbe3 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java @@ -24,10 +24,9 @@ */ package sun.util.locale.provider; +import java.util.Calendar; import static java.util.Calendar.*; -import java.util.HashMap; import java.util.Locale; -import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.spi.CalendarDataProvider; @@ -58,115 +57,11 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av return getIntData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK, locale); } - @Override - public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - String name = null; - String key = getKey(calendarType, field, style); - if (key != null) { - ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); - if (rb.containsKey(key)) { - String[] strings = rb.getStringArray(key); - if (strings.length > 0) { - if (field == DAY_OF_WEEK || field == YEAR) { - --value; - } - name = strings[value]; - // If name is empty in standalone, try its `format' style. - if (name.length() == 0 - && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) { - name = getDisplayName(calendarType, field, value, - style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT, - locale); - } - } - } - } - return name; - } - - @Override - public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - Map names; - if (style == ALL_STYLES) { - names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); - if (field != AM_PM) { - for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) { - names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); - } - } - } else { - // specific style - names = getDisplayNamesImpl(calendarType, field, style, locale); - } - return names.isEmpty() ? null : names; - } - - private Map getDisplayNamesImpl(String calendarType, int field, - int style, Locale locale) { - String key = getKey(calendarType, field, style); - Map map = new HashMap<>(); - if (key != null) { - ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); - if (rb.containsKey(key)) { - String[] strings = rb.getStringArray(key); - if (field == YEAR) { - if (strings.length > 0) { - map.put(strings[0], 1); - } - } else { - int base = (field == DAY_OF_WEEK) ? 1 : 0; - for (int i = 0; i < strings.length; i++) { - String name = strings[i]; - // Ignore any empty string (some standalone month names - // are not defined) - if (name.length() == 0) { - continue; - } - map.put(name, base + i); - } - } - } - } - return map; - } - @Override public Locale[] getAvailableLocales() { return LocaleProviderAdapter.toLocaleArray(langtags); } - @Override - public boolean isSupportedLocale(Locale locale) { - if (Locale.ROOT.equals(locale)) { - return true; - } - String calendarType = null; - if (locale.hasExtensions()) { - calendarType = locale.getUnicodeLocaleType("ca"); - locale = locale.stripExtensions(); - } - - if (calendarType != null) { - switch (calendarType) { - case "buddhist": - case "japanese": - case "gregory": - break; - default: - // Unknown calendar type - return false; - } - } - if (langtags.contains(locale.toLanguageTag())) { - return true; - } - if (type == LocaleProviderAdapter.Type.JRE) { - String oldname = locale.toString().replace('_', '-'); - return langtags.contains(oldname); - } - return false; - } - @Override public Set getAvailableLanguageTags() { return langtags; @@ -178,49 +73,6 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av String firstday = rb.getString(key); return Integer.parseInt(firstday); } - // Note that the base bundle of CLDR doesn't have the Calendar week parameters. return 0; } - - private String getKey(String type, int field, int style) { - boolean standalone = (style & 0x8000) != 0; - style &= ~0x8000; - - if ("gregory".equals(type)) { - type = null; - } - - StringBuilder key = new StringBuilder(); - switch (field) { - case ERA: - if (type != null) { - key.append(type).append('.'); - } - if (style == SHORT) { - key.append("short."); - } - key.append("Eras"); - break; - - case YEAR: - key.append(type).append(".FirstYear"); - break; - - case MONTH: - if (standalone) { - key.append("standalone."); - } - key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); - break; - - case DAY_OF_WEEK: - key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); - break; - - case AM_PM: - key.append("AmPmMarkers"); - break; - } - return key.length() > 0 ? key.toString() : null; - } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java index 274be8e8787..e86e27234bd 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java @@ -25,9 +25,12 @@ package sun.util.locale.provider; +import java.util.Calendar; +import static java.util.Calendar.*; import java.util.Locale; import java.util.Map; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; /** * {@code CalendarDataUtility} is a utility class for calling the @@ -44,16 +47,32 @@ public class CalendarDataUtility { private CalendarDataUtility() { } - public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) { + public static int retrieveFirstDayOfWeek(Locale locale) { LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE, + locale, FIRST_DAY_OF_WEEK); + return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY; + } + + public static int retrieveMinimalDaysInFirstWeek(Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE, + locale, MINIMAL_DAYS_IN_FIRST_WEEK); + return (value != null && (value >= 1 && value <= 7)) ? value : 1; + } + + public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, id, field, value, style); } public static Map retrieveFieldValueNames(String id, int field, int style, Locale locale) { LocaleServiceProviderPool pool = - LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, id, field, style); } @@ -62,13 +81,13 @@ public class CalendarDataUtility { * implementation. */ private static class CalendarFieldValueNameGetter - implements LocaleServiceProviderPool.LocalizedObjectGetter { private static final CalendarFieldValueNameGetter INSTANCE = new CalendarFieldValueNameGetter(); @Override - public String getObject(CalendarDataProvider calendarDataProvider, + public String getObject(CalendarNameProvider calendarNameProvider, Locale locale, String requestID, // calendarType Object... params) { @@ -76,7 +95,7 @@ public class CalendarDataUtility { int field = (int) params[0]; int value = (int) params[1]; int style = (int) params[2]; - return calendarDataProvider.getDisplayName(requestID, field, value, style, locale); + return calendarNameProvider.getDisplayName(requestID, field, value, style, locale); } } @@ -85,20 +104,47 @@ public class CalendarDataUtility { * implementation. */ private static class CalendarFieldValueNamesMapGetter - implements LocaleServiceProviderPool.LocalizedObjectGetter> { private static final CalendarFieldValueNamesMapGetter INSTANCE = new CalendarFieldValueNamesMapGetter(); @Override - public Map getObject(CalendarDataProvider calendarDataProvider, + public Map getObject(CalendarNameProvider calendarNameProvider, Locale locale, String requestID, // calendarType Object... params) { assert params.length == 2; int field = (int) params[0]; int style = (int) params[1]; - return calendarDataProvider.getDisplayNames(requestID, field, style, locale); + return calendarNameProvider.getDisplayNames(requestID, field, style, locale); + } + } + + private static class CalendarWeekParameterGetter + implements LocaleServiceProviderPool.LocalizedObjectGetter { + private static final CalendarWeekParameterGetter INSTANCE = + new CalendarWeekParameterGetter(); + + @Override + public Integer getObject(CalendarDataProvider calendarDataProvider, + Locale locale, + String requestID, // resource key + Object... params) { + assert params.length == 0; + int value; + switch (requestID) { + case FIRST_DAY_OF_WEEK: + value = calendarDataProvider.getFirstDayOfWeek(locale); + break; + case MINIMAL_DAYS_IN_FIRST_WEEK: + value = calendarDataProvider.getMinimalDaysInFirstWeek(locale); + break; + default: + throw new InternalError("invalid requestID: " + requestID); + } + return (value != 0) ? value : null; } } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java new file mode 100644 index 00000000000..1f262a8445a --- /dev/null +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.util.locale.provider; + +import static java.util.Calendar.*; +import java.util.Comparator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.TreeMap; +import java.util.spi.CalendarNameProvider; + +/** + * Concrete implementation of the {@link java.util.spi.CalendarDataProvider + * CalendarDataProvider} class for the JRE LocaleProviderAdapter. + * + * @author Masayoshi Okutsu + * @author Naoto Sato + */ +public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags { + private final LocaleProviderAdapter.Type type; + private final Set langtags; + + public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set langtags) { + this.type = type; + this.langtags = langtags; + } + + @Override + public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + String name = null; + String key = getKey(calendarType, field, style); + if (key != null) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); + if (rb.containsKey(key)) { + String[] strings = rb.getStringArray(key); + if (strings.length > 0) { + if (field == DAY_OF_WEEK || field == YEAR) { + --value; + } + name = strings[value]; + // If name is empty in standalone, try its `format' style. + if (name.length() == 0 + && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) { + name = getDisplayName(calendarType, field, value, + style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT, + locale); + } + } + } + } + return name; + } + + @Override + public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { + Map names; + if (style == ALL_STYLES) { + names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); + if (field != AM_PM) { + for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) { + names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); + } + } + } else { + // specific style + names = getDisplayNamesImpl(calendarType, field, style, locale); + } + return names.isEmpty() ? null : names; + } + + private Map getDisplayNamesImpl(String calendarType, int field, + int style, Locale locale) { + String key = getKey(calendarType, field, style); + Map map = new TreeMap<>(LengthBasedComparator.INSTANCE); + if (key != null) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); + if (rb.containsKey(key)) { + String[] strings = rb.getStringArray(key); + if (field == YEAR) { + if (strings.length > 0) { + map.put(strings[0], 1); + } + } else { + int base = (field == DAY_OF_WEEK) ? 1 : 0; + for (int i = 0; i < strings.length; i++) { + String name = strings[i]; + // Ignore any empty string (some standalone month names + // are not defined) + if (name.length() == 0) { + continue; + } + map.put(name, base + i); + } + } + } + } + return map; + } + + /** + * Comparator implementation for TreeMap which iterates keys from longest + * to shortest. + */ + private static class LengthBasedComparator implements Comparator { + private static final LengthBasedComparator INSTANCE = new LengthBasedComparator(); + + private LengthBasedComparator() { + } + + @Override + public int compare(String o1, String o2) { + int n = o2.length() - o1.length(); + return (n == 0) ? o1.compareTo(o2) : n; + } + } + + @Override + public Locale[] getAvailableLocales() { + return LocaleProviderAdapter.toLocaleArray(langtags); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + if (Locale.ROOT.equals(locale)) { + return true; + } + String calendarType = null; + if (locale.hasExtensions()) { + calendarType = locale.getUnicodeLocaleType("ca"); + locale = locale.stripExtensions(); + } + + if (calendarType != null) { + switch (calendarType) { + case "buddhist": + case "japanese": + case "gregory": + break; + default: + // Unknown calendar type + return false; + } + } + if (langtags.contains(locale.toLanguageTag())) { + return true; + } + if (type == LocaleProviderAdapter.Type.JRE) { + String oldname = locale.toString().replace('_', '-'); + return langtags.contains(oldname); + } + return false; + } + + @Override + public Set getAvailableLanguageTags() { + return langtags; + } + + private int getIntData(String key, Locale locale) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getCalendarData(locale); + if (rb.containsKey(key)) { + String firstday = rb.getString(key); + return Integer.parseInt(firstday); + } + // Note that the base bundle of CLDR doesn't have the Calendar week parameters. + return 0; + } + + private String getKey(String type, int field, int style) { + boolean standalone = (style & 0x8000) != 0; + style &= ~0x8000; + + if ("gregory".equals(type)) { + type = null; + } + + StringBuilder key = new StringBuilder(); + switch (field) { + case ERA: + if (type != null) { + key.append(type).append('.'); + } + if (style == SHORT) { + key.append("short."); + } + key.append("Eras"); + break; + + case YEAR: + key.append(type).append(".FirstYear"); + break; + + case MONTH: + if (standalone) { + key.append("standalone."); + } + key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); + break; + + case DAY_OF_WEEK: + key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); + break; + + case AM_PM: + key.append("AmPmMarkers"); + break; + } + return key.length() > 0 ? key.toString() : null; + } +} diff --git a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java index e6b3d9e1e32..9f86f7a35ab 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java @@ -41,6 +41,7 @@ import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -101,6 +102,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { return (P) getTimeZoneNameProvider(); case "CalendarDataProvider": return (P) getCalendarDataProvider(); + case "CalendarNameProvider": + return (P) getCalendarNameProvider(); default: throw new InternalError("should not come down here"); } @@ -117,6 +120,7 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { private volatile LocaleNameProvider localeNameProvider = null; private volatile TimeZoneNameProvider timeZoneNameProvider = null; private volatile CalendarDataProvider calendarDataProvider = null; + private volatile CalendarNameProvider calendarNameProvider = null; /* * Getter methods for java.text.spi.* providers @@ -252,11 +256,9 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { @Override public CalendarDataProvider getCalendarDataProvider() { if (calendarDataProvider == null) { - Set set = new HashSet<>(); - set.addAll(getLanguageTagSet("FormatData")); - set.addAll(getLanguageTagSet("CalendarData")); - CalendarDataProvider provider = new CalendarDataProviderImpl(getAdapterType(), - set); + CalendarDataProvider provider; + provider = new CalendarDataProviderImpl(getAdapterType(), + getLanguageTagSet("CalendarData")); synchronized (this) { if (calendarDataProvider == null) { calendarDataProvider = provider; @@ -266,6 +268,21 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { return calendarDataProvider; } + @Override + public CalendarNameProvider getCalendarNameProvider() { + if (calendarNameProvider == null) { + CalendarNameProvider provider; + provider = new CalendarNameProviderImpl(getAdapterType(), + getLanguageTagSet("FormatData")); + synchronized (this) { + if (calendarNameProvider == null) { + calendarNameProvider = provider; + } + } + } + return calendarNameProvider; + } + @Override public LocaleResources getLocaleResources(Locale locale) { LocaleResources lr = localeResourcesMap.get(locale); diff --git a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index 7db4560f81c..17f5c0999d5 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -38,6 +38,7 @@ import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -387,6 +388,14 @@ public abstract class LocaleProviderAdapter { */ public abstract CalendarDataProvider getCalendarDataProvider(); + /** + * Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no + * CalendarNameProvider is available. + * + * @return a CalendarNameProvider + */ + public abstract CalendarNameProvider getCalendarNameProvider(); + public abstract LocaleResources getLocaleResources(Locale locale); public abstract LocaleData getLocaleData(); diff --git a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java index cb4f9aee7de..1d380e38ac2 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java @@ -28,11 +28,29 @@ package sun.util.locale.provider; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.text.*; -import java.text.spi.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.spi.*; +import java.text.BreakIterator; +import java.text.Collator; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.spi.BreakIteratorProvider; +import java.text.spi.CollatorProvider; +import java.text.spi.DateFormatProvider; +import java.text.spi.DateFormatSymbolsProvider; +import java.text.spi.DecimalFormatSymbolsProvider; +import java.text.spi.NumberFormatProvider; +import java.util.Locale; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; +import java.util.spi.CurrencyNameProvider; +import java.util.spi.LocaleNameProvider; +import java.util.spi.LocaleServiceProvider; +import java.util.spi.TimeZoneNameProvider; /** * LocaleProviderAdapter implementation for the installed SPI implementations. @@ -411,12 +429,39 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { assert cdp != null; return cdp.getMinimalDaysInFirstWeek(locale); } + } + + static class CalendarNameProviderDelegate extends CalendarNameProvider + implements Delegate { + private ConcurrentMap map = new ConcurrentHashMap<>(); + + @Override + public void addImpl(CalendarNameProvider impl) { + for (Locale l : impl.getAvailableLocales()) { + map.put(l, impl); + } + } + + @Override + public CalendarNameProvider getImpl(Locale locale) { + return SPILocaleProviderAdapter.getImpl(map, locale); + } + + @Override + public Locale[] getAvailableLocales() { + return map.keySet().toArray(new Locale[0]); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return map.containsKey(locale); + } @Override public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - CalendarDataProvider cdp = getImpl(locale); + CalendarNameProvider cdp = getImpl(locale); assert cdp != null; return cdp.getDisplayName(calendarType, field, value, style, locale); } @@ -425,7 +470,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - CalendarDataProvider cdp = getImpl(locale); + CalendarNameProvider cdp = getImpl(locale); assert cdp != null; return cdp.getDisplayNames(calendarType, field, style, locale); } diff --git a/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java index 53875abea44..a5666f6b6a9 100644 --- a/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java +++ b/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java @@ -25,7 +25,12 @@ package sun.util.locale.provider; import java.lang.ref.SoftReference; -import java.text.*; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; import java.text.spi.DateFormatProvider; import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; @@ -34,12 +39,13 @@ import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.ResourceBundle.Control; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; /** * LocaleProviderdapter implementation for the Windows locale data. @@ -88,7 +94,7 @@ public class HostLocaleProviderAdapterImpl { private static final Set supportedLocaleSet; static { - Set tmpSet = new HashSet(); + Set tmpSet = new HashSet<>(); if (initialize()) { // Assuming the default locales do not include any extensions, so // no stripping is needed here. @@ -258,7 +264,7 @@ public class HostLocaleProviderAdapterImpl { if (ref == null || (patterns = ref.get()) == null) { String langtag = locale.toLanguageTag(); - patterns = new AtomicReferenceArray(NF_MAX+1); + patterns = new AtomicReferenceArray<>(NF_MAX+1); for (int i = 0; i <= NF_MAX; i++) { patterns.compareAndSet(i, null, getNumberPattern(i, langtag)); } @@ -329,18 +335,6 @@ public class HostLocaleProviderAdapterImpl { return isSupportedCalendarLocale(locale); } - @Override - public String getDisplayName(String calType, int field, int value, - int style, Locale locale) { - return null; - } - - @Override - public Map getDisplayNames(String calType, - int field, int style, Locale locale) { - return null; - } - @Override public int getFirstDayOfWeek(Locale locale) { int first = getCalendarDataValue( @@ -360,6 +354,32 @@ public class HostLocaleProviderAdapterImpl { }; } + public static CalendarNameProvider getCalendarNameProvider() { + return new CalendarNameProvider() { + @Override + public Locale[] getAvailableLocales() { + return getSupportedCalendarLocales(); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return isSupportedCalendarLocale(locale); + } + + @Override + public String getDisplayName(String calType, int field, int value, + int style, Locale locale) { + return null; + } + + @Override + public Map getDisplayNames(String calType, + int field, int style, Locale locale) { + return null; + } + }; + } + private static String convertDateTimePattern(String winPattern) { String ret = winPattern.replaceAll("dddd", "EEEE"); ret = ret.replaceAll("ddd", "EEE"); diff --git a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java index 5ee6b4d8306..1ef683b300f 100644 --- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java +++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java @@ -36,17 +36,11 @@ import com.bar.CalendarDataProviderImpl; * * Test strategy: * com.bar.CalendarDataProviderImpl supports only ja_JP_kids locale. It returns - * month names only in full-width digits, followed by "gatsu" in Hiragana if - * it's a long style, and also returns unusual week parameter values, WEDNESDAY - * - first day of week, 7 - minimal days in the first week. The standalone - * styles are used because DateFormatSymbols has precedence for the format - * styles. + * unusual week parameter values, WEDNESDAY - first day of week, 7 - minimal + * days in the first week. * * A Calendar instance created with ja_JP_kids should use the week parameters - * provided by com.bar.CalendarDataProviderImpl. Calendar.getDisplayName(s) - * should be called with kids to get the month names provided by - * com.bar.CalendarDataProviderImpl. Other display names should be the same as - * what a Calendar constructed with ja_JP returns. + * provided by com.bar.CalendarDataProviderImpl. */ public class CalendarDataProviderTest { @@ -62,45 +56,6 @@ public class CalendarDataProviderTest { // check the week parameters checkResult("firstDayOfWeek", kcal.getFirstDayOfWeek(), WEDNESDAY); checkResult("minimalDaysInFirstWeek", kcal.getMinimalDaysInFirstWeek(), 7); - - // check month names and week day names - Map mapAllStyles = new HashMap<>(); - for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) { - // Check month names provided by com.bar.CalendarDataProviderImpl - Map map = new HashMap<>(); - for (int month = JANUARY; month <= DECEMBER; month++) { - kcal.set(DAY_OF_MONTH, 1); - kcal.set(MONTH, month); - kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions... - kcal.getTimeInMillis(); - String name = kcal.getDisplayName(MONTH, style, kids); - checkResult("Month name", - name, - CalendarDataProviderImpl.toMonthName(kcal.get(MONTH) + 1, style)); - - // Builds the map with name to its integer value. - map.put(name, kcal.get(MONTH)); - } - checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map", - kcal.getDisplayNames(MONTH, style, kids), map); - mapAllStyles.putAll(map); - if (style == LONG_STANDALONE) { - checkResult("Short and long month names map", - kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles); - } - - // Check week names: kcal and jcal should return the same names and maps. - for (int dow = SUNDAY; dow <= SATURDAY; dow++) { - kcal.set(DAY_OF_WEEK, dow); - jcal.setTimeInMillis(kcal.getTimeInMillis()); - String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids); - checkResult("Day of week name", name, - jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN)); - } - checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids), - jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN)); - } - } private void checkResult(String msg, T got, T expected) { diff --git a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh index 2e8f7924c00..c4d1f90d76c 100644 --- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 7058206 +# @bug 7058207 8000986 # @summary CalendarDataProvider tests # @run shell ExecTest.sh bar CalendarDataProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java new file mode 100644 index 00000000000..4910f1596fe --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * + */ + +import java.text.*; +import java.util.*; +import static java.util.Calendar.*; +import sun.util.locale.provider.*; +import sun.util.resources.*; +import com.bar.CalendarNameProviderImpl; + +/** + * Test case for CalendarNameProvider. + * + * Test strategy: + * com.bar.CalendarNameProviderImpl supports only ja_JP_kids locale. It returns + * month names only in full-width digits, followed by "gatsu" in Hiragana if + * it's a long style. The standalone styles are used because DateFormatSymbols + * has precedence for the format styles. + * + * Calendar.getDisplayName(s) should be called with kids to get the month + * names provided by com.bar.CalendarNameProviderImpl. Other display names + * should be the same as what a Calendar constructed with ja_JP returns. + */ +public class CalendarNameProviderTest { + + public static void main(String[] s) { + new CalendarNameProviderTest().test(); + } + + void test() { + Locale kids = new Locale("ja", "JP", "kids"); // test provider's supported locale + Calendar kcal = Calendar.getInstance(kids); + Calendar jcal = Calendar.getInstance(Locale.JAPAN); + + // check month names and week day names + Map mapAllStyles = new HashMap<>(); + for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) { + // Check month names provided by com.bar.CalendarNameProviderImpl + Map map = new HashMap<>(); + for (int month = JANUARY; month <= DECEMBER; month++) { + kcal.set(DAY_OF_MONTH, 1); + kcal.set(MONTH, month); + kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions... + kcal.getTimeInMillis(); + String name = kcal.getDisplayName(MONTH, style, kids); + checkResult("Month name", + name, + CalendarNameProviderImpl.toMonthName(kcal.get(MONTH) + 1, style)); + + // Builds the map with name to its integer value. + map.put(name, kcal.get(MONTH)); + } + checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map", + kcal.getDisplayNames(MONTH, style, kids), map); + mapAllStyles.putAll(map); + if (style == LONG_STANDALONE) { + checkResult("Short and long month names map", + kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles); + } + + // Check week names: kcal and jcal should return the same names and maps. + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + kcal.set(DAY_OF_WEEK, dow); + jcal.setTimeInMillis(kcal.getTimeInMillis()); + String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids); + checkResult("Day of week name", name, + jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN)); + } + checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids), + jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN)); + } + + } + + private void checkResult(String msg, T got, T expected) { + if (!expected.equals(got)) { + String s = String.format("%s: got='%s', expected='%s'", msg, got, expected); + throw new RuntimeException(s); + } + } +} diff --git a/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh new file mode 100644 index 00000000000..a772292b936 --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh @@ -0,0 +1,27 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8000986 +# @summary CalendarNameProvider tests +# @run shell ExecTest.sh bar CalendarNameProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/GenericTest.java b/jdk/test/java/util/PluggableLocale/GenericTest.java index 29a49fb3f26..8be74cdca91 100644 --- a/jdk/test/java/util/PluggableLocale/GenericTest.java +++ b/jdk/test/java/util/PluggableLocale/GenericTest.java @@ -42,6 +42,7 @@ public class GenericTest { com.bar.LocaleNameProviderImpl localeNP = new com.bar.LocaleNameProviderImpl(); com.bar.TimeZoneNameProviderImpl tzNP = new com.bar.TimeZoneNameProviderImpl(); com.bar.CalendarDataProviderImpl calDataP = new com.bar.CalendarDataProviderImpl(); + com.bar.CalendarNameProviderImpl calNameP = new com.bar.CalendarNameProviderImpl(); public static void main(String[] s) { new GenericTest(); @@ -73,6 +74,7 @@ public class GenericTest { expected.addAll(Arrays.asList(localeNP.getAvailableLocales())); expected.addAll(Arrays.asList(tzNP.getAvailableLocales())); expected.addAll(Arrays.asList(calDataP.getAvailableLocales())); + expected.addAll(Arrays.asList(calNameP.getAvailableLocales())); if (!result.equals(expected)) { throw new RuntimeException("Locale.getAvailableLocales() does not return the union of locales: diff=" + getDiff(result, expected)); diff --git a/jdk/test/java/util/PluggableLocale/barprovider.jar b/jdk/test/java/util/PluggableLocale/barprovider.jar index 901b2b2b7f6..7f621fa3c67 100644 Binary files a/jdk/test/java/util/PluggableLocale/barprovider.jar and b/jdk/test/java/util/PluggableLocale/barprovider.jar differ diff --git a/jdk/test/java/util/PluggableLocale/fooprovider.jar b/jdk/test/java/util/PluggableLocale/fooprovider.jar index 125dbe17756..cfc6616019c 100644 Binary files a/jdk/test/java/util/PluggableLocale/fooprovider.jar and b/jdk/test/java/util/PluggableLocale/fooprovider.jar differ diff --git a/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java index 7a8fff62a83..274d468df08 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java +++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java @@ -47,66 +47,8 @@ public class CalendarDataProviderImpl extends CalendarDataProvider { return 7; } - @Override - public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - if (calendarType == null || locale == null) { - throw new NullPointerException(); - } - if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { - throw new IllegalArgumentException("locale is not one of available locales: "+ locale); - } - if (field != MONTH) { - return null; - } - return toMonthName(value + 1, style); - } - - @Override - public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - if (calendarType == null || locale == null) { - throw new NullPointerException(); - } - if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { - throw new IllegalArgumentException("locale is not one of available locales: " + locale); - } - if (field != MONTH) { - return null; - } - Map map = new HashMap<>(); - if (style == LONG_STANDALONE) { - style = LONG; - } else if (style == SHORT_STANDALONE) { - style = SHORT; - } - for (int month = JANUARY; month <= DECEMBER; month++) { - if (style == ALL_STYLES || style == LONG) { - map.put(toMonthName(month + 1, LONG), month); - } - if (style == ALL_STYLES || style == SHORT) { - map.put(toMonthName(month + 1, SHORT), month); - } - } - return map; - } - @Override public Locale[] getAvailableLocales() { return avail.clone(); } - - // month is 1-based. - public static String toMonthName(int month, int style) { - StringBuilder sb = new StringBuilder(); - if (month >= 10) { - sb.append((char)(FULLWIDTH_ZERO + 1)); - sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10))); - } else { - sb.appendCodePoint((char)(FULLWIDTH_ZERO + month)); - } - if (style == SHORT || style == SHORT_STANDALONE) { - return sb.toString(); // full-width digit(s) - } - sb.append("\u304c\u3064"); // + "gatsu" in Hiragana - return sb.toString(); - } } diff --git a/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java new file mode 100644 index 00000000000..d93ba36229b --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.bar; + +import com.foobar.Utils; +import java.util.Arrays; +import static java.util.Calendar.*; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.spi.CalendarNameProvider; + +public class CalendarNameProviderImpl extends CalendarNameProvider { + static final char FULLWIDTH_ZERO = '\uff10'; + static final Locale[] avail = { + new Locale("ja", "JP", "kids"), + }; + + @Override + public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + if (calendarType == null || locale == null) { + throw new NullPointerException(); + } + if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { + throw new IllegalArgumentException("locale is not one of available locales: "+ locale); + } + if (field != MONTH) { + return null; + } + return toMonthName(value + 1, style); + } + + @Override + public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { + if (calendarType == null || locale == null) { + throw new NullPointerException(); + } + if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { + throw new IllegalArgumentException("locale is not one of available locales: " + locale); + } + if (field != MONTH) { + return null; + } + Map map = new HashMap<>(); + if (style == LONG_STANDALONE) { + style = LONG; + } else if (style == SHORT_STANDALONE) { + style = SHORT; + } + for (int month = JANUARY; month <= DECEMBER; month++) { + if (style == ALL_STYLES || style == LONG) { + map.put(toMonthName(month + 1, LONG), month); + } + if (style == ALL_STYLES || style == SHORT) { + map.put(toMonthName(month + 1, SHORT), month); + } + } + return map; + } + + @Override + public Locale[] getAvailableLocales() { + return avail.clone(); + } + + // month is 1-based. + public static String toMonthName(int month, int style) { + StringBuilder sb = new StringBuilder(); + if (month >= 10) { + sb.append((char)(FULLWIDTH_ZERO + 1)); + sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10))); + } else { + sb.appendCodePoint((char)(FULLWIDTH_ZERO + month)); + } + if (style == SHORT || style == SHORT_STANDALONE) { + return sb.toString(); // full-width digit(s) + } + sb.append("\u304c\u3064"); // + "gatsu" in Hiragana + return sb.toString(); + } +} diff --git a/jdk/test/java/util/PluggableLocale/providersrc/Makefile b/jdk/test/java/util/PluggableLocale/providersrc/Makefile index 3c550992691..2af60665a36 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/Makefile +++ b/jdk/test/java/util/PluggableLocale/providersrc/Makefile @@ -20,7 +20,8 @@ BARSERVICES = \ java.util.spi.CurrencyNameProvider \ java.util.spi.TimeZoneNameProvider \ java.util.spi.LocaleNameProvider \ - java.util.spi.CalendarDataProvider + java.util.spi.CalendarDataProvider \ + java.util.spi.CalendarNameProvider FOOFILES_JAVA = \ BreakIteratorProviderImpl.java \ @@ -39,6 +40,7 @@ BARFILES_JAVA = \ TimeZoneNameProviderImpl.java \ LocaleNameProviderImpl.java \ CalendarDataProviderImpl.java \ + CalendarNameProviderImpl.java \ Utils.java BARFILES_PROPERTIES = \ @@ -68,3 +70,8 @@ $(DESTDIR)/barprovider.jar: $(BARSERVICES) $(BARFILES_JAVA) $(BARFILES_PROPERTIE cp $(BARFILES_PROPERTIES) $(BARDIR)/com/bar rm -f $(DESTDIR)/barprovider.jar $(BINDIR)/jar cvf $(DESTDIR)/barprovider.jar -C $(BARDIR) . + +clean: + rm -rf $(BARDIR) $(FOODIR) + +.PHONY: all clean diff --git a/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider new file mode 100644 index 00000000000..dd6f8ec9909 --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider @@ -0,0 +1,7 @@ +# +# +# +# fully-qualified name of the java.util.spi.CalendarNameProvider +# implementation class +# +com.bar.CalendarNameProviderImpl