Home | History | Annotate | Download | only in duration
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 2007-2010, International Business Machines Corporation and   *
      6 * others. All Rights Reserved.                                               *
      7 ******************************************************************************
      8 */
      9 
     10 package com.ibm.icu.impl.duration;
     11 
     12 import java.util.Locale;
     13 
     14 import com.ibm.icu.impl.duration.impl.DataRecord.ECountVariant;
     15 import com.ibm.icu.impl.duration.impl.DataRecord.ESeparatorVariant;
     16 import com.ibm.icu.impl.duration.impl.DataRecord.EUnitVariant;
     17 import com.ibm.icu.impl.duration.impl.PeriodFormatterData;
     18 import com.ibm.icu.impl.duration.impl.PeriodFormatterDataService;
     19 
     20 /**
     21  * An implementation of PeriodFormatterFactory that provides customization of
     22  * formatting behavior. Instances of this factory are created by
     23  * BasicPeriodFormatterService.
     24  *
     25  * The settings on BasicPeriodFormatterFactory are:
     26  * <ul>
     27  *
     28  * <li><b>setDisplayLimit</b> controls whether phrases like 'more than'
     29  * or 'less than' will be displayed when the Period has a defined
     30  * limit.  Default is to display them.</li>
     31  *
     32  * <li><b>setDisplayPastFuture</b> controls whether phrases like 'ago'
     33  * or 'from now' will be displayed to indicate past or future
     34  * time. Default is to display them.</li>
     35  *
     36  * <li><b>setSeparatorVariant</b> controls how separators (between
     37  * count and period, and multiple periods) will be displayed, when
     38  * appropriate for the language. Default is to use full
     39  * separators.</li>
     40  *
     41  * <li><b>setUnitVariant</b> controls which of various types of
     42  * unit names to use.  PLURALIZED indicates that full names will be
     43  * used.  MEDIUM indicates that medium-length (usually 2-3 character)
     44  * names will be used.  SHORT indicates that short (usually single
     45  * character) names will be used.  If there is no localization data
     46  * available for either the SHORT or MEDIUM names, the other will be
     47  * used, if neither is available, the PLURALIZED names will be used.
     48  * Default is PLURALIZED.</li>
     49  *
     50  * <li><b>setCountVariant</b> controls how the count for the smallest
     51  * unit will be formatted: either as an integer, a fraction to the
     52  * smallest half, or as a decimal with 1, 2, or 3 decimal points.</li>
     53  * Counts for higher units will be formatted as integers.
     54  *
     55  * </ul>
     56  */
     57 public class BasicPeriodFormatterFactory implements PeriodFormatterFactory {
     58   private final PeriodFormatterDataService ds;
     59   private PeriodFormatterData data;
     60   private Customizations customizations;
     61   private boolean customizationsInUse;
     62   private String localeName;
     63 
     64   // package-only constructor
     65   BasicPeriodFormatterFactory(PeriodFormatterDataService ds) {
     66     this.ds = ds;
     67     this.customizations = new Customizations();
     68     this.localeName = Locale.getDefault().toString();
     69   }
     70 
     71   /**
     72    * Return the default rdf factory as a BasicPeriodFormatterFactory.
     73    *
     74    * @return a default BasicPeriodFormatterFactory
     75    */
     76   public static BasicPeriodFormatterFactory getDefault() {
     77       return (BasicPeriodFormatterFactory)
     78         BasicPeriodFormatterService.getInstance().newPeriodFormatterFactory();
     79   }
     80 
     81   /**
     82    * Set the locale for this factory.
     83    */
     84   @Override
     85   public PeriodFormatterFactory setLocale(String localeName) {
     86     data = null;
     87     this.localeName = localeName;
     88     return this;
     89   }
     90 
     91   /**
     92    * Set whether limits will be displayed.
     93    *
     94    * @param display true if limits will be displayed
     95    * @return this PeriodFormatterFactory
     96    */
     97   @Override
     98   public PeriodFormatterFactory setDisplayLimit(boolean display) {
     99     updateCustomizations().displayLimit = display;
    100     return this;
    101   }
    102 
    103   /**
    104    * Return true if limits will be displayed.
    105    *
    106    * @return true if limits will be displayed
    107    */
    108   public boolean getDisplayLimit() {
    109     return customizations.displayLimit;
    110   }
    111 
    112   /**
    113    * Set whether past and future will be displayed.
    114    *
    115    * @param display true if past and future will be displayed
    116    * @return this PeriodFormatterFactory
    117    */
    118   @Override
    119   public PeriodFormatterFactory setDisplayPastFuture(boolean display) {
    120     updateCustomizations().displayDirection = display;
    121     return this;
    122   }
    123 
    124   /**
    125    * Return true if past and future will be displayed.
    126    *
    127    * @return true if past and future will be displayed
    128    */
    129   public boolean getDisplayPastFuture() {
    130     return customizations.displayDirection;
    131   }
    132 
    133   /**
    134    * Set how separators will be displayed.
    135    *
    136    * @param variant the variant indicating separators will be displayed
    137    * @return this PeriodFormatterFactory
    138    */
    139   @Override
    140   public PeriodFormatterFactory setSeparatorVariant(int variant) {
    141     updateCustomizations().separatorVariant = (byte) variant;
    142     return this;
    143   }
    144 
    145   /**
    146    * Return the variant indicating how separators will be displayed.
    147    *
    148    * @return the variant
    149    */
    150   public int getSeparatorVariant() {
    151     return customizations.separatorVariant;
    152   }
    153 
    154   /**
    155    * Set the variant of the time unit names to use.
    156    *
    157    * @param variant the variant to use
    158    * @return this PeriodFormatterFactory
    159    */
    160   @Override
    161   public PeriodFormatterFactory setUnitVariant(int variant) {
    162     updateCustomizations().unitVariant = (byte) variant;
    163     return this;
    164   }
    165 
    166   /**
    167    * Return the unit variant.
    168    *
    169    * @return the unit variant
    170    */
    171   public int getUnitVariant() {
    172     return customizations.unitVariant;
    173   }
    174 
    175   /**
    176    * Set the variant of the count to use.
    177    *
    178    * @param variant the variant to use
    179    * @return this PeriodFormatterFactory
    180    */
    181   @Override
    182   public PeriodFormatterFactory setCountVariant(int variant) {
    183     updateCustomizations().countVariant = (byte) variant;
    184     return this;
    185   }
    186 
    187   /**
    188    * Return the count variant.
    189    *
    190    * @return the count variant
    191    */
    192   public int getCountVariant() {
    193     return customizations.countVariant;
    194   }
    195 
    196   @Override
    197   public PeriodFormatter getFormatter() {
    198     customizationsInUse = true;
    199     return new BasicPeriodFormatter(this, localeName, getData(),
    200                                     customizations);
    201   }
    202 
    203   private Customizations updateCustomizations() {
    204     if (customizationsInUse) {
    205       customizations = customizations.copy();
    206       customizationsInUse = false;
    207     }
    208     return customizations;
    209   }
    210 
    211   // package access only
    212   PeriodFormatterData getData() {
    213     if (data == null) {
    214       data = ds.get(localeName);
    215     }
    216     return data;
    217   }
    218 
    219   // package access for use by BasicPeriodFormatter
    220   PeriodFormatterData getData(String locName) {
    221     return ds.get(locName);
    222   }
    223 
    224   // package access for use by BasicPeriodFormatter
    225   static class Customizations {
    226     boolean displayLimit = true;
    227     boolean displayDirection = true;
    228     byte separatorVariant = ESeparatorVariant.FULL;
    229     byte unitVariant = EUnitVariant.PLURALIZED;
    230     byte countVariant = ECountVariant.INTEGER;
    231 
    232     public Customizations copy() {
    233         Customizations result = new Customizations();
    234         result.displayLimit = displayLimit;
    235         result.displayDirection = displayDirection;
    236         result.separatorVariant = separatorVariant;
    237         result.unitVariant = unitVariant;
    238         result.countVariant = countVariant;
    239         return result;
    240     }
    241   }
    242 }
    243