1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 /* 3 ******************************************************************************* 4 * Copyright (C) 2012-2016, Google, International Business Machines Corporation and 5 * others. All Rights Reserved. 6 ******************************************************************************* 7 */ 8 package android.icu.text; 9 10 import java.util.ArrayList; 11 import java.util.Arrays; 12 import java.util.Collection; 13 import java.util.Iterator; 14 import java.util.Locale; 15 16 import android.icu.impl.ICUCache; 17 import android.icu.impl.ICUResourceBundle; 18 import android.icu.impl.SimpleCache; 19 import android.icu.impl.SimplePatternFormatter; 20 import android.icu.util.ULocale; 21 import android.icu.util.UResourceBundle; 22 23 /** 24 * Immutable class for formatting a list, using data from CLDR (or supplied 25 * separately). The class is not subclassable. 26 * 27 * @author Mark Davis 28 * @hide Only a subset of ICU is exposed in Android 29 */ 30 final public class ListFormatter { 31 // Compiled SimplePatternFormatter patterns. 32 private final String two; 33 private final String start; 34 private final String middle; 35 private final String end; 36 private final ULocale locale; 37 38 /** 39 * Indicates the style of Listformatter 40 * @deprecated This API is ICU internal only. 41 * @hide draft / provisional / internal are hidden on Android 42 */ 43 @Deprecated 44 public enum Style { 45 /** 46 * Standard style. 47 * @deprecated This API is ICU internal only. 48 * @hide draft / provisional / internal are hidden on Android 49 */ 50 @Deprecated 51 STANDARD("standard"), 52 /** 53 * Style for full durations 54 * @deprecated This API is ICU internal only. 55 * @hide draft / provisional / internal are hidden on Android 56 */ 57 @Deprecated 58 DURATION("unit"), 59 /** 60 * Style for durations in abbrevated form 61 * @deprecated This API is ICU internal only. 62 * @hide draft / provisional / internal are hidden on Android 63 */ 64 @Deprecated 65 DURATION_SHORT("unit-short"), 66 /** 67 * Style for durations in narrow form 68 * @deprecated This API is ICU internal only. 69 * @hide draft / provisional / internal are hidden on Android 70 */ 71 @Deprecated 72 DURATION_NARROW("unit-narrow"); 73 74 private final String name; 75 76 Style(String name) { 77 this.name = name; 78 } 79 /** 80 * @deprecated This API is ICU internal only. 81 * @hide draft / provisional / internal are hidden on Android 82 */ 83 @Deprecated 84 public String getName() { 85 return name; 86 } 87 88 } 89 90 /** 91 * <b>Internal:</b> Create a ListFormatter from component strings, 92 * with definitions as in LDML. 93 * 94 * @param two 95 * string for two items, containing {0} for the first, and {1} 96 * for the second. 97 * @param start 98 * string for the start of a list items, containing {0} for the 99 * first, and {1} for the rest. 100 * @param middle 101 * string for the start of a list items, containing {0} for the 102 * first part of the list, and {1} for the rest of the list. 103 * @param end 104 * string for the end of a list items, containing {0} for the 105 * first part of the list, and {1} for the last item. 106 * @deprecated This API is ICU internal only. 107 * @hide draft / provisional / internal are hidden on Android 108 */ 109 @Deprecated 110 public ListFormatter(String two, String start, String middle, String end) { 111 this( 112 compilePattern(two, new StringBuilder()), 113 compilePattern(start, new StringBuilder()), 114 compilePattern(middle, new StringBuilder()), 115 compilePattern(end, new StringBuilder()), 116 null); 117 } 118 119 private ListFormatter(String two, String start, String middle, String end, ULocale locale) { 120 this.two = two; 121 this.start = start; 122 this.middle = middle; 123 this.end = end; 124 this.locale = locale; 125 } 126 127 private static String compilePattern(String pattern, StringBuilder sb) { 128 return SimplePatternFormatter.compileToStringMinMaxPlaceholders(pattern, sb, 2, 2); 129 } 130 131 /** 132 * Create a list formatter that is appropriate for a locale. 133 * 134 * @param locale 135 * the locale in question. 136 * @return ListFormatter 137 */ 138 public static ListFormatter getInstance(ULocale locale) { 139 return getInstance(locale, Style.STANDARD); 140 } 141 142 /** 143 * Create a list formatter that is appropriate for a locale. 144 * 145 * @param locale 146 * the locale in question. 147 * @return ListFormatter 148 */ 149 public static ListFormatter getInstance(Locale locale) { 150 return getInstance(ULocale.forLocale(locale), Style.STANDARD); 151 } 152 153 /** 154 * Create a list formatter that is appropriate for a locale and style. 155 * 156 * @param locale the locale in question. 157 * @param style the style 158 * @return ListFormatter 159 * @deprecated This API is ICU internal only. 160 * @hide draft / provisional / internal are hidden on Android 161 */ 162 @Deprecated 163 public static ListFormatter getInstance(ULocale locale, Style style) { 164 return cache.get(locale, style.getName()); 165 } 166 167 /** 168 * Create a list formatter that is appropriate for the default FORMAT locale. 169 * 170 * @return ListFormatter 171 */ 172 public static ListFormatter getInstance() { 173 return getInstance(ULocale.getDefault(ULocale.Category.FORMAT)); 174 } 175 176 /** 177 * Format a list of objects. 178 * 179 * @param items 180 * items to format. The toString() method is called on each. 181 * @return items formatted into a string 182 */ 183 public String format(Object... items) { 184 return format(Arrays.asList(items)); 185 } 186 187 /** 188 * Format a collection of objects. The toString() method is called on each. 189 * 190 * @param items 191 * items to format. The toString() method is called on each. 192 * @return items formatted into a string 193 */ 194 public String format(Collection<?> items) { 195 return format(items, -1).toString(); 196 } 197 198 // Formats a collection of objects and returns the formatted string plus the offset 199 // in the string where the index th element appears. index is zero based. If index is 200 // negative or greater than or equal to the size of items then this function returns -1 for 201 // the offset. 202 FormattedListBuilder format(Collection<?> items, int index) { 203 Iterator<?> it = items.iterator(); 204 int count = items.size(); 205 switch (count) { 206 case 0: 207 return new FormattedListBuilder("", false); 208 case 1: 209 return new FormattedListBuilder(it.next(), index == 0); 210 case 2: 211 return new FormattedListBuilder(it.next(), index == 0).append(two, it.next(), index == 1); 212 } 213 FormattedListBuilder builder = new FormattedListBuilder(it.next(), index == 0); 214 builder.append(start, it.next(), index == 1); 215 for (int idx = 2; idx < count - 1; ++idx) { 216 builder.append(middle, it.next(), index == idx); 217 } 218 return builder.append(end, it.next(), index == count - 1); 219 } 220 221 /** 222 * Returns the pattern to use for a particular item count. 223 * @param count the item count. 224 * @return the pattern with {0}, {1}, {2}, etc. For English, 225 * getPatternForNumItems(3) == "{0}, {1}, and {2}" 226 * @throws IllegalArgumentException when count is 0 or negative. 227 */ 228 public String getPatternForNumItems(int count) { 229 if (count <= 0) { 230 throw new IllegalArgumentException("count must be > 0"); 231 } 232 ArrayList<String> list = new ArrayList<String>(); 233 for (int i = 0; i < count; i++) { 234 list.add(String.format("{%d}", i)); 235 } 236 return format(list); 237 } 238 239 /** 240 * Returns the locale of this object. 241 * @deprecated This API is ICU internal only. 242 * @hide draft / provisional / internal are hidden on Android 243 */ 244 @Deprecated 245 public ULocale getLocale() { 246 return locale; 247 } 248 249 // Builds a formatted list 250 static class FormattedListBuilder { 251 private StringBuilder current; 252 private int offset; 253 254 // Start is the first object in the list; If recordOffset is true, records the offset of 255 // this first object. 256 public FormattedListBuilder(Object start, boolean recordOffset) { 257 this.current = new StringBuilder(start.toString()); 258 this.offset = recordOffset ? 0 : -1; 259 } 260 261 // Appends additional object. pattern is a template indicating where the new object gets 262 // added in relation to the rest of the list. {0} represents the rest of the list; {1} 263 // represents the new object in pattern. next is the object to be added. If recordOffset 264 // is true, records the offset of next in the formatted string. 265 public FormattedListBuilder append(String pattern, Object next, boolean recordOffset) { 266 int[] offsets = (recordOffset || offsetRecorded()) ? new int[2] : null; 267 SimplePatternFormatter.formatAndReplace( 268 pattern, current, offsets, current, next.toString()); 269 if (offsets != null) { 270 if (offsets[0] == -1 || offsets[1] == -1) { 271 throw new IllegalArgumentException( 272 "{0} or {1} missing from pattern " + pattern); 273 } 274 if (recordOffset) { 275 offset = offsets[1]; 276 } else { 277 offset += offsets[0]; 278 } 279 } 280 return this; 281 } 282 283 @Override 284 public String toString() { 285 return current.toString(); 286 } 287 288 // Gets the last recorded offset or -1 if no offset recorded. 289 public int getOffset() { 290 return offset; 291 } 292 293 private boolean offsetRecorded() { 294 return offset >= 0; 295 } 296 } 297 298 private static class Cache { 299 private final ICUCache<String, ListFormatter> cache = 300 new SimpleCache<String, ListFormatter>(); 301 302 public ListFormatter get(ULocale locale, String style) { 303 String key = String.format("%s:%s", locale.toString(), style); 304 ListFormatter result = cache.get(key); 305 if (result == null) { 306 result = load(locale, style); 307 cache.put(key, result); 308 } 309 return result; 310 } 311 312 private static ListFormatter load(ULocale ulocale, String style) { 313 ICUResourceBundle r = (ICUResourceBundle)UResourceBundle. 314 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, ulocale); 315 StringBuilder sb = new StringBuilder(); 316 return new ListFormatter( 317 compilePattern(r.getWithFallback("listPattern/" + style + "/2").getString(), sb), 318 compilePattern(r.getWithFallback("listPattern/" + style + "/start").getString(), sb), 319 compilePattern(r.getWithFallback("listPattern/" + style + "/middle").getString(), sb), 320 compilePattern(r.getWithFallback("listPattern/" + style + "/end").getString(), sb), 321 ulocale); 322 } 323 } 324 325 static Cache cache = new Cache(); 326 } 327