1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2012-2016, Google, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.text; 11 12 import java.io.InvalidObjectException; 13 import java.text.AttributedCharacterIterator; 14 import java.text.Format; 15 import java.util.ArrayList; 16 import java.util.Arrays; 17 import java.util.Collection; 18 import java.util.Iterator; 19 import java.util.Locale; 20 import java.util.regex.Pattern; 21 22 import ohos.global.icu.impl.FormattedStringBuilder; 23 import ohos.global.icu.impl.FormattedValueStringBuilderImpl; 24 import ohos.global.icu.impl.FormattedValueStringBuilderImpl.SpanFieldPlaceholder; 25 import ohos.global.icu.impl.ICUCache; 26 import ohos.global.icu.impl.ICUData; 27 import ohos.global.icu.impl.ICUResourceBundle; 28 import ohos.global.icu.impl.SimpleCache; 29 import ohos.global.icu.impl.SimpleFormatterImpl; 30 import ohos.global.icu.impl.SimpleFormatterImpl.IterInternal; 31 import ohos.global.icu.impl.Utility; 32 import ohos.global.icu.util.ULocale; 33 import ohos.global.icu.util.UResourceBundle; 34 35 /** 36 * Immutable class for formatting a list, using data from CLDR (or supplied 37 * separately). The class is not subclassable. 38 * 39 * @author Mark Davis 40 */ 41 final public class ListFormatter { 42 // Compiled SimpleFormatter patterns. 43 private final String start; 44 private final String middle; 45 private final ULocale locale; 46 47 private interface PatternHandler { getTwoPattern(String text)48 public String getTwoPattern(String text); getEndPattern(String text)49 public String getEndPattern(String text); 50 } 51 private final PatternHandler patternHandler; 52 53 /** 54 * Indicates the style of Listformatter 55 * TODO(ICU-20888): Remove this in ICU 68. 56 * @deprecated This API is ICU internal only. 57 * @hide exposed on OHOS 58 * @hide draft / provisional / internal are hidden on OHOS 59 */ 60 @Deprecated 61 public enum Style { 62 /** 63 * Standard, conjunction style. 64 * @deprecated This API is ICU internal only. 65 * @hide draft / provisional / internal are hidden on OHOS 66 */ 67 @Deprecated 68 STANDARD("standard"), 69 /** 70 * Disjunction style. 71 * @deprecated This API is ICU internal only. 72 * @hide draft / provisional / internal are hidden on OHOS 73 */ 74 @Deprecated 75 OR("or"), 76 /** 77 * Style for full units 78 * @deprecated This API is ICU internal only. 79 * @hide draft / provisional / internal are hidden on OHOS 80 */ 81 @Deprecated 82 UNIT("unit"), 83 /** 84 * Style for units in abbrevated form 85 * @deprecated This API is ICU internal only. 86 * @hide draft / provisional / internal are hidden on OHOS 87 */ 88 @Deprecated 89 UNIT_SHORT("unit-short"), 90 /** 91 * Style for units in narrow form 92 * @deprecated This API is ICU internal only. 93 * @hide draft / provisional / internal are hidden on OHOS 94 */ 95 @Deprecated 96 UNIT_NARROW("unit-narrow"); 97 98 private final String name; 99 Style(String name)100 Style(String name) { 101 this.name = name; 102 } 103 /** 104 * @deprecated This API is ICU internal only. 105 * @hide draft / provisional / internal are hidden on OHOS 106 */ 107 @Deprecated getName()108 public String getName() { 109 return name; 110 } 111 112 } 113 114 /** 115 * Type of meaning expressed by the list. 116 * 117 * @hide exposed on OHOS 118 * @hide draft / provisional / internal are hidden on OHOS 119 */ 120 public enum Type { 121 /** 122 * Conjunction formatting, e.g. "Alice, Bob, Charlie, and Delta". 123 * 124 * @hide draft / provisional / internal are hidden on OHOS 125 */ 126 AND, 127 128 /** 129 * Disjunction (or alternative, or simply one of) formatting, e.g. 130 * "Alice, Bob, Charlie, or Delta". 131 * 132 * @hide draft / provisional / internal are hidden on OHOS 133 */ 134 OR, 135 136 /** 137 * Formatting of a list of values with units, e.g. "5 pounds, 12 ounces". 138 * 139 * @hide draft / provisional / internal are hidden on OHOS 140 */ 141 UNITS 142 }; 143 144 /** 145 * Verbosity level of the list patterns. 146 * 147 * @hide exposed on OHOS 148 * @hide draft / provisional / internal are hidden on OHOS 149 */ 150 public enum Width { 151 /** 152 * Use list formatting with full words (no abbreviations) when possible. 153 * 154 * @hide draft / provisional / internal are hidden on OHOS 155 */ 156 WIDE, 157 158 /** 159 * Use list formatting of typical length. 160 * 161 * @hide draft / provisional / internal are hidden on OHOS 162 */ 163 SHORT, 164 165 /** 166 * Use list formatting of the shortest possible length. 167 * 168 * @hide draft / provisional / internal are hidden on OHOS 169 */ 170 NARROW, 171 }; 172 173 /** 174 * Class for span fields in FormattedList. 175 * 176 * @hide exposed on OHOS 177 * @hide draft / provisional / internal are hidden on OHOS 178 */ 179 public static final class SpanField extends UFormat.SpanField { 180 private static final long serialVersionUID = 3563544214705634403L; 181 182 /** 183 * The concrete field used for spans in FormattedList. 184 * 185 * Instances of LIST_SPAN should have an associated value, the index 186 * within the input list that is represented by the span. 187 * 188 * @hide draft / provisional / internal are hidden on OHOS 189 */ 190 public static final SpanField LIST_SPAN = new SpanField("list-span"); 191 SpanField(String name)192 private SpanField(String name) { 193 super(name); 194 } 195 196 /** 197 * serialization method resolve instances to the constant 198 * ListFormatter.SpanField values 199 * @deprecated This API is ICU internal only. 200 * @hide draft / provisional / internal are hidden on OHOS 201 */ 202 @Deprecated 203 @Override readResolve()204 protected Object readResolve() throws InvalidObjectException { 205 if (this.getName().equals(LIST_SPAN.getName())) 206 return LIST_SPAN; 207 208 throw new InvalidObjectException("An invalid object."); 209 } 210 } 211 212 /** 213 * Field selectors for format fields defined by ListFormatter. 214 * @hide exposed on OHOS 215 * @hide draft / provisional / internal are hidden on OHOS 216 */ 217 public static final class Field extends Format.Field { 218 private static final long serialVersionUID = -8071145668708265437L; 219 220 /** 221 * The literal text in the result which came from the resources. 222 * @hide draft / provisional / internal are hidden on OHOS 223 */ 224 public static Field LITERAL = new Field("literal"); 225 226 /** 227 * The element text in the result which came from the input strings. 228 * @hide draft / provisional / internal are hidden on OHOS 229 */ 230 public static Field ELEMENT = new Field("element"); 231 Field(String name)232 private Field(String name) { 233 super(name); 234 } 235 236 /** 237 * Serizalization method resolve instances to the constant Field values 238 * 239 * @hide draft / provisional / internal are hidden on OHOS 240 */ 241 @Override readResolve()242 protected Object readResolve() throws InvalidObjectException { 243 if (this.getName().equals(LITERAL.getName())) 244 return LITERAL; 245 if (this.getName().equals(ELEMENT.getName())) 246 return ELEMENT; 247 248 throw new InvalidObjectException("An invalid object."); 249 } 250 } 251 252 /** 253 * An immutable class containing the result of a list formatting operation. 254 * 255 * Instances of this class are immutable and thread-safe. 256 * 257 * Not intended for public subclassing. 258 * 259 * @hide exposed on OHOS 260 * @hide draft / provisional / internal are hidden on OHOS 261 */ 262 public static final class FormattedList implements FormattedValue { 263 private final FormattedStringBuilder string; 264 FormattedList(FormattedStringBuilder string)265 FormattedList(FormattedStringBuilder string) { 266 this.string = string; 267 } 268 269 /** 270 * {@inheritDoc} 271 * @hide draft / provisional / internal are hidden on OHOS 272 */ 273 @Override toString()274 public String toString() { 275 return string.toString(); 276 } 277 278 /** 279 * {@inheritDoc} 280 * @hide draft / provisional / internal are hidden on OHOS 281 */ 282 @Override length()283 public int length() { 284 return string.length(); 285 } 286 287 /** 288 * {@inheritDoc} 289 * @hide draft / provisional / internal are hidden on OHOS 290 */ 291 @Override charAt(int index)292 public char charAt(int index) { 293 return string.charAt(index); 294 } 295 296 /** 297 * {@inheritDoc} 298 * @hide draft / provisional / internal are hidden on OHOS 299 */ 300 @Override subSequence(int start, int end)301 public CharSequence subSequence(int start, int end) { 302 return string.subString(start, end); 303 } 304 305 /** 306 * {@inheritDoc} 307 * @hide draft / provisional / internal are hidden on OHOS 308 */ 309 @Override appendTo(A appendable)310 public <A extends Appendable> A appendTo(A appendable) { 311 return Utility.appendTo(string, appendable); 312 } 313 314 /** 315 * {@inheritDoc} 316 * @hide draft / provisional / internal are hidden on OHOS 317 */ 318 @Override nextPosition(ConstrainedFieldPosition cfpos)319 public boolean nextPosition(ConstrainedFieldPosition cfpos) { 320 return FormattedValueStringBuilderImpl.nextPosition(string, cfpos, null); 321 } 322 323 /** 324 * {@inheritDoc} 325 * @hide draft / provisional / internal are hidden on OHOS 326 */ 327 @Override toCharacterIterator()328 public AttributedCharacterIterator toCharacterIterator() { 329 return FormattedValueStringBuilderImpl.toCharacterIterator(string, null); 330 } 331 } 332 333 /** 334 * <b>Internal:</b> Create a ListFormatter from component strings, 335 * with definitions as in LDML. 336 * 337 * @param two 338 * string for two items, containing {0} for the first, and {1} 339 * for the second. 340 * @param start 341 * string for the start of a list items, containing {0} for the 342 * first, and {1} for the rest. 343 * @param middle 344 * string for the start of a list items, containing {0} for the 345 * first part of the list, and {1} for the rest of the list. 346 * @param end 347 * string for the end of a list items, containing {0} for the 348 * first part of the list, and {1} for the last item. 349 * @deprecated This API is ICU internal only. 350 * @hide draft / provisional / internal are hidden on OHOS 351 */ 352 @Deprecated ListFormatter(String two, String start, String middle, String end)353 public ListFormatter(String two, String start, String middle, String end) { 354 this( 355 compilePattern(two, new StringBuilder()), 356 compilePattern(start, new StringBuilder()), 357 compilePattern(middle, new StringBuilder()), 358 compilePattern(end, new StringBuilder()), 359 null); 360 } 361 ListFormatter(String two, String start, String middle, String end, ULocale locale)362 private ListFormatter(String two, String start, String middle, String end, ULocale locale) { 363 this.start = start; 364 this.middle = middle; 365 this.locale = locale; 366 this.patternHandler = createPatternHandler(two, end); 367 } 368 compilePattern(String pattern, StringBuilder sb)369 private static String compilePattern(String pattern, StringBuilder sb) { 370 return SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, sb, 2, 2); 371 } 372 373 /** 374 * Create a list formatter that is appropriate for a locale. 375 * 376 * @param locale 377 * the locale in question. 378 * @return ListFormatter 379 * @hide draft / provisional / internal are hidden on OHOS 380 */ getInstance(ULocale locale, Type type, Width width)381 public static ListFormatter getInstance(ULocale locale, Type type, Width width) { 382 String styleName = typeWidthToStyleString(type, width); 383 if (styleName == null) { 384 throw new IllegalArgumentException("Invalid list format type/width"); 385 } 386 return cache.get(locale, styleName); 387 } 388 389 /** 390 * Create a list formatter that is appropriate for a locale. 391 * 392 * @param locale 393 * the locale in question. 394 * @return ListFormatter 395 * @hide draft / provisional / internal are hidden on OHOS 396 */ getInstance(Locale locale, Type type, Width width)397 public static ListFormatter getInstance(Locale locale, Type type, Width width) { 398 return getInstance(ULocale.forLocale(locale), type, width); 399 } 400 401 /** 402 * Create a list formatter that is appropriate for a locale and style. 403 * 404 * @param locale the locale in question. 405 * @param style the style 406 * @return ListFormatter 407 * @deprecated This API is ICU internal only. 408 * @hide draft / provisional / internal are hidden on OHOS 409 */ 410 @Deprecated getInstance(ULocale locale, Style style)411 public static ListFormatter getInstance(ULocale locale, Style style) { 412 return cache.get(locale, style.getName()); 413 } 414 415 /** 416 * Create a list formatter that is appropriate for a locale. 417 * 418 * @param locale 419 * the locale in question. 420 * @return ListFormatter 421 */ getInstance(ULocale locale)422 public static ListFormatter getInstance(ULocale locale) { 423 return getInstance(locale, Style.STANDARD); 424 } 425 426 /** 427 * Create a list formatter that is appropriate for a locale. 428 * 429 * @param locale 430 * the locale in question. 431 * @return ListFormatter 432 */ getInstance(Locale locale)433 public static ListFormatter getInstance(Locale locale) { 434 return getInstance(ULocale.forLocale(locale), Style.STANDARD); 435 } 436 437 /** 438 * Create a list formatter that is appropriate for the default FORMAT locale. 439 * 440 * @return ListFormatter 441 */ getInstance()442 public static ListFormatter getInstance() { 443 return getInstance(ULocale.getDefault(ULocale.Category.FORMAT)); 444 } 445 446 /** 447 * Format a list of objects. 448 * 449 * @param items 450 * items to format. The toString() method is called on each. 451 * @return items formatted into a string 452 */ format(Object... items)453 public String format(Object... items) { 454 return format(Arrays.asList(items)); 455 } 456 457 /** 458 * Format a collection of objects. The toString() method is called on each. 459 * 460 * @param items 461 * items to format. The toString() method is called on each. 462 * @return items formatted into a string 463 */ format(Collection<?> items)464 public String format(Collection<?> items) { 465 return formatImpl(items, false).toString(); 466 } 467 468 /** 469 * Format a list of objects to a FormattedList. You can access the offsets 470 * of each element from the FormattedList. 471 * 472 * @param items 473 * items to format. The toString() method is called on each. 474 * @return items formatted into a FormattedList 475 * @hide draft / provisional / internal are hidden on OHOS 476 */ formatToValue(Object... items)477 public FormattedList formatToValue(Object... items) { 478 return formatToValue(Arrays.asList(items)); 479 } 480 481 482 /** 483 * Format a collection of objects to a FormattedList. You can access the offsets 484 * of each element from the FormattedList. 485 * 486 * @param items 487 * items to format. The toString() method is called on each. 488 * @return items formatted into a FormattedList 489 * @hide draft / provisional / internal are hidden on OHOS 490 */ formatToValue(Collection<?> items)491 public FormattedList formatToValue(Collection<?> items) { 492 return formatImpl(items, true).toValue(); 493 } 494 495 // Formats a collection of objects and returns the formatted string plus the offset 496 // in the string where the index th element appears. index is zero based. If index is 497 // negative or greater than or equal to the size of items then this function returns -1 for 498 // the offset. formatImpl(Collection<?> items, boolean needsFields)499 FormattedListBuilder formatImpl(Collection<?> items, boolean needsFields) { 500 Iterator<?> it = items.iterator(); 501 int count = items.size(); 502 switch (count) { 503 case 0: 504 return new FormattedListBuilder("", needsFields); 505 case 1: 506 return new FormattedListBuilder(it.next(), needsFields); 507 case 2: 508 Object first = it.next(); 509 Object second = it.next(); 510 return new FormattedListBuilder(first, needsFields) 511 .append(patternHandler.getTwoPattern(String.valueOf(second)), second, 1); 512 } 513 FormattedListBuilder builder = new FormattedListBuilder(it.next(), needsFields); 514 builder.append(start, it.next(), 1); 515 for (int idx = 2; idx < count - 1; ++idx) { 516 builder.append(middle, it.next(), idx); 517 } 518 Object last = it.next(); 519 return builder.append(patternHandler.getEndPattern(String.valueOf(last)), last, count - 1); 520 } 521 522 // A static handler just returns the pattern without considering the input text. 523 private class StaticHandler implements PatternHandler { StaticHandler(String two, String end)524 StaticHandler(String two, String end) { 525 twoPattern = two; 526 endPattern = end; 527 } 528 529 @Override getTwoPattern(String text)530 public String getTwoPattern(String text) { return twoPattern; } 531 532 @Override getEndPattern(String text)533 public String getEndPattern(String text) { return endPattern; } 534 535 private final String twoPattern; 536 private final String endPattern; 537 } 538 539 // A contextual handler returns one of the two patterns depending on whether the text matched the regexp. 540 private class ContextualHandler implements PatternHandler { ContextualHandler(Pattern regexp, String thenTwo, String elseTwo, String thenEnd, String elseEnd)541 ContextualHandler(Pattern regexp, String thenTwo, String elseTwo, String thenEnd, String elseEnd) { 542 this.regexp = regexp; 543 thenTwoPattern = thenTwo; 544 elseTwoPattern = elseTwo; 545 thenEndPattern = thenEnd; 546 elseEndPattern = elseEnd; 547 } 548 549 @Override getTwoPattern(String text)550 public String getTwoPattern(String text) { 551 if(regexp.matcher(text).matches()) { 552 return thenTwoPattern; 553 } else { 554 return elseTwoPattern; 555 } 556 } 557 558 @Override getEndPattern(String text)559 public String getEndPattern(String text) { 560 if(regexp.matcher(text).matches()) { 561 return thenEndPattern; 562 } else { 563 return elseEndPattern; 564 } 565 } 566 567 private final Pattern regexp; 568 private final String thenTwoPattern; 569 private final String elseTwoPattern; 570 private final String thenEndPattern; 571 private final String elseEndPattern; 572 573 } 574 575 // Pattern in the ICU Data which might be replaced y by e. 576 private static final String compiledY = compilePattern("{0} y {1}", new StringBuilder()); 577 578 // The new pattern to replace y to e 579 private static final String compiledE = compilePattern("{0} e {1}", new StringBuilder()); 580 581 // Pattern in the ICU Data which might be replaced o by u. 582 private static final String compiledO = compilePattern("{0} o {1}", new StringBuilder()); 583 584 // The new pattern to replace u to o 585 private static final String compiledU = compilePattern("{0} u {1}", new StringBuilder()); 586 587 // Condition to change to e. 588 // Starts with "hi" or "i" but not with "hie" nor "hia"a 589 private static final Pattern changeToE = Pattern.compile("(i.*|hi|hi[^ae].*)", Pattern.CASE_INSENSITIVE); 590 591 // Condition to change to u. 592 // Starts with "o", "ho", and "8". Also "11" by itself. 593 private static final Pattern changeToU = Pattern.compile("((o|ho|8).*|11)", Pattern.CASE_INSENSITIVE); 594 595 // Pattern in the ICU Data which might need to add a DASH after VAV. 596 private static final String compiledVav = compilePattern("{0} \u05D5{1}", new StringBuilder()); 597 598 // Pattern to add a DASH after VAV. 599 private static final String compiledVavDash = compilePattern("{0} \u05D5-{1}", new StringBuilder()); 600 601 // Condition to change to VAV follow by a dash. 602 // Starts with non Hebrew letter. 603 private static final Pattern changeToVavDash = Pattern.compile("^[\\P{InHebrew}].*$"); 604 605 // A factory function to create function based on locale 606 // Handle specal case of Spanish and Hebrew createPatternHandler(String two, String end)607 private PatternHandler createPatternHandler(String two, String end) { 608 if (this.locale != null) { 609 String language = this.locale.getLanguage(); 610 if (language.equals("es")) { 611 boolean twoIsY = two.equals(compiledY); 612 boolean endIsY = end.equals(compiledY); 613 if (twoIsY || endIsY) { 614 return new ContextualHandler( 615 changeToE, twoIsY ? compiledE : two, two, endIsY ? compiledE : end, end); 616 } 617 boolean twoIsO = two.equals(compiledO); 618 boolean endIsO = end.equals(compiledO); 619 if (twoIsO || endIsO) { 620 return new ContextualHandler( 621 changeToU, twoIsO ? compiledU : two, two, endIsO ? compiledU : end, end); 622 } 623 } else if (language.equals("he") || language.equals("iw")) { 624 boolean twoIsVav = two.equals(compiledVav); 625 boolean endIsVav = end.equals(compiledVav); 626 if (twoIsVav || endIsVav) { 627 return new ContextualHandler(changeToVavDash, 628 twoIsVav ? compiledVavDash : two, two, endIsVav ? compiledVavDash : end, end); 629 } 630 } 631 } 632 return new StaticHandler(two, end); 633 } 634 635 /** 636 * Returns the pattern to use for a particular item count. 637 * @param count the item count. 638 * @return the pattern with {0}, {1}, {2}, etc. For English, 639 * getPatternForNumItems(3) == "{0}, {1}, and {2}" 640 * @throws IllegalArgumentException when count is 0 or negative. 641 */ getPatternForNumItems(int count)642 public String getPatternForNumItems(int count) { 643 if (count <= 0) { 644 throw new IllegalArgumentException("count must be > 0"); 645 } 646 ArrayList<String> list = new ArrayList<>(); 647 for (int i = 0; i < count; i++) { 648 list.add(String.format("{%d}", i)); 649 } 650 return format(list); 651 } 652 653 /** 654 * Returns the locale of this object. 655 * @deprecated This API is ICU internal only. 656 * @hide draft / provisional / internal are hidden on OHOS 657 */ 658 @Deprecated getLocale()659 public ULocale getLocale() { 660 return locale; 661 } 662 663 // Builds a formatted list 664 static class FormattedListBuilder { 665 private FormattedStringBuilder string; 666 boolean needsFields; 667 668 // Start is the first object in the list; If needsFields is true, enable the slightly 669 // more expensive code path that records offsets of each element. FormattedListBuilder(Object start, boolean needsFields)670 public FormattedListBuilder(Object start, boolean needsFields) { 671 string = new FormattedStringBuilder(); 672 this.needsFields = needsFields; 673 string.setAppendableField(Field.LITERAL); 674 appendElement(start, 0); 675 } 676 677 // Appends additional object. pattern is a template indicating where the new object gets 678 // added in relation to the rest of the list. {0} represents the rest of the list; {1} 679 // represents the new object in pattern. next is the object to be added. position is the 680 // index of the next object in the list of inputs. append(String compiledPattern, Object next, int position)681 public FormattedListBuilder append(String compiledPattern, Object next, int position) { 682 assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 2; 683 string.setAppendIndex(0); 684 long state = 0; 685 while (true) { 686 state = IterInternal.step(state, compiledPattern, string); 687 if (state == IterInternal.DONE) { 688 break; 689 } 690 int argIndex = IterInternal.getArgIndex(state); 691 if (argIndex == 0) { 692 string.setAppendIndex(string.length()); 693 } else { 694 appendElement(next, position); 695 } 696 } 697 return this; 698 } 699 appendElement(Object element, int position)700 private void appendElement(Object element, int position) { 701 if (needsFields) { 702 SpanFieldPlaceholder field = new SpanFieldPlaceholder(); 703 field.spanField = SpanField.LIST_SPAN; 704 field.normalField = Field.ELEMENT; 705 field.value = position; 706 string.append(element.toString(), field); 707 } else { 708 string.append(element.toString(), null); 709 } 710 } 711 appendTo(Appendable appendable)712 public void appendTo(Appendable appendable) { 713 Utility.appendTo(string, appendable); 714 } 715 getOffset(int fieldPositionFoundIndex)716 public int getOffset(int fieldPositionFoundIndex) { 717 return FormattedValueStringBuilderImpl.findSpan(string, fieldPositionFoundIndex); 718 } 719 720 @Override toString()721 public String toString() { 722 return string.toString(); 723 } 724 toValue()725 public FormattedList toValue() { 726 return new FormattedList(string); 727 } 728 } 729 730 private static class Cache { 731 private final ICUCache<String, ListFormatter> cache = 732 new SimpleCache<>(); 733 get(ULocale locale, String style)734 public ListFormatter get(ULocale locale, String style) { 735 String key = String.format("%s:%s", locale.toString(), style); 736 ListFormatter result = cache.get(key); 737 if (result == null) { 738 result = load(locale, style); 739 cache.put(key, result); 740 } 741 return result; 742 } 743 load(ULocale ulocale, String style)744 private static ListFormatter load(ULocale ulocale, String style) { 745 ICUResourceBundle r = (ICUResourceBundle)UResourceBundle. 746 getBundleInstance(ICUData.ICU_BASE_NAME, ulocale); 747 StringBuilder sb = new StringBuilder(); 748 return new ListFormatter( 749 compilePattern(r.getWithFallback("listPattern/" + style + "/2").getString(), sb), 750 compilePattern(r.getWithFallback("listPattern/" + style + "/start").getString(), sb), 751 compilePattern(r.getWithFallback("listPattern/" + style + "/middle").getString(), sb), 752 compilePattern(r.getWithFallback("listPattern/" + style + "/end").getString(), sb), 753 ulocale); 754 } 755 } 756 757 static Cache cache = new Cache(); 758 typeWidthToStyleString(Type type, Width width)759 static String typeWidthToStyleString(Type type, Width width) { 760 switch (type) { 761 case AND: 762 switch (width) { 763 case WIDE: 764 return "standard"; 765 case SHORT: 766 return "standard-short"; 767 case NARROW: 768 return "standard-narrow"; 769 } 770 break; 771 772 case OR: 773 switch (width) { 774 case WIDE: 775 return "or"; 776 case SHORT: 777 return "or-short"; 778 case NARROW: 779 return "or-narrow"; 780 } 781 break; 782 783 case UNITS: 784 switch (width) { 785 case WIDE: 786 return "unit"; 787 case SHORT: 788 return "unit-short"; 789 case NARROW: 790 return "unit-narrow"; 791 } 792 } 793 794 return null; 795 } 796 } 797