269 if ("root".equals(id)) {
270 parentsMap = null;
271 }
272
273 for (CalendarType calendarType : CalendarType.values()) {
274 String calendarPrefix = calendarType.keyElementName();
275 // handle multiple inheritance for month and day names
276 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
277 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
278 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows");
279 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
280 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
281 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
282 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
283 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
284 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "abbreviated.AmPmMarkers");
285 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames");
286 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations");
287 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows");
288
289 adjustEraNames(myMap, calendarType);
290
291 handleDateTimeFormatPatterns(TIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "TimePatterns");
292 handleDateTimeFormatPatterns(DATE_PATTERN_KEYS, myMap, parentsMap, calendarType, "DatePatterns");
293 handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns");
294 }
295
296 // First, weed out any empty timezone or metazone names from myMap.
297 for (Iterator<String> it = myMap.keySet().iterator(); it.hasNext();) {
298 String key = it.next();
299 if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)
300 || key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) {
301 @SuppressWarnings("unchecked")
302 Map<String, String> nameMap = (Map<String, String>) myMap.get(key);
303 if (nameMap.isEmpty()) {
304 // Some zones have only exemplarCity, which become empty.
305 // Remove those from the map.
306 it.remove();
307 continue;
308 }
309 }
393 if (format != null) {
394 map.remove(formatMapKey);
395 map.put(key, format);
396 if (fillInElements(parents, formatMapKey, format)) {
397 map.remove(key);
398 }
399 }
400 String standaloneMapKey = key + "/stand-alone";
401 Object standalone = map.get(standaloneMapKey);
402 if (standalone != null) {
403 map.remove(standaloneMapKey);
404 String standaloneResourceKey = "standalone." + key;
405 map.put(standaloneResourceKey, standalone);
406 if (fillInElements(parents, standaloneMapKey, standalone)) {
407 map.remove(standaloneResourceKey);
408 }
409 }
410 }
411
412 /**
413 * Fills in any empty elements with its parent element. Returns true if the resulting array is
414 * identical to its parent array.
415 *
416 * @param parents
417 * @param key
418 * @param value
419 * @return true if the resulting array is identical to its parent array.
420 */
421 private boolean fillInElements(Map<String, Object> parents, String key, Object value) {
422 if (parents == null) {
423 return false;
424 }
425 if (value instanceof String[]) {
426 Object pvalue = parents.get(key);
427 if (pvalue != null && pvalue instanceof String[]) {
428 String[] strings = (String[]) value;
429 String[] pstrings = (String[]) pvalue;
430 for (int i = 0; i < strings.length; i++) {
431 if (strings[i] == null || strings[i].length() == 0) {
432 strings[i] = pstrings[i];
433 }
434 }
435 return Arrays.equals(strings, pstrings);
436 }
437 }
438 return false;
439 }
440
441 /*
442 * Adjusts String[] for era names because JRE's Calendars use different
443 * ERA value indexes in the Buddhist, Japanese Imperial, and Islamic calendars.
444 */
445 private void adjustEraNames(Map<String, Object> map, CalendarType type) {
446 String[][] eraNames = new String[ERA_KEYS.length][];
447 String[] realKeys = new String[ERA_KEYS.length];
448 int index = 0;
449 for (String key : ERA_KEYS) {
450 String realKey = type.keyElementName() + key;
451 String[] value = (String[]) map.get(realKey);
452 if (value != null) {
453 switch (type) {
454 case GREGORIAN:
455 break;
456
457 case JAPANESE:
458 {
459 String[] newValue = new String[value.length + 1];
460 String[] julianEras = (String[]) map.get(key);
461 if (julianEras != null && julianEras.length >= 2) {
462 newValue[0] = julianEras[1];
463 } else {
464 newValue[0] = "";
465 }
466 System.arraycopy(value, 0, newValue, 1, value.length);
467 value = newValue;
468
469 // fix up 'Reiwa' era, which can be missing in some locales
470 if (value[value.length - 1] == null) {
471 value[value.length - 1] = (key.startsWith("narrow.") ? "R" : "Reiwa");
472 }
|
269 if ("root".equals(id)) {
270 parentsMap = null;
271 }
272
273 for (CalendarType calendarType : CalendarType.values()) {
274 String calendarPrefix = calendarType.keyElementName();
275 // handle multiple inheritance for month and day names
276 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
277 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
278 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows");
279 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
280 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
281 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
282 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
283 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
284 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "abbreviated.AmPmMarkers");
285 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames");
286 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations");
287 handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows");
288
289 adjustEraNames(myMap, parentsMap, calendarType);
290
291 handleDateTimeFormatPatterns(TIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "TimePatterns");
292 handleDateTimeFormatPatterns(DATE_PATTERN_KEYS, myMap, parentsMap, calendarType, "DatePatterns");
293 handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns");
294 }
295
296 // First, weed out any empty timezone or metazone names from myMap.
297 for (Iterator<String> it = myMap.keySet().iterator(); it.hasNext();) {
298 String key = it.next();
299 if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)
300 || key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) {
301 @SuppressWarnings("unchecked")
302 Map<String, String> nameMap = (Map<String, String>) myMap.get(key);
303 if (nameMap.isEmpty()) {
304 // Some zones have only exemplarCity, which become empty.
305 // Remove those from the map.
306 it.remove();
307 continue;
308 }
309 }
393 if (format != null) {
394 map.remove(formatMapKey);
395 map.put(key, format);
396 if (fillInElements(parents, formatMapKey, format)) {
397 map.remove(key);
398 }
399 }
400 String standaloneMapKey = key + "/stand-alone";
401 Object standalone = map.get(standaloneMapKey);
402 if (standalone != null) {
403 map.remove(standaloneMapKey);
404 String standaloneResourceKey = "standalone." + key;
405 map.put(standaloneResourceKey, standalone);
406 if (fillInElements(parents, standaloneMapKey, standalone)) {
407 map.remove(standaloneResourceKey);
408 }
409 }
410 }
411
412 /**
413 * Fills in any empty elements with its parent element, falling back to
414 * aliased one if parent element is not found. Returns true if the resulting
415 * array is identical to its parent array.
416 *
417 * @param parents
418 * @param key
419 * @param value
420 * @return true if the resulting array is identical to its parent array.
421 */
422 private boolean fillInElements(Map<String, Object> parents, String key, Object value) {
423 if (parents == null) {
424 return false;
425 }
426 if (value instanceof String[]) {
427 Object pvalue = parents.getOrDefault(key, parents.get(CLDRConverter.aliases.get(key)));
428 if (pvalue != null && pvalue instanceof String[]) {
429 String[] strings = (String[]) value;
430 String[] pstrings = (String[]) pvalue;
431 for (int i = 0; i < strings.length; i++) {
432 if (strings[i] == null || strings[i].length() == 0) {
433 strings[i] = pstrings[i];
434 }
435 }
436 return Arrays.equals(strings, pstrings);
437 }
438 }
439 return false;
440 }
441
442 /*
443 * Adjusts String[] for era names because JRE's Calendars use different
444 * ERA value indexes in the Buddhist, Japanese Imperial, and Islamic calendars.
445 */
446 private void adjustEraNames(Map<String, Object> map, Map<String, Object> pMap, CalendarType type) {
447 String[][] eraNames = new String[ERA_KEYS.length][];
448 String[] realKeys = new String[ERA_KEYS.length];
449 int index = 0;
450 for (String key : ERA_KEYS) {
451 String realKey = type.keyElementName() + key;
452 String[] value = (String[]) map.get(realKey);
453 if (value != null) {
454 // first fill in missing elements from parents map.
455 fillInElements(pMap, realKey, value);
456
457 switch (type) {
458 case GREGORIAN:
459 break;
460
461 case JAPANESE:
462 {
463 String[] newValue = new String[value.length + 1];
464 String[] julianEras = (String[]) map.get(key);
465 if (julianEras != null && julianEras.length >= 2) {
466 newValue[0] = julianEras[1];
467 } else {
468 newValue[0] = "";
469 }
470 System.arraycopy(value, 0, newValue, 1, value.length);
471 value = newValue;
472
473 // fix up 'Reiwa' era, which can be missing in some locales
474 if (value[value.length - 1] == null) {
475 value[value.length - 1] = (key.startsWith("narrow.") ? "R" : "Reiwa");
476 }
|