1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/rt/emul/compact/src/main/java/java/text/DateFormatSymbols.java Thu Oct 03 15:40:35 2013 +0200
1.3 @@ -0,0 +1,794 @@
1.4 +/*
1.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +/*
1.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
1.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
1.32 + *
1.33 + * The original version of this source code and documentation is copyrighted
1.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
1.35 + * materials are provided under terms of a License Agreement between Taligent
1.36 + * and Sun. This technology is protected by multiple US and International
1.37 + * patents. This notice and attribution to Taligent may not be removed.
1.38 + * Taligent is a registered trademark of Taligent, Inc.
1.39 + *
1.40 + */
1.41 +
1.42 +package java.text;
1.43 +
1.44 +import java.io.IOException;
1.45 +import java.io.ObjectOutputStream;
1.46 +import java.io.Serializable;
1.47 +import java.lang.ref.SoftReference;
1.48 +import java.text.spi.DateFormatSymbolsProvider;
1.49 +import java.util.Arrays;
1.50 +import java.util.List;
1.51 +import java.util.Locale;
1.52 +import java.util.ResourceBundle;
1.53 +import java.util.TimeZone;
1.54 +import java.util.concurrent.ConcurrentHashMap;
1.55 +import java.util.concurrent.ConcurrentMap;
1.56 +import java.util.spi.LocaleServiceProvider;
1.57 +import sun.util.LocaleServiceProviderPool;
1.58 +import sun.util.TimeZoneNameUtility;
1.59 +import sun.util.calendar.ZoneInfo;
1.60 +import sun.util.resources.LocaleData;
1.61 +
1.62 +/**
1.63 + * <code>DateFormatSymbols</code> is a public class for encapsulating
1.64 + * localizable date-time formatting data, such as the names of the
1.65 + * months, the names of the days of the week, and the time zone data.
1.66 + * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
1.67 + * <code>DateFormatSymbols</code> to encapsulate this information.
1.68 + *
1.69 + * <p>
1.70 + * Typically you shouldn't use <code>DateFormatSymbols</code> directly.
1.71 + * Rather, you are encouraged to create a date-time formatter with the
1.72 + * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
1.73 + * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
1.74 + * These methods automatically create a <code>DateFormatSymbols</code> for
1.75 + * the formatter so that you don't have to. After the
1.76 + * formatter is created, you may modify its format pattern using the
1.77 + * <code>setPattern</code> method. For more information about
1.78 + * creating formatters using <code>DateFormat</code>'s factory methods,
1.79 + * see {@link DateFormat}.
1.80 + *
1.81 + * <p>
1.82 + * If you decide to create a date-time formatter with a specific
1.83 + * format pattern for a specific locale, you can do so with:
1.84 + * <blockquote>
1.85 + * <pre>
1.86 + * new SimpleDateFormat(aPattern, DateFormatSymbols.getInstance(aLocale)).
1.87 + * </pre>
1.88 + * </blockquote>
1.89 + *
1.90 + * <p>
1.91 + * <code>DateFormatSymbols</code> objects are cloneable. When you obtain
1.92 + * a <code>DateFormatSymbols</code> object, feel free to modify the
1.93 + * date-time formatting data. For instance, you can replace the localized
1.94 + * date-time format pattern characters with the ones that you feel easy
1.95 + * to remember. Or you can change the representative cities
1.96 + * to your favorite ones.
1.97 + *
1.98 + * <p>
1.99 + * New <code>DateFormatSymbols</code> subclasses may be added to support
1.100 + * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
1.101 +
1.102 + * @see DateFormat
1.103 + * @see SimpleDateFormat
1.104 + * @see java.util.SimpleTimeZone
1.105 + * @author Chen-Lieh Huang
1.106 + */
1.107 +public class DateFormatSymbols implements Serializable, Cloneable {
1.108 +
1.109 + /**
1.110 + * Construct a DateFormatSymbols object by loading format data from
1.111 + * resources for the default locale. This constructor can only
1.112 + * construct instances for the locales supported by the Java
1.113 + * runtime environment, not for those supported by installed
1.114 + * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
1.115 + * implementations. For full locale coverage, use the
1.116 + * {@link #getInstance(Locale) getInstance} method.
1.117 + *
1.118 + * @see #getInstance()
1.119 + * @exception java.util.MissingResourceException
1.120 + * if the resources for the default locale cannot be
1.121 + * found or cannot be loaded.
1.122 + */
1.123 + public DateFormatSymbols()
1.124 + {
1.125 + initializeData(Locale.getDefault(Locale.Category.FORMAT));
1.126 + }
1.127 +
1.128 + /**
1.129 + * Construct a DateFormatSymbols object by loading format data from
1.130 + * resources for the given locale. This constructor can only
1.131 + * construct instances for the locales supported by the Java
1.132 + * runtime environment, not for those supported by installed
1.133 + * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
1.134 + * implementations. For full locale coverage, use the
1.135 + * {@link #getInstance(Locale) getInstance} method.
1.136 + *
1.137 + * @see #getInstance(Locale)
1.138 + * @exception java.util.MissingResourceException
1.139 + * if the resources for the specified locale cannot be
1.140 + * found or cannot be loaded.
1.141 + */
1.142 + public DateFormatSymbols(Locale locale)
1.143 + {
1.144 + initializeData(locale);
1.145 + }
1.146 +
1.147 + /**
1.148 + * Era strings. For example: "AD" and "BC". An array of 2 strings,
1.149 + * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
1.150 + * @serial
1.151 + */
1.152 + String eras[] = null;
1.153 +
1.154 + /**
1.155 + * Month strings. For example: "January", "February", etc. An array
1.156 + * of 13 strings (some calendars have 13 months), indexed by
1.157 + * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
1.158 + * @serial
1.159 + */
1.160 + String months[] = null;
1.161 +
1.162 + /**
1.163 + * Short month strings. For example: "Jan", "Feb", etc. An array of
1.164 + * 13 strings (some calendars have 13 months), indexed by
1.165 + * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
1.166 +
1.167 + * @serial
1.168 + */
1.169 + String shortMonths[] = null;
1.170 +
1.171 + /**
1.172 + * Weekday strings. For example: "Sunday", "Monday", etc. An array
1.173 + * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
1.174 + * <code>Calendar.MONDAY</code>, etc.
1.175 + * The element <code>weekdays[0]</code> is ignored.
1.176 + * @serial
1.177 + */
1.178 + String weekdays[] = null;
1.179 +
1.180 + /**
1.181 + * Short weekday strings. For example: "Sun", "Mon", etc. An array
1.182 + * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
1.183 + * <code>Calendar.MONDAY</code>, etc.
1.184 + * The element <code>shortWeekdays[0]</code> is ignored.
1.185 + * @serial
1.186 + */
1.187 + String shortWeekdays[] = null;
1.188 +
1.189 + /**
1.190 + * AM and PM strings. For example: "AM" and "PM". An array of
1.191 + * 2 strings, indexed by <code>Calendar.AM</code> and
1.192 + * <code>Calendar.PM</code>.
1.193 + * @serial
1.194 + */
1.195 + String ampms[] = null;
1.196 +
1.197 + /**
1.198 + * Localized names of time zones in this locale. This is a
1.199 + * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
1.200 + * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
1.201 + * entry containing the localized names for a single <code>TimeZone</code>.
1.202 + * Each such row contains (with <code>i</code> ranging from
1.203 + * 0..<em>n</em>-1):
1.204 + * <ul>
1.205 + * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
1.206 + * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
1.207 + * time</li>
1.208 + * <li><code>zoneStrings[i][2]</code> - short name of zone in
1.209 + * standard time</li>
1.210 + * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
1.211 + * saving time</li>
1.212 + * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
1.213 + * saving time</li>
1.214 + * </ul>
1.215 + * The zone ID is <em>not</em> localized; it's one of the valid IDs of
1.216 + * the {@link java.util.TimeZone TimeZone} class that are not
1.217 + * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
1.218 + * All other entries are localized names.
1.219 + * @see java.util.TimeZone
1.220 + * @serial
1.221 + */
1.222 + String zoneStrings[][] = null;
1.223 +
1.224 + /**
1.225 + * Indicates that zoneStrings is set externally with setZoneStrings() method.
1.226 + */
1.227 + transient boolean isZoneStringsSet = false;
1.228 +
1.229 + /**
1.230 + * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
1.231 + * All locales use the same these unlocalized pattern characters.
1.232 + */
1.233 + static final String patternChars = "GyMdkHmsSEDFwWahKzZYuX";
1.234 +
1.235 + static final int PATTERN_ERA = 0; // G
1.236 + static final int PATTERN_YEAR = 1; // y
1.237 + static final int PATTERN_MONTH = 2; // M
1.238 + static final int PATTERN_DAY_OF_MONTH = 3; // d
1.239 + static final int PATTERN_HOUR_OF_DAY1 = 4; // k
1.240 + static final int PATTERN_HOUR_OF_DAY0 = 5; // H
1.241 + static final int PATTERN_MINUTE = 6; // m
1.242 + static final int PATTERN_SECOND = 7; // s
1.243 + static final int PATTERN_MILLISECOND = 8; // S
1.244 + static final int PATTERN_DAY_OF_WEEK = 9; // E
1.245 + static final int PATTERN_DAY_OF_YEAR = 10; // D
1.246 + static final int PATTERN_DAY_OF_WEEK_IN_MONTH = 11; // F
1.247 + static final int PATTERN_WEEK_OF_YEAR = 12; // w
1.248 + static final int PATTERN_WEEK_OF_MONTH = 13; // W
1.249 + static final int PATTERN_AM_PM = 14; // a
1.250 + static final int PATTERN_HOUR1 = 15; // h
1.251 + static final int PATTERN_HOUR0 = 16; // K
1.252 + static final int PATTERN_ZONE_NAME = 17; // z
1.253 + static final int PATTERN_ZONE_VALUE = 18; // Z
1.254 + static final int PATTERN_WEEK_YEAR = 19; // Y
1.255 + static final int PATTERN_ISO_DAY_OF_WEEK = 20; // u
1.256 + static final int PATTERN_ISO_ZONE = 21; // X
1.257 +
1.258 + /**
1.259 + * Localized date-time pattern characters. For example, a locale may
1.260 + * wish to use 'u' rather than 'y' to represent years in its date format
1.261 + * pattern strings.
1.262 + * This string must be exactly 18 characters long, with the index of
1.263 + * the characters described by <code>DateFormat.ERA_FIELD</code>,
1.264 + * <code>DateFormat.YEAR_FIELD</code>, etc. Thus, if the string were
1.265 + * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
1.266 + * @serial
1.267 + */
1.268 + String localPatternChars = null;
1.269 +
1.270 + /**
1.271 + * The locale which is used for initializing this DateFormatSymbols object.
1.272 + *
1.273 + * @since 1.6
1.274 + * @serial
1.275 + */
1.276 + Locale locale = null;
1.277 +
1.278 + /* use serialVersionUID from JDK 1.1.4 for interoperability */
1.279 + static final long serialVersionUID = -5987973545549424702L;
1.280 +
1.281 + /**
1.282 + * Returns an array of all locales for which the
1.283 + * <code>getInstance</code> methods of this class can return
1.284 + * localized instances.
1.285 + * The returned array represents the union of locales supported by the
1.286 + * Java runtime and by installed
1.287 + * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
1.288 + * implementations. It must contain at least a <code>Locale</code>
1.289 + * instance equal to {@link java.util.Locale#US Locale.US}.
1.290 + *
1.291 + * @return An array of locales for which localized
1.292 + * <code>DateFormatSymbols</code> instances are available.
1.293 + * @since 1.6
1.294 + */
1.295 + public static Locale[] getAvailableLocales() {
1.296 + LocaleServiceProviderPool pool=
1.297 + LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
1.298 + return pool.getAvailableLocales();
1.299 + }
1.300 +
1.301 + /**
1.302 + * Gets the <code>DateFormatSymbols</code> instance for the default
1.303 + * locale. This method provides access to <code>DateFormatSymbols</code>
1.304 + * instances for locales supported by the Java runtime itself as well
1.305 + * as for those supported by installed
1.306 + * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
1.307 + * implementations.
1.308 + * @return a <code>DateFormatSymbols</code> instance.
1.309 + * @since 1.6
1.310 + */
1.311 + public static final DateFormatSymbols getInstance() {
1.312 + return getInstance(Locale.getDefault(Locale.Category.FORMAT));
1.313 + }
1.314 +
1.315 + /**
1.316 + * Gets the <code>DateFormatSymbols</code> instance for the specified
1.317 + * locale. This method provides access to <code>DateFormatSymbols</code>
1.318 + * instances for locales supported by the Java runtime itself as well
1.319 + * as for those supported by installed
1.320 + * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
1.321 + * implementations.
1.322 + * @param locale the given locale.
1.323 + * @return a <code>DateFormatSymbols</code> instance.
1.324 + * @exception NullPointerException if <code>locale</code> is null
1.325 + * @since 1.6
1.326 + */
1.327 + public static final DateFormatSymbols getInstance(Locale locale) {
1.328 + DateFormatSymbols dfs = getProviderInstance(locale);
1.329 + if (dfs != null) {
1.330 + return dfs;
1.331 + }
1.332 + return (DateFormatSymbols) getCachedInstance(locale).clone();
1.333 + }
1.334 +
1.335 + /**
1.336 + * Returns a DateFormatSymbols provided by a provider or found in
1.337 + * the cache. Note that this method returns a cached instance,
1.338 + * not its clone. Therefore, the instance should never be given to
1.339 + * an application.
1.340 + */
1.341 + static final DateFormatSymbols getInstanceRef(Locale locale) {
1.342 + DateFormatSymbols dfs = getProviderInstance(locale);
1.343 + if (dfs != null) {
1.344 + return dfs;
1.345 + }
1.346 + return getCachedInstance(locale);
1.347 + }
1.348 +
1.349 + private static DateFormatSymbols getProviderInstance(Locale locale) {
1.350 + DateFormatSymbols providersInstance = null;
1.351 +
1.352 + // Check whether a provider can provide an implementation that's closer
1.353 + // to the requested locale than what the Java runtime itself can provide.
1.354 + LocaleServiceProviderPool pool =
1.355 + LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
1.356 + if (pool.hasProviders()) {
1.357 + providersInstance = pool.getLocalizedObject(
1.358 + DateFormatSymbolsGetter.INSTANCE, locale);
1.359 + }
1.360 + return providersInstance;
1.361 + }
1.362 +
1.363 + /**
1.364 + * Returns a cached DateFormatSymbols if it's found in the
1.365 + * cache. Otherwise, this method returns a newly cached instance
1.366 + * for the given locale.
1.367 + */
1.368 + private static DateFormatSymbols getCachedInstance(Locale locale) {
1.369 + SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
1.370 + DateFormatSymbols dfs = null;
1.371 + if (ref == null || (dfs = ref.get()) == null) {
1.372 + dfs = new DateFormatSymbols(locale);
1.373 + ref = new SoftReference<DateFormatSymbols>(dfs);
1.374 + SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
1.375 + if (x != null) {
1.376 + DateFormatSymbols y = x.get();
1.377 + if (y != null) {
1.378 + dfs = y;
1.379 + } else {
1.380 + // Replace the empty SoftReference with ref.
1.381 + cachedInstances.put(locale, ref);
1.382 + }
1.383 + }
1.384 + }
1.385 + return dfs;
1.386 + }
1.387 +
1.388 + /**
1.389 + * Gets era strings. For example: "AD" and "BC".
1.390 + * @return the era strings.
1.391 + */
1.392 + public String[] getEras() {
1.393 + return Arrays.copyOf(eras, eras.length);
1.394 + }
1.395 +
1.396 + /**
1.397 + * Sets era strings. For example: "AD" and "BC".
1.398 + * @param newEras the new era strings.
1.399 + */
1.400 + public void setEras(String[] newEras) {
1.401 + eras = Arrays.copyOf(newEras, newEras.length);
1.402 + }
1.403 +
1.404 + /**
1.405 + * Gets month strings. For example: "January", "February", etc.
1.406 + * @return the month strings.
1.407 + */
1.408 + public String[] getMonths() {
1.409 + return Arrays.copyOf(months, months.length);
1.410 + }
1.411 +
1.412 + /**
1.413 + * Sets month strings. For example: "January", "February", etc.
1.414 + * @param newMonths the new month strings.
1.415 + */
1.416 + public void setMonths(String[] newMonths) {
1.417 + months = Arrays.copyOf(newMonths, newMonths.length);
1.418 + }
1.419 +
1.420 + /**
1.421 + * Gets short month strings. For example: "Jan", "Feb", etc.
1.422 + * @return the short month strings.
1.423 + */
1.424 + public String[] getShortMonths() {
1.425 + return Arrays.copyOf(shortMonths, shortMonths.length);
1.426 + }
1.427 +
1.428 + /**
1.429 + * Sets short month strings. For example: "Jan", "Feb", etc.
1.430 + * @param newShortMonths the new short month strings.
1.431 + */
1.432 + public void setShortMonths(String[] newShortMonths) {
1.433 + shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
1.434 + }
1.435 +
1.436 + /**
1.437 + * Gets weekday strings. For example: "Sunday", "Monday", etc.
1.438 + * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
1.439 + * <code>Calendar.MONDAY</code>, etc. to index the result array.
1.440 + */
1.441 + public String[] getWeekdays() {
1.442 + return Arrays.copyOf(weekdays, weekdays.length);
1.443 + }
1.444 +
1.445 + /**
1.446 + * Sets weekday strings. For example: "Sunday", "Monday", etc.
1.447 + * @param newWeekdays the new weekday strings. The array should
1.448 + * be indexed by <code>Calendar.SUNDAY</code>,
1.449 + * <code>Calendar.MONDAY</code>, etc.
1.450 + */
1.451 + public void setWeekdays(String[] newWeekdays) {
1.452 + weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
1.453 + }
1.454 +
1.455 + /**
1.456 + * Gets short weekday strings. For example: "Sun", "Mon", etc.
1.457 + * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
1.458 + * <code>Calendar.MONDAY</code>, etc. to index the result array.
1.459 + */
1.460 + public String[] getShortWeekdays() {
1.461 + return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
1.462 + }
1.463 +
1.464 + /**
1.465 + * Sets short weekday strings. For example: "Sun", "Mon", etc.
1.466 + * @param newShortWeekdays the new short weekday strings. The array should
1.467 + * be indexed by <code>Calendar.SUNDAY</code>,
1.468 + * <code>Calendar.MONDAY</code>, etc.
1.469 + */
1.470 + public void setShortWeekdays(String[] newShortWeekdays) {
1.471 + shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
1.472 + }
1.473 +
1.474 + /**
1.475 + * Gets ampm strings. For example: "AM" and "PM".
1.476 + * @return the ampm strings.
1.477 + */
1.478 + public String[] getAmPmStrings() {
1.479 + return Arrays.copyOf(ampms, ampms.length);
1.480 + }
1.481 +
1.482 + /**
1.483 + * Sets ampm strings. For example: "AM" and "PM".
1.484 + * @param newAmpms the new ampm strings.
1.485 + */
1.486 + public void setAmPmStrings(String[] newAmpms) {
1.487 + ampms = Arrays.copyOf(newAmpms, newAmpms.length);
1.488 + }
1.489 +
1.490 + /**
1.491 + * Gets time zone strings. Use of this method is discouraged; use
1.492 + * {@link java.util.TimeZone#getDisplayName() TimeZone.getDisplayName()}
1.493 + * instead.
1.494 + * <p>
1.495 + * The value returned is a
1.496 + * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
1.497 + * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
1.498 + * entry containing the localized names for a single <code>TimeZone</code>.
1.499 + * Each such row contains (with <code>i</code> ranging from
1.500 + * 0..<em>n</em>-1):
1.501 + * <ul>
1.502 + * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
1.503 + * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
1.504 + * time</li>
1.505 + * <li><code>zoneStrings[i][2]</code> - short name of zone in
1.506 + * standard time</li>
1.507 + * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
1.508 + * saving time</li>
1.509 + * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
1.510 + * saving time</li>
1.511 + * </ul>
1.512 + * The zone ID is <em>not</em> localized; it's one of the valid IDs of
1.513 + * the {@link java.util.TimeZone TimeZone} class that are not
1.514 + * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
1.515 + * All other entries are localized names. If a zone does not implement
1.516 + * daylight saving time, the daylight saving time names should not be used.
1.517 + * <p>
1.518 + * If {@link #setZoneStrings(String[][]) setZoneStrings} has been called
1.519 + * on this <code>DateFormatSymbols</code> instance, then the strings
1.520 + * provided by that call are returned. Otherwise, the returned array
1.521 + * contains names provided by the Java runtime and by installed
1.522 + * {@link java.util.spi.TimeZoneNameProvider TimeZoneNameProvider}
1.523 + * implementations.
1.524 + *
1.525 + * @return the time zone strings.
1.526 + * @see #setZoneStrings(String[][])
1.527 + */
1.528 + public String[][] getZoneStrings() {
1.529 + return getZoneStringsImpl(true);
1.530 + }
1.531 +
1.532 + /**
1.533 + * Sets time zone strings. The argument must be a
1.534 + * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
1.535 + * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
1.536 + * entry containing the localized names for a single <code>TimeZone</code>.
1.537 + * Each such row contains (with <code>i</code> ranging from
1.538 + * 0..<em>n</em>-1):
1.539 + * <ul>
1.540 + * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
1.541 + * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
1.542 + * time</li>
1.543 + * <li><code>zoneStrings[i][2]</code> - short name of zone in
1.544 + * standard time</li>
1.545 + * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
1.546 + * saving time</li>
1.547 + * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
1.548 + * saving time</li>
1.549 + * </ul>
1.550 + * The zone ID is <em>not</em> localized; it's one of the valid IDs of
1.551 + * the {@link java.util.TimeZone TimeZone} class that are not
1.552 + * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
1.553 + * All other entries are localized names.
1.554 + *
1.555 + * @param newZoneStrings the new time zone strings.
1.556 + * @exception IllegalArgumentException if the length of any row in
1.557 + * <code>newZoneStrings</code> is less than 5
1.558 + * @exception NullPointerException if <code>newZoneStrings</code> is null
1.559 + * @see #getZoneStrings()
1.560 + */
1.561 + public void setZoneStrings(String[][] newZoneStrings) {
1.562 + String[][] aCopy = new String[newZoneStrings.length][];
1.563 + for (int i = 0; i < newZoneStrings.length; ++i) {
1.564 + int len = newZoneStrings[i].length;
1.565 + if (len < 5) {
1.566 + throw new IllegalArgumentException();
1.567 + }
1.568 + aCopy[i] = Arrays.copyOf(newZoneStrings[i], len);
1.569 + }
1.570 + zoneStrings = aCopy;
1.571 + isZoneStringsSet = true;
1.572 + }
1.573 +
1.574 + /**
1.575 + * Gets localized date-time pattern characters. For example: 'u', 't', etc.
1.576 + * @return the localized date-time pattern characters.
1.577 + */
1.578 + public String getLocalPatternChars() {
1.579 + return localPatternChars;
1.580 + }
1.581 +
1.582 + /**
1.583 + * Sets localized date-time pattern characters. For example: 'u', 't', etc.
1.584 + * @param newLocalPatternChars the new localized date-time
1.585 + * pattern characters.
1.586 + */
1.587 + public void setLocalPatternChars(String newLocalPatternChars) {
1.588 + // Call toString() to throw an NPE in case the argument is null
1.589 + localPatternChars = newLocalPatternChars.toString();
1.590 + }
1.591 +
1.592 + /**
1.593 + * Overrides Cloneable
1.594 + */
1.595 + public Object clone()
1.596 + {
1.597 + try
1.598 + {
1.599 + DateFormatSymbols other = (DateFormatSymbols)super.clone();
1.600 + copyMembers(this, other);
1.601 + return other;
1.602 + } catch (CloneNotSupportedException e) {
1.603 + throw new InternalError();
1.604 + }
1.605 + }
1.606 +
1.607 + /**
1.608 + * Override hashCode.
1.609 + * Generates a hash code for the DateFormatSymbols object.
1.610 + */
1.611 + public int hashCode() {
1.612 + int hashcode = 0;
1.613 + String[][] zoneStrings = getZoneStringsWrapper();
1.614 + for (int index = 0; index < zoneStrings[0].length; ++index)
1.615 + hashcode ^= zoneStrings[0][index].hashCode();
1.616 + return hashcode;
1.617 + }
1.618 +
1.619 + /**
1.620 + * Override equals
1.621 + */
1.622 + public boolean equals(Object obj)
1.623 + {
1.624 + if (this == obj) return true;
1.625 + if (obj == null || getClass() != obj.getClass()) return false;
1.626 + DateFormatSymbols that = (DateFormatSymbols) obj;
1.627 + return (Arrays.equals(eras, that.eras)
1.628 + && Arrays.equals(months, that.months)
1.629 + && Arrays.equals(shortMonths, that.shortMonths)
1.630 + && Arrays.equals(weekdays, that.weekdays)
1.631 + && Arrays.equals(shortWeekdays, that.shortWeekdays)
1.632 + && Arrays.equals(ampms, that.ampms)
1.633 + && Arrays.deepEquals(getZoneStringsWrapper(), that.getZoneStringsWrapper())
1.634 + && ((localPatternChars != null
1.635 + && localPatternChars.equals(that.localPatternChars))
1.636 + || (localPatternChars == null
1.637 + && that.localPatternChars == null)));
1.638 + }
1.639 +
1.640 + // =======================privates===============================
1.641 +
1.642 + /**
1.643 + * Useful constant for defining time zone offsets.
1.644 + */
1.645 + static final int millisPerHour = 60*60*1000;
1.646 +
1.647 + /**
1.648 + * Cache to hold DateFormatSymbols instances per Locale.
1.649 + */
1.650 + private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
1.651 + = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
1.652 +
1.653 + private void initializeData(Locale desiredLocale) {
1.654 + locale = desiredLocale;
1.655 +
1.656 + // Copy values of a cached instance if any.
1.657 + SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
1.658 + DateFormatSymbols dfs;
1.659 + if (ref != null && (dfs = ref.get()) != null) {
1.660 + copyMembers(dfs, this);
1.661 + return;
1.662 + }
1.663 +
1.664 + // Initialize the fields from the ResourceBundle for locale.
1.665 + ResourceBundle resource = LocaleData.getDateFormatData(locale);
1.666 +
1.667 + eras = resource.getStringArray("Eras");
1.668 + months = resource.getStringArray("MonthNames");
1.669 + shortMonths = resource.getStringArray("MonthAbbreviations");
1.670 + ampms = resource.getStringArray("AmPmMarkers");
1.671 + localPatternChars = resource.getString("DateTimePatternChars");
1.672 +
1.673 + // Day of week names are stored in a 1-based array.
1.674 + weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
1.675 + shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
1.676 + }
1.677 +
1.678 + private static String[] toOneBasedArray(String[] src) {
1.679 + int len = src.length;
1.680 + String[] dst = new String[len + 1];
1.681 + dst[0] = "";
1.682 + for (int i = 0; i < len; i++) {
1.683 + dst[i + 1] = src[i];
1.684 + }
1.685 + return dst;
1.686 + }
1.687 +
1.688 + /**
1.689 + * Package private: used by SimpleDateFormat
1.690 + * Gets the index for the given time zone ID to obtain the time zone
1.691 + * strings for formatting. The time zone ID is just for programmatic
1.692 + * lookup. NOT LOCALIZED!!!
1.693 + * @param ID the given time zone ID.
1.694 + * @return the index of the given time zone ID. Returns -1 if
1.695 + * the given time zone ID can't be located in the DateFormatSymbols object.
1.696 + * @see java.util.SimpleTimeZone
1.697 + */
1.698 + final int getZoneIndex(String ID)
1.699 + {
1.700 + String[][] zoneStrings = getZoneStringsWrapper();
1.701 + for (int index=0; index<zoneStrings.length; index++)
1.702 + {
1.703 + if (ID.equals(zoneStrings[index][0])) return index;
1.704 + }
1.705 +
1.706 + return -1;
1.707 + }
1.708 +
1.709 + /**
1.710 + * Wrapper method to the getZoneStrings(), which is called from inside
1.711 + * the java.text package and not to mutate the returned arrays, so that
1.712 + * it does not need to create a defensive copy.
1.713 + */
1.714 + final String[][] getZoneStringsWrapper() {
1.715 + if (isSubclassObject()) {
1.716 + return getZoneStrings();
1.717 + } else {
1.718 + return getZoneStringsImpl(false);
1.719 + }
1.720 + }
1.721 +
1.722 + private final String[][] getZoneStringsImpl(boolean needsCopy) {
1.723 + if (zoneStrings == null) {
1.724 + zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
1.725 + }
1.726 +
1.727 + if (!needsCopy) {
1.728 + return zoneStrings;
1.729 + }
1.730 +
1.731 + int len = zoneStrings.length;
1.732 + String[][] aCopy = new String[len][];
1.733 + for (int i = 0; i < len; i++) {
1.734 + aCopy[i] = Arrays.copyOf(zoneStrings[i], zoneStrings[i].length);
1.735 + }
1.736 + return aCopy;
1.737 + }
1.738 +
1.739 + private final boolean isSubclassObject() {
1.740 + return !getClass().getName().equals("java.text.DateFormatSymbols");
1.741 + }
1.742 +
1.743 + /**
1.744 + * Clones all the data members from the source DateFormatSymbols to
1.745 + * the target DateFormatSymbols. This is only for subclasses.
1.746 + * @param src the source DateFormatSymbols.
1.747 + * @param dst the target DateFormatSymbols.
1.748 + */
1.749 + private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
1.750 + {
1.751 + dst.eras = Arrays.copyOf(src.eras, src.eras.length);
1.752 + dst.months = Arrays.copyOf(src.months, src.months.length);
1.753 + dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
1.754 + dst.weekdays = Arrays.copyOf(src.weekdays, src.weekdays.length);
1.755 + dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length);
1.756 + dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length);
1.757 + if (src.zoneStrings != null) {
1.758 + dst.zoneStrings = src.getZoneStringsImpl(true);
1.759 + } else {
1.760 + dst.zoneStrings = null;
1.761 + }
1.762 + dst.localPatternChars = src.localPatternChars;
1.763 + }
1.764 +
1.765 + /**
1.766 + * Write out the default serializable data, after ensuring the
1.767 + * <code>zoneStrings</code> field is initialized in order to make
1.768 + * sure the backward compatibility.
1.769 + *
1.770 + * @since 1.6
1.771 + */
1.772 + private void writeObject(ObjectOutputStream stream) throws IOException {
1.773 + if (zoneStrings == null) {
1.774 + zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
1.775 + }
1.776 + stream.defaultWriteObject();
1.777 + }
1.778 +
1.779 + /**
1.780 + * Obtains a DateFormatSymbols instance from a DateFormatSymbolsProvider
1.781 + * implementation.
1.782 + */
1.783 + private static class DateFormatSymbolsGetter
1.784 + implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatSymbolsProvider,
1.785 + DateFormatSymbols> {
1.786 + private static final DateFormatSymbolsGetter INSTANCE =
1.787 + new DateFormatSymbolsGetter();
1.788 +
1.789 + public DateFormatSymbols getObject(DateFormatSymbolsProvider dateFormatSymbolsProvider,
1.790 + Locale locale,
1.791 + String key,
1.792 + Object... params) {
1.793 + assert params.length == 0;
1.794 + return dateFormatSymbolsProvider.getInstance(locale);
1.795 + }
1.796 + }
1.797 +}