History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/text/DateFormatSymbols.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/text/DateFormatSymbols.java+794−0
@@ -0,0 +1,794 @@
1+/*
2+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+/*
27+ * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
28+ * (C) Copyright IBM Corp. 1996 - All Rights Reserved
29+ *
30+ * The original version of this source code and documentation is copyrighted
31+ * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32+ * materials are provided under terms of a License Agreement between Taligent
33+ * and Sun. This technology is protected by multiple US and International
34+ * patents. This notice and attribution to Taligent may not be removed.
35+ * Taligent is a registered trademark of Taligent, Inc.
36+ *
37+ */
38+
39+package java.text;
40+
41+import java.io.IOException;
42+import java.io.ObjectOutputStream;
43+import java.io.Serializable;
44+import java.lang.ref.SoftReference;
45+import java.text.spi.DateFormatSymbolsProvider;
46+import java.util.Arrays;
47+import java.util.List;
48+import java.util.Locale;
49+import java.util.ResourceBundle;
50+import java.util.TimeZone;
51+import java.util.concurrent.ConcurrentHashMap;
52+import java.util.concurrent.ConcurrentMap;
53+import java.util.spi.LocaleServiceProvider;
54+import sun.util.LocaleServiceProviderPool;
55+import sun.util.TimeZoneNameUtility;
56+import sun.util.calendar.ZoneInfo;
57+import sun.util.resources.LocaleData;
58+
59+/**
60+ * <code>DateFormatSymbols</code> is a public class for encapsulating
61+ * localizable date-time formatting data, such as the names of the
62+ * months, the names of the days of the week, and the time zone data.
63+ * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
64+ * <code>DateFormatSymbols</code> to encapsulate this information.
65+ *
66+ * <p>
67+ * Typically you shouldn't use <code>DateFormatSymbols</code> directly.
68+ * Rather, you are encouraged to create a date-time formatter with the
69+ * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
70+ * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
71+ * These methods automatically create a <code>DateFormatSymbols</code> for
72+ * the formatter so that you don't have to. After the
73+ * formatter is created, you may modify its format pattern using the
74+ * <code>setPattern</code> method. For more information about
75+ * creating formatters using <code>DateFormat</code>'s factory methods,
76+ * see {@link DateFormat}.
77+ *
78+ * <p>
79+ * If you decide to create a date-time formatter with a specific
80+ * format pattern for a specific locale, you can do so with:
81+ * <blockquote>
82+ * <pre>
83+ * new SimpleDateFormat(aPattern, DateFormatSymbols.getInstance(aLocale)).
84+ * </pre>
85+ * </blockquote>
86+ *
87+ * <p>
88+ * <code>DateFormatSymbols</code> objects are cloneable. When you obtain
89+ * a <code>DateFormatSymbols</code> object, feel free to modify the
90+ * date-time formatting data. For instance, you can replace the localized
91+ * date-time format pattern characters with the ones that you feel easy
92+ * to remember. Or you can change the representative cities
93+ * to your favorite ones.
94+ *
95+ * <p>
96+ * New <code>DateFormatSymbols</code> subclasses may be added to support
97+ * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
98+
99+ * @see DateFormat
100+ * @see SimpleDateFormat
101+ * @see java.util.SimpleTimeZone
102+ * @author Chen-Lieh Huang
103+ */
104+public class DateFormatSymbols implements Serializable, Cloneable {
105+
106+ /**
107+ * Construct a DateFormatSymbols object by loading format data from
108+ * resources for the default locale. This constructor can only
109+ * construct instances for the locales supported by the Java
110+ * runtime environment, not for those supported by installed
111+ * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
112+ * implementations. For full locale coverage, use the
113+ * {@link #getInstance(Locale) getInstance} method.
114+ *
115+ * @see #getInstance()
116+ * @exception java.util.MissingResourceException
117+ * if the resources for the default locale cannot be
118+ * found or cannot be loaded.
119+ */
120+ public DateFormatSymbols()
121+ {
122+ initializeData(Locale.getDefault(Locale.Category.FORMAT));
123+ }
124+
125+ /**
126+ * Construct a DateFormatSymbols object by loading format data from
127+ * resources for the given locale. This constructor can only
128+ * construct instances for the locales supported by the Java
129+ * runtime environment, not for those supported by installed
130+ * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
131+ * implementations. For full locale coverage, use the
132+ * {@link #getInstance(Locale) getInstance} method.
133+ *
134+ * @see #getInstance(Locale)
135+ * @exception java.util.MissingResourceException
136+ * if the resources for the specified locale cannot be
137+ * found or cannot be loaded.
138+ */
139+ public DateFormatSymbols(Locale locale)
140+ {
141+ initializeData(locale);
142+ }
143+
144+ /**
145+ * Era strings. For example: "AD" and "BC". An array of 2 strings,
146+ * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
147+ * @serial
148+ */
149+ String eras[] = null;
150+
151+ /**
152+ * Month strings. For example: "January", "February", etc. An array
153+ * of 13 strings (some calendars have 13 months), indexed by
154+ * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
155+ * @serial
156+ */
157+ String months[] = null;
158+
159+ /**
160+ * Short month strings. For example: "Jan", "Feb", etc. An array of
161+ * 13 strings (some calendars have 13 months), indexed by
162+ * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
163+
164+ * @serial
165+ */
166+ String shortMonths[] = null;
167+
168+ /**
169+ * Weekday strings. For example: "Sunday", "Monday", etc. An array
170+ * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
171+ * <code>Calendar.MONDAY</code>, etc.
172+ * The element <code>weekdays[0]</code> is ignored.
173+ * @serial
174+ */
175+ String weekdays[] = null;
176+
177+ /**
178+ * Short weekday strings. For example: "Sun", "Mon", etc. An array
179+ * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
180+ * <code>Calendar.MONDAY</code>, etc.
181+ * The element <code>shortWeekdays[0]</code> is ignored.
182+ * @serial
183+ */
184+ String shortWeekdays[] = null;
185+
186+ /**
187+ * AM and PM strings. For example: "AM" and "PM". An array of
188+ * 2 strings, indexed by <code>Calendar.AM</code> and
189+ * <code>Calendar.PM</code>.
190+ * @serial
191+ */
192+ String ampms[] = null;
193+
194+ /**
195+ * Localized names of time zones in this locale. This is a
196+ * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
197+ * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
198+ * entry containing the localized names for a single <code>TimeZone</code>.
199+ * Each such row contains (with <code>i</code> ranging from
200+ * 0..<em>n</em>-1):
201+ * <ul>
202+ * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
203+ * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
204+ * time</li>
205+ * <li><code>zoneStrings[i][2]</code> - short name of zone in
206+ * standard time</li>
207+ * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
208+ * saving time</li>
209+ * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
210+ * saving time</li>
211+ * </ul>
212+ * The zone ID is <em>not</em> localized; it's one of the valid IDs of
213+ * the {@link java.util.TimeZone TimeZone} class that are not
214+ * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
215+ * All other entries are localized names.
216+ * @see java.util.TimeZone
217+ * @serial
218+ */
219+ String zoneStrings[][] = null;
220+
221+ /**
222+ * Indicates that zoneStrings is set externally with setZoneStrings() method.
223+ */
224+ transient boolean isZoneStringsSet = false;
225+
226+ /**
227+ * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
228+ * All locales use the same these unlocalized pattern characters.
229+ */
230+ static final String patternChars = "GyMdkHmsSEDFwWahKzZYuX";
231+
232+ static final int PATTERN_ERA = 0; // G
233+ static final int PATTERN_YEAR = 1; // y
234+ static final int PATTERN_MONTH = 2; // M
235+ static final int PATTERN_DAY_OF_MONTH = 3; // d
236+ static final int PATTERN_HOUR_OF_DAY1 = 4; // k
237+ static final int PATTERN_HOUR_OF_DAY0 = 5; // H
238+ static final int PATTERN_MINUTE = 6; // m
239+ static final int PATTERN_SECOND = 7; // s
240+ static final int PATTERN_MILLISECOND = 8; // S
241+ static final int PATTERN_DAY_OF_WEEK = 9; // E
242+ static final int PATTERN_DAY_OF_YEAR = 10; // D
243+ static final int PATTERN_DAY_OF_WEEK_IN_MONTH = 11; // F
244+ static final int PATTERN_WEEK_OF_YEAR = 12; // w
245+ static final int PATTERN_WEEK_OF_MONTH = 13; // W
246+ static final int PATTERN_AM_PM = 14; // a
247+ static final int PATTERN_HOUR1 = 15; // h
248+ static final int PATTERN_HOUR0 = 16; // K
249+ static final int PATTERN_ZONE_NAME = 17; // z
250+ static final int PATTERN_ZONE_VALUE = 18; // Z
251+ static final int PATTERN_WEEK_YEAR = 19; // Y
252+ static final int PATTERN_ISO_DAY_OF_WEEK = 20; // u
253+ static final int PATTERN_ISO_ZONE = 21; // X
254+
255+ /**
256+ * Localized date-time pattern characters. For example, a locale may
257+ * wish to use 'u' rather than 'y' to represent years in its date format
258+ * pattern strings.
259+ * This string must be exactly 18 characters long, with the index of
260+ * the characters described by <code>DateFormat.ERA_FIELD</code>,
261+ * <code>DateFormat.YEAR_FIELD</code>, etc. Thus, if the string were
262+ * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
263+ * @serial
264+ */
265+ String localPatternChars = null;
266+
267+ /**
268+ * The locale which is used for initializing this DateFormatSymbols object.
269+ *
270+ * @since 1.6
271+ * @serial
272+ */
273+ Locale locale = null;
274+
275+ /* use serialVersionUID from JDK 1.1.4 for interoperability */
276+ static final long serialVersionUID = -5987973545549424702L;
277+
278+ /**
279+ * Returns an array of all locales for which the
280+ * <code>getInstance</code> methods of this class can return
281+ * localized instances.
282+ * The returned array represents the union of locales supported by the
283+ * Java runtime and by installed
284+ * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
285+ * implementations. It must contain at least a <code>Locale</code>
286+ * instance equal to {@link java.util.Locale#US Locale.US}.
287+ *
288+ * @return An array of locales for which localized
289+ * <code>DateFormatSymbols</code> instances are available.
290+ * @since 1.6
291+ */
292+ public static Locale[] getAvailableLocales() {
293+ LocaleServiceProviderPool pool=
294+ LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
295+ return pool.getAvailableLocales();
296+ }
297+
298+ /**
299+ * Gets the <code>DateFormatSymbols</code> instance for the default
300+ * locale. This method provides access to <code>DateFormatSymbols</code>
301+ * instances for locales supported by the Java runtime itself as well
302+ * as for those supported by installed
303+ * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
304+ * implementations.
305+ * @return a <code>DateFormatSymbols</code> instance.
306+ * @since 1.6
307+ */
308+ public static final DateFormatSymbols getInstance() {
309+ return getInstance(Locale.getDefault(Locale.Category.FORMAT));
310+ }
311+
312+ /**
313+ * Gets the <code>DateFormatSymbols</code> instance for the specified
314+ * locale. This method provides access to <code>DateFormatSymbols</code>
315+ * instances for locales supported by the Java runtime itself as well
316+ * as for those supported by installed
317+ * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
318+ * implementations.
319+ * @param locale the given locale.
320+ * @return a <code>DateFormatSymbols</code> instance.
321+ * @exception NullPointerException if <code>locale</code> is null
322+ * @since 1.6
323+ */
324+ public static final DateFormatSymbols getInstance(Locale locale) {
325+ DateFormatSymbols dfs = getProviderInstance(locale);
326+ if (dfs != null) {
327+ return dfs;
328+ }
329+ return (DateFormatSymbols) getCachedInstance(locale).clone();
330+ }
331+
332+ /**
333+ * Returns a DateFormatSymbols provided by a provider or found in
334+ * the cache. Note that this method returns a cached instance,
335+ * not its clone. Therefore, the instance should never be given to
336+ * an application.
337+ */
338+ static final DateFormatSymbols getInstanceRef(Locale locale) {
339+ DateFormatSymbols dfs = getProviderInstance(locale);
340+ if (dfs != null) {
341+ return dfs;
342+ }
343+ return getCachedInstance(locale);
344+ }
345+
346+ private static DateFormatSymbols getProviderInstance(Locale locale) {
347+ DateFormatSymbols providersInstance = null;
348+
349+ // Check whether a provider can provide an implementation that's closer
350+ // to the requested locale than what the Java runtime itself can provide.
351+ LocaleServiceProviderPool pool =
352+ LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
353+ if (pool.hasProviders()) {
354+ providersInstance = pool.getLocalizedObject(
355+ DateFormatSymbolsGetter.INSTANCE, locale);
356+ }
357+ return providersInstance;
358+ }
359+
360+ /**
361+ * Returns a cached DateFormatSymbols if it's found in the
362+ * cache. Otherwise, this method returns a newly cached instance
363+ * for the given locale.
364+ */
365+ private static DateFormatSymbols getCachedInstance(Locale locale) {
366+ SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
367+ DateFormatSymbols dfs = null;
368+ if (ref == null || (dfs = ref.get()) == null) {
369+ dfs = new DateFormatSymbols(locale);
370+ ref = new SoftReference<DateFormatSymbols>(dfs);
371+ SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
372+ if (x != null) {
373+ DateFormatSymbols y = x.get();
374+ if (y != null) {
375+ dfs = y;
376+ } else {
377+ // Replace the empty SoftReference with ref.
378+ cachedInstances.put(locale, ref);
379+ }
380+ }
381+ }
382+ return dfs;
383+ }
384+
385+ /**
386+ * Gets era strings. For example: "AD" and "BC".
387+ * @return the era strings.
388+ */
389+ public String[] getEras() {
390+ return Arrays.copyOf(eras, eras.length);
391+ }
392+
393+ /**
394+ * Sets era strings. For example: "AD" and "BC".
395+ * @param newEras the new era strings.
396+ */
397+ public void setEras(String[] newEras) {
398+ eras = Arrays.copyOf(newEras, newEras.length);
399+ }
400+
401+ /**
402+ * Gets month strings. For example: "January", "February", etc.
403+ * @return the month strings.
404+ */
405+ public String[] getMonths() {
406+ return Arrays.copyOf(months, months.length);
407+ }
408+
409+ /**
410+ * Sets month strings. For example: "January", "February", etc.
411+ * @param newMonths the new month strings.
412+ */
413+ public void setMonths(String[] newMonths) {
414+ months = Arrays.copyOf(newMonths, newMonths.length);
415+ }
416+
417+ /**
418+ * Gets short month strings. For example: "Jan", "Feb", etc.
419+ * @return the short month strings.
420+ */
421+ public String[] getShortMonths() {
422+ return Arrays.copyOf(shortMonths, shortMonths.length);
423+ }
424+
425+ /**
426+ * Sets short month strings. For example: "Jan", "Feb", etc.
427+ * @param newShortMonths the new short month strings.
428+ */
429+ public void setShortMonths(String[] newShortMonths) {
430+ shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
431+ }
432+
433+ /**
434+ * Gets weekday strings. For example: "Sunday", "Monday", etc.
435+ * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
436+ * <code>Calendar.MONDAY</code>, etc. to index the result array.
437+ */
438+ public String[] getWeekdays() {
439+ return Arrays.copyOf(weekdays, weekdays.length);
440+ }
441+
442+ /**
443+ * Sets weekday strings. For example: "Sunday", "Monday", etc.
444+ * @param newWeekdays the new weekday strings. The array should
445+ * be indexed by <code>Calendar.SUNDAY</code>,
446+ * <code>Calendar.MONDAY</code>, etc.
447+ */
448+ public void setWeekdays(String[] newWeekdays) {
449+ weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
450+ }
451+
452+ /**
453+ * Gets short weekday strings. For example: "Sun", "Mon", etc.
454+ * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
455+ * <code>Calendar.MONDAY</code>, etc. to index the result array.
456+ */
457+ public String[] getShortWeekdays() {
458+ return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
459+ }
460+
461+ /**
462+ * Sets short weekday strings. For example: "Sun", "Mon", etc.
463+ * @param newShortWeekdays the new short weekday strings. The array should
464+ * be indexed by <code>Calendar.SUNDAY</code>,
465+ * <code>Calendar.MONDAY</code>, etc.
466+ */
467+ public void setShortWeekdays(String[] newShortWeekdays) {
468+ shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
469+ }
470+
471+ /**
472+ * Gets ampm strings. For example: "AM" and "PM".
473+ * @return the ampm strings.
474+ */
475+ public String[] getAmPmStrings() {
476+ return Arrays.copyOf(ampms, ampms.length);
477+ }
478+
479+ /**
480+ * Sets ampm strings. For example: "AM" and "PM".
481+ * @param newAmpms the new ampm strings.
482+ */
483+ public void setAmPmStrings(String[] newAmpms) {
484+ ampms = Arrays.copyOf(newAmpms, newAmpms.length);
485+ }
486+
487+ /**
488+ * Gets time zone strings. Use of this method is discouraged; use
489+ * {@link java.util.TimeZone#getDisplayName() TimeZone.getDisplayName()}
490+ * instead.
491+ * <p>
492+ * The value returned is a
493+ * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
494+ * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
495+ * entry containing the localized names for a single <code>TimeZone</code>.
496+ * Each such row contains (with <code>i</code> ranging from
497+ * 0..<em>n</em>-1):
498+ * <ul>
499+ * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
500+ * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
501+ * time</li>
502+ * <li><code>zoneStrings[i][2]</code> - short name of zone in
503+ * standard time</li>
504+ * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
505+ * saving time</li>
506+ * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
507+ * saving time</li>
508+ * </ul>
509+ * The zone ID is <em>not</em> localized; it's one of the valid IDs of
510+ * the {@link java.util.TimeZone TimeZone} class that are not
511+ * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
512+ * All other entries are localized names. If a zone does not implement
513+ * daylight saving time, the daylight saving time names should not be used.
514+ * <p>
515+ * If {@link #setZoneStrings(String[][]) setZoneStrings} has been called
516+ * on this <code>DateFormatSymbols</code> instance, then the strings
517+ * provided by that call are returned. Otherwise, the returned array
518+ * contains names provided by the Java runtime and by installed
519+ * {@link java.util.spi.TimeZoneNameProvider TimeZoneNameProvider}
520+ * implementations.
521+ *
522+ * @return the time zone strings.
523+ * @see #setZoneStrings(String[][])
524+ */
525+ public String[][] getZoneStrings() {
526+ return getZoneStringsImpl(true);
527+ }
528+
529+ /**
530+ * Sets time zone strings. The argument must be a
531+ * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
532+ * where <em>m</em> is at least 5. Each of the <em>n</em> rows is an
533+ * entry containing the localized names for a single <code>TimeZone</code>.
534+ * Each such row contains (with <code>i</code> ranging from
535+ * 0..<em>n</em>-1):
536+ * <ul>
537+ * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
538+ * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
539+ * time</li>
540+ * <li><code>zoneStrings[i][2]</code> - short name of zone in
541+ * standard time</li>
542+ * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
543+ * saving time</li>
544+ * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
545+ * saving time</li>
546+ * </ul>
547+ * The zone ID is <em>not</em> localized; it's one of the valid IDs of
548+ * the {@link java.util.TimeZone TimeZone} class that are not
549+ * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
550+ * All other entries are localized names.
551+ *
552+ * @param newZoneStrings the new time zone strings.
553+ * @exception IllegalArgumentException if the length of any row in
554+ * <code>newZoneStrings</code> is less than 5
555+ * @exception NullPointerException if <code>newZoneStrings</code> is null
556+ * @see #getZoneStrings()
557+ */
558+ public void setZoneStrings(String[][] newZoneStrings) {
559+ String[][] aCopy = new String[newZoneStrings.length][];
560+ for (int i = 0; i < newZoneStrings.length; ++i) {
561+ int len = newZoneStrings[i].length;
562+ if (len < 5) {
563+ throw new IllegalArgumentException();
564+ }
565+ aCopy[i] = Arrays.copyOf(newZoneStrings[i], len);
566+ }
567+ zoneStrings = aCopy;
568+ isZoneStringsSet = true;
569+ }
570+
571+ /**
572+ * Gets localized date-time pattern characters. For example: 'u', 't', etc.
573+ * @return the localized date-time pattern characters.
574+ */
575+ public String getLocalPatternChars() {
576+ return localPatternChars;
577+ }
578+
579+ /**
580+ * Sets localized date-time pattern characters. For example: 'u', 't', etc.
581+ * @param newLocalPatternChars the new localized date-time
582+ * pattern characters.
583+ */
584+ public void setLocalPatternChars(String newLocalPatternChars) {
585+ // Call toString() to throw an NPE in case the argument is null
586+ localPatternChars = newLocalPatternChars.toString();
587+ }
588+
589+ /**
590+ * Overrides Cloneable
591+ */
592+ public Object clone()
593+ {
594+ try
595+ {
596+ DateFormatSymbols other = (DateFormatSymbols)super.clone();
597+ copyMembers(this, other);
598+ return other;
599+ } catch (CloneNotSupportedException e) {
600+ throw new InternalError();
601+ }
602+ }
603+
604+ /**
605+ * Override hashCode.
606+ * Generates a hash code for the DateFormatSymbols object.
607+ */
608+ public int hashCode() {
609+ int hashcode = 0;
610+ String[][] zoneStrings = getZoneStringsWrapper();
611+ for (int index = 0; index < zoneStrings[0].length; ++index)
612+ hashcode ^= zoneStrings[0][index].hashCode();
613+ return hashcode;
614+ }
615+
616+ /**
617+ * Override equals
618+ */
619+ public boolean equals(Object obj)
620+ {
621+ if (this == obj) return true;
622+ if (obj == null || getClass() != obj.getClass()) return false;
623+ DateFormatSymbols that = (DateFormatSymbols) obj;
624+ return (Arrays.equals(eras, that.eras)
625+ && Arrays.equals(months, that.months)
626+ && Arrays.equals(shortMonths, that.shortMonths)
627+ && Arrays.equals(weekdays, that.weekdays)
628+ && Arrays.equals(shortWeekdays, that.shortWeekdays)
629+ && Arrays.equals(ampms, that.ampms)
630+ && Arrays.deepEquals(getZoneStringsWrapper(), that.getZoneStringsWrapper())
631+ && ((localPatternChars != null
632+ && localPatternChars.equals(that.localPatternChars))
633+ || (localPatternChars == null
634+ && that.localPatternChars == null)));
635+ }
636+
637+ // =======================privates===============================
638+
639+ /**
640+ * Useful constant for defining time zone offsets.
641+ */
642+ static final int millisPerHour = 60*60*1000;
643+
644+ /**
645+ * Cache to hold DateFormatSymbols instances per Locale.
646+ */
647+ private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
648+ = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
649+
650+ private void initializeData(Locale desiredLocale) {
651+ locale = desiredLocale;
652+
653+ // Copy values of a cached instance if any.
654+ SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
655+ DateFormatSymbols dfs;
656+ if (ref != null && (dfs = ref.get()) != null) {
657+ copyMembers(dfs, this);
658+ return;
659+ }
660+
661+ // Initialize the fields from the ResourceBundle for locale.
662+ ResourceBundle resource = LocaleData.getDateFormatData(locale);
663+
664+ eras = resource.getStringArray("Eras");
665+ months = resource.getStringArray("MonthNames");
666+ shortMonths = resource.getStringArray("MonthAbbreviations");
667+ ampms = resource.getStringArray("AmPmMarkers");
668+ localPatternChars = resource.getString("DateTimePatternChars");
669+
670+ // Day of week names are stored in a 1-based array.
671+ weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
672+ shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
673+ }
674+
675+ private static String[] toOneBasedArray(String[] src) {
676+ int len = src.length;
677+ String[] dst = new String[len + 1];
678+ dst[0] = "";
679+ for (int i = 0; i < len; i++) {
680+ dst[i + 1] = src[i];
681+ }
682+ return dst;
683+ }
684+
685+ /**
686+ * Package private: used by SimpleDateFormat
687+ * Gets the index for the given time zone ID to obtain the time zone
688+ * strings for formatting. The time zone ID is just for programmatic
689+ * lookup. NOT LOCALIZED!!!
690+ * @param ID the given time zone ID.
691+ * @return the index of the given time zone ID. Returns -1 if
692+ * the given time zone ID can't be located in the DateFormatSymbols object.
693+ * @see java.util.SimpleTimeZone
694+ */
695+ final int getZoneIndex(String ID)
696+ {
697+ String[][] zoneStrings = getZoneStringsWrapper();
698+ for (int index=0; index<zoneStrings.length; index++)
699+ {
700+ if (ID.equals(zoneStrings[index][0])) return index;
701+ }
702+
703+ return -1;
704+ }
705+
706+ /**
707+ * Wrapper method to the getZoneStrings(), which is called from inside
708+ * the java.text package and not to mutate the returned arrays, so that
709+ * it does not need to create a defensive copy.
710+ */
711+ final String[][] getZoneStringsWrapper() {
712+ if (isSubclassObject()) {
713+ return getZoneStrings();
714+ } else {
715+ return getZoneStringsImpl(false);
716+ }
717+ }
718+
719+ private final String[][] getZoneStringsImpl(boolean needsCopy) {
720+ if (zoneStrings == null) {
721+ zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
722+ }
723+
724+ if (!needsCopy) {
725+ return zoneStrings;
726+ }
727+
728+ int len = zoneStrings.length;
729+ String[][] aCopy = new String[len][];
730+ for (int i = 0; i < len; i++) {
731+ aCopy[i] = Arrays.copyOf(zoneStrings[i], zoneStrings[i].length);
732+ }
733+ return aCopy;
734+ }
735+
736+ private final boolean isSubclassObject() {
737+ return !getClass().getName().equals("java.text.DateFormatSymbols");
738+ }
739+
740+ /**
741+ * Clones all the data members from the source DateFormatSymbols to
742+ * the target DateFormatSymbols. This is only for subclasses.
743+ * @param src the source DateFormatSymbols.
744+ * @param dst the target DateFormatSymbols.
745+ */
746+ private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
747+ {
748+ dst.eras = Arrays.copyOf(src.eras, src.eras.length);
749+ dst.months = Arrays.copyOf(src.months, src.months.length);
750+ dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
751+ dst.weekdays = Arrays.copyOf(src.weekdays, src.weekdays.length);
752+ dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length);
753+ dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length);
754+ if (src.zoneStrings != null) {
755+ dst.zoneStrings = src.getZoneStringsImpl(true);
756+ } else {
757+ dst.zoneStrings = null;
758+ }
759+ dst.localPatternChars = src.localPatternChars;
760+ }
761+
762+ /**
763+ * Write out the default serializable data, after ensuring the
764+ * <code>zoneStrings</code> field is initialized in order to make
765+ * sure the backward compatibility.
766+ *
767+ * @since 1.6
768+ */
769+ private void writeObject(ObjectOutputStream stream) throws IOException {
770+ if (zoneStrings == null) {
771+ zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
772+ }
773+ stream.defaultWriteObject();
774+ }
775+
776+ /**
777+ * Obtains a DateFormatSymbols instance from a DateFormatSymbolsProvider
778+ * implementation.
779+ */
780+ private static class DateFormatSymbolsGetter
781+ implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatSymbolsProvider,
782+ DateFormatSymbols> {
783+ private static final DateFormatSymbolsGetter INSTANCE =
784+ new DateFormatSymbolsGetter();
785+
786+ public DateFormatSymbols getObject(DateFormatSymbolsProvider dateFormatSymbolsProvider,
787+ Locale locale,
788+ String key,
789+ Object... params) {
790+ assert params.length == 0;
791+ return dateFormatSymbolsProvider.getInstance(locale);
792+ }
793+ }
794+}