62 --value; |
62 --value; |
63 } |
63 } |
64 name = strings[value]; |
64 name = strings[value]; |
65 // If name is empty in standalone, try its `format' style. |
65 // If name is empty in standalone, try its `format' style. |
66 if (name.length() == 0 |
66 if (name.length() == 0 |
67 && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) { |
67 && (style == SHORT_STANDALONE || style == LONG_STANDALONE |
|
68 || style == NARROW_STANDALONE)) { |
68 name = getDisplayName(calendarType, field, value, |
69 name = getDisplayName(calendarType, field, value, |
69 style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT, |
70 getBaseStyle(style), |
70 locale); |
71 locale); |
71 } |
72 } |
72 } |
73 } |
73 } |
74 } |
74 } |
75 } |
75 return name; |
76 return name; |
76 } |
77 } |
77 |
78 |
|
79 private static int[] REST_OF_STYLES = { |
|
80 SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE, |
|
81 NARROW_FORMAT, NARROW_STANDALONE |
|
82 }; |
78 @Override |
83 @Override |
79 public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) { |
84 public Map<String, Integer> getDisplayNames(String calendarType, int field, int style, Locale locale) { |
80 Map<String, Integer> names; |
85 Map<String, Integer> names; |
81 if (style == ALL_STYLES) { |
86 if (style == ALL_STYLES) { |
82 names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); |
87 names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); |
83 if (field != AM_PM) { |
88 for (int st : REST_OF_STYLES) { |
84 for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) { |
89 names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); |
85 names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); |
|
86 } |
|
87 } |
90 } |
88 } else { |
91 } else { |
89 // specific style |
92 // specific style |
90 names = getDisplayNamesImpl(calendarType, field, style, locale); |
93 names = getDisplayNamesImpl(calendarType, field, style, locale); |
91 } |
94 } |
92 return names.isEmpty() ? null : names; |
95 return names.isEmpty() ? null : names; |
93 } |
96 } |
94 |
97 |
95 private Map<String, Integer> getDisplayNamesImpl(String calendarType, int field, |
98 private Map<String, Integer> getDisplayNamesImpl(String calendarType, int field, |
96 int style, Locale locale) { |
99 int style, Locale locale) { |
97 String key = getKey(calendarType, field, style); |
100 String key = getResourceKey(calendarType, field, style); |
98 Map<String, Integer> map = new TreeMap<>(LengthBasedComparator.INSTANCE); |
101 Map<String, Integer> map = new TreeMap<>(LengthBasedComparator.INSTANCE); |
99 if (key != null) { |
102 if (key != null) { |
100 ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); |
103 ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); |
101 if (rb.containsKey(key)) { |
104 if (rb.containsKey(key)) { |
102 String[] strings = rb.getStringArray(key); |
105 String[] strings = rb.getStringArray(key); |
103 if (field == YEAR) { |
106 if (!hasDuplicates(strings)) { |
104 if (strings.length > 0) { |
107 if (field == YEAR) { |
105 map.put(strings[0], 1); |
108 if (strings.length > 0) { |
106 } |
109 map.put(strings[0], 1); |
107 } else { |
|
108 int base = (field == DAY_OF_WEEK) ? 1 : 0; |
|
109 for (int i = 0; i < strings.length; i++) { |
|
110 String name = strings[i]; |
|
111 // Ignore any empty string (some standalone month names |
|
112 // are not defined) |
|
113 if (name.length() == 0) { |
|
114 continue; |
|
115 } |
110 } |
116 map.put(name, base + i); |
111 } else { |
|
112 int base = (field == DAY_OF_WEEK) ? 1 : 0; |
|
113 for (int i = 0; i < strings.length; i++) { |
|
114 String name = strings[i]; |
|
115 // Ignore any empty string (some standalone month names |
|
116 // are not defined) |
|
117 if (name.length() == 0) { |
|
118 continue; |
|
119 } |
|
120 map.put(name, base + i); |
|
121 } |
117 } |
122 } |
118 } |
123 } |
119 } |
124 } |
120 } |
125 } |
121 return map; |
126 return map; |
|
127 } |
|
128 |
|
129 private int getBaseStyle(int style) { |
|
130 return style & ~(SHORT_STANDALONE - SHORT_FORMAT); |
122 } |
131 } |
123 |
132 |
124 /** |
133 /** |
125 * Comparator implementation for TreeMap which iterates keys from longest |
134 * Comparator implementation for TreeMap which iterates keys from longest |
126 * to shortest. |
135 * to shortest. |
178 @Override |
187 @Override |
179 public Set<String> getAvailableLanguageTags() { |
188 public Set<String> getAvailableLanguageTags() { |
180 return langtags; |
189 return langtags; |
181 } |
190 } |
182 |
191 |
183 private int getIntData(String key, Locale locale) { |
192 private boolean hasDuplicates(String[] strings) { |
184 ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getCalendarData(locale); |
193 int len = strings.length; |
185 if (rb.containsKey(key)) { |
194 for (int i = 0; i < len - 1; i++) { |
186 String firstday = rb.getString(key); |
195 String a = strings[i]; |
187 return Integer.parseInt(firstday); |
196 if (a != null) { |
188 } |
197 for (int j = i + 1; j < len; j++) { |
189 // Note that the base bundle of CLDR doesn't have the Calendar week parameters. |
198 if (a.equals(strings[j])) { |
190 return 0; |
199 return true; |
191 } |
200 } |
192 |
201 } |
193 private String getKey(String type, int field, int style) { |
202 } |
194 boolean standalone = (style & 0x8000) != 0; |
203 } |
195 style &= ~0x8000; |
204 return false; |
|
205 } |
|
206 |
|
207 private String getResourceKey(String type, int field, int style) { |
|
208 int baseStyle = getBaseStyle(style); |
|
209 boolean isStandalone = (style != baseStyle); |
196 |
210 |
197 if ("gregory".equals(type)) { |
211 if ("gregory".equals(type)) { |
198 type = null; |
212 type = null; |
199 } |
213 } |
200 |
214 boolean isNarrow = (baseStyle == NARROW_FORMAT); |
201 StringBuilder key = new StringBuilder(); |
215 StringBuilder key = new StringBuilder(); |
202 switch (field) { |
216 switch (field) { |
203 case ERA: |
217 case ERA: |
204 if (type != null) { |
218 if (type != null) { |
205 key.append(type).append('.'); |
219 key.append(type).append('.'); |
206 } |
220 } |
207 if (style == SHORT) { |
221 if (isNarrow) { |
208 key.append("short."); |
222 key.append("narrow."); |
|
223 } else { |
|
224 // JRE and CLDR use different resource key conventions |
|
225 // due to historical reasons. (JRE DateFormatSymbols.getEras returns |
|
226 // abbreviations while other getShort*() return abbreviations.) |
|
227 if (this.type == LocaleProviderAdapter.Type.JRE) { |
|
228 if (baseStyle == SHORT) { |
|
229 key.append("short."); |
|
230 } |
|
231 } else { // CLDR |
|
232 if (baseStyle == LONG) { |
|
233 key.append("long."); |
|
234 } |
|
235 } |
209 } |
236 } |
210 key.append("Eras"); |
237 key.append("Eras"); |
211 break; |
238 break; |
212 |
239 |
213 case YEAR: |
240 case YEAR: |
214 key.append(type).append(".FirstYear"); |
241 if (!isNarrow) { |
|
242 key.append(type).append(".FirstYear"); |
|
243 } |
215 break; |
244 break; |
216 |
245 |
217 case MONTH: |
246 case MONTH: |
218 if (standalone) { |
247 if (isStandalone) { |
219 key.append("standalone."); |
248 key.append("standalone."); |
220 } |
249 } |
221 key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); |
250 key.append("Month").append(toStyleName(baseStyle)); |
222 break; |
251 break; |
223 |
252 |
224 case DAY_OF_WEEK: |
253 case DAY_OF_WEEK: |
225 key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); |
254 // support standalone narrow day names |
|
255 if (isStandalone && isNarrow) { |
|
256 key.append("standalone."); |
|
257 } |
|
258 key.append("Day").append(toStyleName(baseStyle)); |
226 break; |
259 break; |
227 |
260 |
228 case AM_PM: |
261 case AM_PM: |
|
262 if (isNarrow) { |
|
263 key.append("narrow."); |
|
264 } |
229 key.append("AmPmMarkers"); |
265 key.append("AmPmMarkers"); |
230 break; |
266 break; |
231 } |
267 } |
232 return key.length() > 0 ? key.toString() : null; |
268 return key.length() > 0 ? key.toString() : null; |
233 } |
269 } |
|
270 |
|
271 private String toStyleName(int baseStyle) { |
|
272 switch (baseStyle) { |
|
273 case SHORT: |
|
274 return "Abbreviations"; |
|
275 case NARROW_FORMAT: |
|
276 return "Narrows"; |
|
277 } |
|
278 return "Names"; |
|
279 } |
234 } |
280 } |