Home | History | Annotate | Download | only in text
      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