1 /*
2 * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package sun.util.locale.provider;
26
27 import static java.util.Calendar.*;
28 import java.util.Comparator;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.TreeMap;
33 import java.util.spi.CalendarNameProvider;
34 import sun.util.calendar.CalendarSystem;
35 import sun.util.calendar.Era;
36
37 /**
38 * Concrete implementation of the {@link java.util.spi.CalendarDataProvider
39 * CalendarDataProvider} class for the JRE LocaleProviderAdapter.
40 *
41 * @author Masayoshi Okutsu
42 * @author Naoto Sato
43 */
44 public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags {
45 private final LocaleProviderAdapter.Type type;
46 private final Set<String> langtags;
47
48 public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
49 this.type = type;
50 this.langtags = langtags;
51 }
52
53 @Override
54 public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
55 return getDisplayNameImpl(calendarType, field, value, style, locale, false);
56 }
57
58 public String getJavaTimeDisplayName(String calendarType, int field, int value, int style, Locale locale) {
59 return getDisplayNameImpl(calendarType, field, value, style, locale, true);
60 }
61
62 public String getDisplayNameImpl(String calendarType, int field, int value, int style, Locale locale, boolean javatime) {
63 String name = null;
64 String key = getResourceKey(calendarType, field, style, javatime);
65 if (key != null) {
66 LocaleResources lr = LocaleProviderAdapter.forType(type).getLocaleResources(locale);
67 String[] strings = javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
68 if (strings != null && strings.length > 0) {
69 if (field == DAY_OF_WEEK || field == YEAR) {
70 --value;
71 }
72 if (value < 0 || value > strings.length) {
73 return null;
74 } else if (value == strings.length) {
75 if (field == ERA && "japanese".equals(calendarType)) {
76 // get the supplemental era, if any, specified through
77 // the property "jdk.calendar.japanese.supplemental.era"
78 // which is always the last element.
79 Era[] jeras = CalendarSystem.forName("japanese").getEras();
80 if (jeras.length == value) {
81 Era supEra = jeras[value - 1]; // 0-based index
82 return style == LONG ?
83 supEra.getName() :
84 supEra.getAbbreviation();
85 }
86 }
87 return null;
88 }
89 name = strings[value];
90 // If name is empty in standalone, try its `format' style.
91 if (name.length() == 0
92 && (style == SHORT_STANDALONE || style == LONG_STANDALONE
93 || style == NARROW_STANDALONE)) {
94 name = getDisplayName(calendarType, field, value,
95 getBaseStyle(style),
96 locale);
97 }
98 }
99 }
100 return name;
101 }
102
103 private static int[] REST_OF_STYLES = {
104 SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE,
105 NARROW_FORMAT, NARROW_STANDALONE
106 };
107
108 @Override
141 map.put(strings[0], 1);
142 }
143 } else {
144 int base = (field == DAY_OF_WEEK) ? 1 : 0;
145 for (int i = 0; i < strings.length; i++) {
146 String name = strings[i];
147 // Ignore any empty string (some standalone month names
148 // are not defined)
149 if (name.length() == 0) {
150 continue;
151 }
152 map.put(name, base + i);
153 }
154 }
155 }
156 }
157 }
158 return map;
159 }
160
161 private int getBaseStyle(int style) {
162 return style & ~(SHORT_STANDALONE - SHORT_FORMAT);
163 }
164
165 /**
166 * Comparator implementation for TreeMap which iterates keys from longest
167 * to shortest.
168 */
169 private static class LengthBasedComparator implements Comparator<String> {
170 private static final LengthBasedComparator INSTANCE = new LengthBasedComparator();
171
172 private LengthBasedComparator() {
173 }
174
175 @Override
176 public int compare(String o1, String o2) {
177 int n = o2.length() - o1.length();
178 return (n == 0) ? o1.compareTo(o2) : n;
179 }
180 }
181
222 public Set<String> getAvailableLanguageTags() {
223 return langtags;
224 }
225
226 private boolean hasDuplicates(String[] strings) {
227 int len = strings.length;
228 for (int i = 0; i < len - 1; i++) {
229 String a = strings[i];
230 if (a != null) {
231 for (int j = i + 1; j < len; j++) {
232 if (a.equals(strings[j])) {
233 return true;
234 }
235 }
236 }
237 }
238 return false;
239 }
240
241 private String getResourceKey(String type, int field, int style, boolean javatime) {
242 int baseStyle = getBaseStyle(style);
243 boolean isStandalone = (style != baseStyle);
244
245 if ("gregory".equals(type)) {
246 type = null;
247 }
248 boolean isNarrow = (baseStyle == NARROW_FORMAT);
249 StringBuilder key = new StringBuilder();
250 // If javatime is true, use prefix "java.time.".
251 if (javatime) {
252 key.append("java.time.");
253 }
254 switch (field) {
255 case ERA:
256 if (type != null) {
257 key.append(type).append('.');
258 }
259 if (isNarrow) {
260 key.append("narrow.");
261 } else {
262 // JRE and CLDR use different resource key conventions
263 // due to historical reasons. (JRE DateFormatSymbols.getEras returns
264 // abbreviations while other getShort*() return abbreviations.)
265 if (this.type == LocaleProviderAdapter.Type.JRE) {
266 if (javatime) {
267 if (baseStyle == LONG) {
268 key.append("long.");
269 }
270 }
271 if (baseStyle == SHORT) {
272 key.append("short.");
273 }
274 } else { // this.type == LocaleProviderAdapter.Type.CLDR
275 if (baseStyle == LONG) {
276 key.append("long.");
277 }
278 }
279 }
280 key.append("Eras");
281 break;
282
283 case YEAR:
284 if (!isNarrow) {
285 key.append(type).append(".FirstYear");
297 break;
298
299 case DAY_OF_WEEK:
300 // support standalone narrow day names
301 if (isStandalone && isNarrow) {
302 key.append("standalone.");
303 }
304 key.append("Day").append(toStyleName(baseStyle));
305 break;
306
307 case AM_PM:
308 if (isNarrow) {
309 key.append("narrow.");
310 }
311 key.append("AmPmMarkers");
312 break;
313 }
314 return key.length() > 0 ? key.toString() : null;
315 }
316
317 private String toStyleName(int baseStyle) {
318 switch (baseStyle) {
319 case SHORT:
320 return "Abbreviations";
321 case NARROW_FORMAT:
322 return "Narrows";
323 }
324 return "Names";
325 }
326 }
|
1 /*
2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package sun.util.locale.provider;
26
27 import static java.util.Calendar.*;
28 import java.util.Comparator;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.TreeMap;
33 import java.util.spi.CalendarNameProvider;
34 import sun.util.calendar.CalendarSystem;
35 import sun.util.calendar.Era;
36
37 /**
38 * Concrete implementation of the {@link java.util.spi.CalendarNameProvider
39 * CalendarNameProvider} class for the JRE LocaleProviderAdapter.
40 *
41 * @author Masayoshi Okutsu
42 * @author Naoto Sato
43 */
44 public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags {
45 private final LocaleProviderAdapter.Type type;
46 private final Set<String> langtags;
47
48 public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
49 this.type = type;
50 this.langtags = langtags;
51 }
52
53 @Override
54 public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) {
55 return getDisplayNameImpl(calendarType, field, value, style, locale, false);
56 }
57
58 public String getJavaTimeDisplayName(String calendarType, int field, int value, int style, Locale locale) {
59 return getDisplayNameImpl(calendarType, field, value, style, locale, true);
60 }
61
62 public String getDisplayNameImpl(String calendarType, int field, int value, int style, Locale locale, boolean javatime) {
63 String name = null;
64 String key = getResourceKey(calendarType, field, style, javatime);
65 if (key != null) {
66 LocaleResources lr = LocaleProviderAdapter.forType(type).getLocaleResources(locale);
67 String[] strings = javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
68 if (strings != null && strings.length > 0) {
69 if (field == DAY_OF_WEEK || field == YEAR) {
70 --value;
71 }
72 if (value < 0) {
73 return null;
74 } else if (value >= strings.length) {
75 if (field == ERA && "japanese".equals(calendarType)) {
76 Era[] jeras = CalendarSystem.forName("japanese").getEras();
77 if (value <= jeras.length) {
78 // Localized era name could not be retrieved from this provider.
79 // This can occur either for NewEra or SupEra.
80 //
81 // If it's CLDR provider, try COMPAT first, which is guaranteed to have
82 // the name for NewEra.
83 if (type == LocaleProviderAdapter.Type.CLDR) {
84 lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
85 key = getResourceKeyFor(LocaleProviderAdapter.Type.JRE,
86 calendarType, field, style, javatime);
87 strings =
88 javatime ? lr.getJavaTimeNames(key) : lr.getCalendarNames(key);
89 }
90 if (strings == null || value >= strings.length) {
91 // Get the default name for SupEra
92 Era supEra = jeras[value - 1]; // 0-based index
93 if (javatime) {
94 return getBaseStyle(style) == NARROW_FORMAT ?
95 supEra.getAbbreviation() :
96 supEra.getName();
97 } else {
98 return (style & LONG) != 0 ?
99 supEra.getName() :
100 supEra.getAbbreviation();
101 }
102 }
103 } else {
104 return null;
105 }
106 } else {
107 return null;
108 }
109 }
110 name = strings[value];
111 // If name is empty in standalone, try its `format' style.
112 if (name.length() == 0
113 && (style == SHORT_STANDALONE || style == LONG_STANDALONE
114 || style == NARROW_STANDALONE)) {
115 name = getDisplayName(calendarType, field, value,
116 getBaseStyle(style),
117 locale);
118 }
119 }
120 }
121 return name;
122 }
123
124 private static int[] REST_OF_STYLES = {
125 SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE,
126 NARROW_FORMAT, NARROW_STANDALONE
127 };
128
129 @Override
162 map.put(strings[0], 1);
163 }
164 } else {
165 int base = (field == DAY_OF_WEEK) ? 1 : 0;
166 for (int i = 0; i < strings.length; i++) {
167 String name = strings[i];
168 // Ignore any empty string (some standalone month names
169 // are not defined)
170 if (name.length() == 0) {
171 continue;
172 }
173 map.put(name, base + i);
174 }
175 }
176 }
177 }
178 }
179 return map;
180 }
181
182 private static int getBaseStyle(int style) {
183 return style & ~(SHORT_STANDALONE - SHORT_FORMAT);
184 }
185
186 /**
187 * Comparator implementation for TreeMap which iterates keys from longest
188 * to shortest.
189 */
190 private static class LengthBasedComparator implements Comparator<String> {
191 private static final LengthBasedComparator INSTANCE = new LengthBasedComparator();
192
193 private LengthBasedComparator() {
194 }
195
196 @Override
197 public int compare(String o1, String o2) {
198 int n = o2.length() - o1.length();
199 return (n == 0) ? o1.compareTo(o2) : n;
200 }
201 }
202
243 public Set<String> getAvailableLanguageTags() {
244 return langtags;
245 }
246
247 private boolean hasDuplicates(String[] strings) {
248 int len = strings.length;
249 for (int i = 0; i < len - 1; i++) {
250 String a = strings[i];
251 if (a != null) {
252 for (int j = i + 1; j < len; j++) {
253 if (a.equals(strings[j])) {
254 return true;
255 }
256 }
257 }
258 }
259 return false;
260 }
261
262 private String getResourceKey(String type, int field, int style, boolean javatime) {
263 return getResourceKeyFor(this.type, type, field, style, javatime);
264 }
265
266 private static String getResourceKeyFor(LocaleProviderAdapter.Type adapterType,
267 String type, int field, int style, boolean javatime) {
268 int baseStyle = getBaseStyle(style);
269 boolean isStandalone = (style != baseStyle);
270
271 if ("gregory".equals(type)) {
272 type = null;
273 }
274 boolean isNarrow = (baseStyle == NARROW_FORMAT);
275 StringBuilder key = new StringBuilder();
276 // If javatime is true, use prefix "java.time.".
277 if (javatime) {
278 key.append("java.time.");
279 }
280 switch (field) {
281 case ERA:
282 if (type != null) {
283 key.append(type).append('.');
284 }
285 if (isNarrow) {
286 key.append("narrow.");
287 } else {
288 // JRE and CLDR use different resource key conventions
289 // due to historical reasons. (JRE DateFormatSymbols.getEras returns
290 // abbreviations while other getShort*() return abbreviations.)
291 if (adapterType == LocaleProviderAdapter.Type.JRE) {
292 if (javatime) {
293 if (baseStyle == LONG) {
294 key.append("long.");
295 }
296 }
297 if (baseStyle == SHORT) {
298 key.append("short.");
299 }
300 } else { // this.type == LocaleProviderAdapter.Type.CLDR
301 if (baseStyle == LONG) {
302 key.append("long.");
303 }
304 }
305 }
306 key.append("Eras");
307 break;
308
309 case YEAR:
310 if (!isNarrow) {
311 key.append(type).append(".FirstYear");
323 break;
324
325 case DAY_OF_WEEK:
326 // support standalone narrow day names
327 if (isStandalone && isNarrow) {
328 key.append("standalone.");
329 }
330 key.append("Day").append(toStyleName(baseStyle));
331 break;
332
333 case AM_PM:
334 if (isNarrow) {
335 key.append("narrow.");
336 }
337 key.append("AmPmMarkers");
338 break;
339 }
340 return key.length() > 0 ? key.toString() : null;
341 }
342
343 private static String toStyleName(int baseStyle) {
344 switch (baseStyle) {
345 case SHORT:
346 return "Abbreviations";
347 case NARROW_FORMAT:
348 return "Narrows";
349 }
350 return "Names";
351 }
352 }
|