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