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-2009, 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 import java.util.TimeZone;
     14 
     15 /**
     16  * Abstract factory object used to create DurationFormatters.
     17  * DurationFormatters are immutable once created.
     18  * <p>
     19  * Setters on the factory mutate the factory and return it,
     20  * for chaining.
     21  * <p>
     22  * Subclasses override getFormatter to return a custom
     23  * DurationFormatter.
     24  */
     25 class BasicDurationFormatterFactory implements DurationFormatterFactory {
     26   private BasicPeriodFormatterService ps;
     27   private PeriodFormatter formatter;
     28   private PeriodBuilder builder;
     29   private DateFormatter fallback;
     30   private long fallbackLimit;
     31   private String localeName;
     32   private TimeZone timeZone;
     33   private BasicDurationFormatter f; // cache
     34 
     35   /**
     36    * Create a default formatter for the current locale and time zone.
     37    */
     38   BasicDurationFormatterFactory(BasicPeriodFormatterService ps) {
     39     this.ps = ps;
     40     this.localeName = Locale.getDefault().toString();
     41     this.timeZone = TimeZone.getDefault();
     42   }
     43 
     44   /**
     45    * Set the period formatter used by the factory.  New formatters created
     46    * with this factory will use the given period formatter.
     47    *
     48    * @return this BasicDurationFormatterFactory
     49    */
     50   @Override
     51   public DurationFormatterFactory setPeriodFormatter(
     52       PeriodFormatter formatter) {
     53     if (formatter != this.formatter) {
     54       this.formatter = formatter;
     55       reset();
     56     }
     57     return this;
     58   }
     59 
     60   /**
     61    * Set the builder used by the factory.  New formatters created
     62    * with this factory will use the given locale.
     63    *
     64    * @param builder the builder to use
     65    * @return this BasicDurationFormatterFactory
     66    */
     67   @Override
     68   public DurationFormatterFactory setPeriodBuilder(PeriodBuilder builder) {
     69     if (builder != this.builder) {
     70       this.builder = builder;
     71       reset();
     72     }
     73     return this;
     74   }
     75 
     76   /**
     77    * Set a fallback formatter for durations over a given limit.
     78    *
     79    * @param fallback the fallback formatter to use, or null
     80    * @return this BasicDurationFormatterFactory
     81    */
     82   @Override
     83   public DurationFormatterFactory setFallback(DateFormatter fallback) {
     84     boolean doReset = fallback == null
     85         ? this.fallback != null
     86         : !fallback.equals(this.fallback);
     87     if (doReset) {
     88       this.fallback = fallback;
     89       reset();
     90     }
     91     return this;
     92   }
     93 
     94   /**
     95    * Set a fallback limit for durations over a given limit.
     96    *
     97    * @param fallbackLimit the fallback limit to use, or 0 if none is desired.
     98    * @return this BasicDurationFormatterFactory
     99    */
    100   @Override
    101   public DurationFormatterFactory setFallbackLimit(long fallbackLimit) {
    102     if (fallbackLimit < 0) {
    103       fallbackLimit = 0;
    104     }
    105     if (fallbackLimit != this.fallbackLimit) {
    106       this.fallbackLimit = fallbackLimit;
    107       reset();
    108     }
    109     return this;
    110   }
    111 
    112   /**
    113    * Set the name of the locale that will be used when
    114    * creating new formatters.
    115    *
    116    * @param localeName the name of the Locale
    117    * @return this BasicDurationFormatterFactory
    118    */
    119   @Override
    120   public DurationFormatterFactory setLocale(String localeName) {
    121     if (!localeName.equals(this.localeName)) {
    122       this.localeName = localeName;
    123       if (builder != null) {
    124           builder = builder.withLocale(localeName);
    125       }
    126       if (formatter != null) {
    127           formatter = formatter.withLocale(localeName);
    128       }
    129       reset();
    130     }
    131     return this;
    132   }
    133 
    134   /**
    135    * Set the name of the locale that will be used when
    136    * creating new formatters.
    137    *
    138    * @param timeZone The time zone to use.
    139    * @return this BasicDurationFormatterFactory
    140    */
    141   @Override
    142   public DurationFormatterFactory setTimeZone(TimeZone timeZone) {
    143     if (!timeZone.equals(this.timeZone)) {
    144       this.timeZone = timeZone;
    145       if (builder != null) {
    146           builder = builder.withTimeZone(timeZone);
    147       }
    148       reset();
    149     }
    150     return this;
    151   }
    152 
    153   /**
    154    * Return a formatter based on this factory's current settings.
    155    *
    156    * @return a BasicDurationFormatter
    157    */
    158   @Override
    159   public DurationFormatter getFormatter() {
    160     if (f == null) {
    161       if (fallback != null) {
    162         fallback = fallback.withLocale(localeName).withTimeZone(timeZone);
    163       }
    164       formatter = getPeriodFormatter();
    165       builder = getPeriodBuilder();
    166 
    167       f = createFormatter();
    168     }
    169     return f;
    170   }
    171 
    172   /**
    173    * Return the current period formatter.
    174    *
    175    * @return the current period formatter
    176    */
    177   public PeriodFormatter getPeriodFormatter() {
    178     if (formatter == null) {
    179       formatter = ps.newPeriodFormatterFactory()
    180           .setLocale(localeName)
    181           .getFormatter();
    182     }
    183     return formatter;
    184   }
    185 
    186   /**
    187    * Return the current builder.
    188    *
    189    * @return the current builder
    190    */
    191   public PeriodBuilder getPeriodBuilder() {
    192     if (builder == null) {
    193       builder = ps.newPeriodBuilderFactory()
    194           .setLocale(localeName)
    195           .setTimeZone(timeZone)
    196           .getSingleUnitBuilder();
    197     }
    198     return builder;
    199   }
    200 
    201   /**
    202    * Return the current fallback formatter.
    203    *
    204    * @return the fallback formatter, or null if there is no fallback
    205    * formatter
    206    */
    207   public DateFormatter getFallback() {
    208     return fallback;
    209   }
    210 
    211   /**
    212    * Return the current fallback formatter limit
    213    *
    214    * @return the limit, or 0 if there is no fallback.
    215    */
    216   public long getFallbackLimit() {
    217     return fallback == null ? 0 : fallbackLimit;
    218   }
    219 
    220   /**
    221    * Return the current locale name.
    222    *
    223    * @return the current locale name
    224    */
    225   public String getLocaleName() {
    226     return localeName;
    227   }
    228 
    229   /**
    230    * Return the current locale name.
    231    *
    232    * @return the current locale name
    233    */
    234   public TimeZone getTimeZone() {
    235     return timeZone;
    236   }
    237 
    238   /**
    239    * Create the formatter.  All local fields are already initialized.
    240    */
    241   protected BasicDurationFormatter createFormatter() {
    242     return new BasicDurationFormatter(formatter, builder, fallback,
    243                                       fallbackLimit, localeName,
    244                                       timeZone);
    245   }
    246 
    247   /**
    248    * Clear the cached formatter.  Subclasses must call this if their
    249    * state has changed. This is automatically invoked by setBuilder,
    250    * setFormatter, setFallback, setLocaleName, and setTimeZone
    251    */
    252   protected void reset() {
    253     f = null;
    254   }
    255 }
    256