diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/sun/util/calendar/CalendarSystem.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/util/calendar/CalendarSystem.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,357 @@ +/* + * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.util.calendar; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * CalendarSystem is an abstract class that defines the + * programming interface to deal with calendar date and time. + * + *

CalendarSystem instances are singletons. For + * example, there exists only one Gregorian calendar instance in the + * Java runtime environment. A singleton instance can be obtained + * calling one of the static factory methods. + * + *

CalendarDate

+ * + *

For the methods in a CalendarSystem that manipulate + * a CalendarDate, CalendarDates that have + * been created by the CalendarSystem must be + * specified. Otherwise, the methods throw an exception. This is + * because, for example, a Chinese calendar date can't be understood + * by the Hebrew calendar system. + * + *

Calendar names

+ * + * Each calendar system has a unique name to be identified. The Java + * runtime in this release supports the following calendar systems. + * + *
+ *  Name          Calendar System
+ *  ---------------------------------------
+ *  gregorian     Gregorian Calendar
+ *  julian        Julian Calendar
+ *  japanese      Japanese Imperial Calendar
+ * 
+ * + * @see CalendarDate + * @author Masayoshi Okutsu + * @since 1.5 + */ + +public abstract class CalendarSystem { + + /////////////////////// Calendar Factory Methods ///////////////////////// + + private volatile static boolean initialized = false; + + // Map of calendar names and calendar class names + private static ConcurrentMap names; + + // Map of calendar names and CalendarSystem instances + private static ConcurrentMap calendars; + + private static final String PACKAGE_NAME = "sun.util.calendar."; + + private static final String[] namePairs = { + "gregorian", "Gregorian", + "japanese", "LocalGregorianCalendar", + "julian", "JulianCalendar", + /* + "hebrew", "HebrewCalendar", + "iso8601", "ISOCalendar", + "taiwanese", "LocalGregorianCalendar", + "thaibuddhist", "LocalGregorianCalendar", + */ + }; + + private static void initNames() { + ConcurrentMap nameMap = new ConcurrentHashMap(); + + // Associate a calendar name with its class name and the + // calendar class name with its date class name. + StringBuilder clName = new StringBuilder(); + for (int i = 0; i < namePairs.length; i += 2) { + clName.setLength(0); + String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString(); + nameMap.put(namePairs[i], cl); + } + synchronized (CalendarSystem.class) { + if (!initialized) { + names = nameMap; + calendars = new ConcurrentHashMap(); + initialized = true; + } + } + } + + private final static Gregorian GREGORIAN_INSTANCE = new Gregorian(); + + /** + * Returns the singleton instance of the Gregorian + * calendar system. + * + * @return the Gregorian instance + */ + public static Gregorian getGregorianCalendar() { + return GREGORIAN_INSTANCE; + } + + /** + * Returns a CalendarSystem specified by the calendar + * name. The calendar name has to be one of the supported calendar + * names. + * + * @param calendarName the calendar name + * @return the CalendarSystem specified by + * calendarName, or null if there is no + * CalendarSystem associated with the given calendar name. + */ + public static CalendarSystem forName(String calendarName) { + if ("gregorian".equals(calendarName)) { + return GREGORIAN_INSTANCE; + } + + if (!initialized) { + initNames(); + } + + CalendarSystem cal = calendars.get(calendarName); + if (cal != null) { + return cal; + } + + String className = names.get(calendarName); + if (className == null) { + return null; // Unknown calendar name + } + + if (className.endsWith("LocalGregorianCalendar")) { + // Create the specific kind of local Gregorian calendar system + cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName); + } else { + try { + Class cl = Class.forName(className); + cal = (CalendarSystem) cl.newInstance(); + } catch (Exception e) { + throw new RuntimeException("internal error", e); + } + } + if (cal == null) { + return null; + } + CalendarSystem cs = calendars.putIfAbsent(calendarName, cal); + return (cs == null) ? cal : cs; + } + + //////////////////////////////// Calendar API ////////////////////////////////// + + /** + * Returns the name of this calendar system. + */ + public abstract String getName(); + + public abstract CalendarDate getCalendarDate(); + + /** + * Calculates calendar fields from the specified number of + * milliseconds since the Epoch, January 1, 1970 00:00:00 UTC + * (Gregorian). This method doesn't check overflow or underflow + * when adjusting the millisecond value (representing UTC) with + * the time zone offsets (i.e., the GMT offset and amount of + * daylight saving). + * + * @param millis the offset value in milliseconds from January 1, + * 1970 00:00:00 UTC (Gregorian). + * @return a CalendarDate instance that contains the + * calculated calendar field values. + */ + public abstract CalendarDate getCalendarDate(long millis); + + public abstract CalendarDate getCalendarDate(long millis, CalendarDate date); + + public abstract CalendarDate getCalendarDate(long millis, TimeZone zone); + + /** + * Constructs a CalendarDate that is specific to this + * calendar system. All calendar fields have their initial + * values. The {@link TimeZone#getDefault() default time zone} is + * set to the instance. + * + * @return a CalendarDate instance that contains the initial + * calendar field values. + */ + public abstract CalendarDate newCalendarDate(); + + public abstract CalendarDate newCalendarDate(TimeZone zone); + + /** + * Returns the number of milliseconds since the Epoch, January 1, + * 1970 00:00:00 UTC (Gregorian), represented by the specified + * CalendarDate. + * + * @param date the CalendarDate from which the time + * value is calculated + * @return the number of milliseconds since the Epoch. + */ + public abstract long getTime(CalendarDate date); + + /** + * Returns the length in days of the specified year by + * date. This method does not perform the + * normalization with the specified CalendarDate. The + * CalendarDate must be normalized to get a correct + * value. + */ + public abstract int getYearLength(CalendarDate date); + + /** + * Returns the number of months of the specified year. This method + * does not perform the normalization with the specified + * CalendarDate. The CalendarDate must + * be normalized to get a correct value. + */ + public abstract int getYearLengthInMonths(CalendarDate date); + + /** + * Returns the length in days of the month specified by the calendar + * date. This method does not perform the normalization with the + * specified calendar date. The CalendarDate must + * be normalized to get a correct value. + * + * @param date the date from which the month value is obtained + * @return the number of days in the month + * @exception IllegalArgumentException if the specified calendar date + * doesn't have a valid month value in this calendar system. + */ + public abstract int getMonthLength(CalendarDate date); // no setter + + /** + * Returns the length in days of a week in this calendar + * system. If this calendar system has multiple radix weeks, this + * method returns only one of them. + */ + public abstract int getWeekLength(); + + /** + * Returns the Era designated by the era name that + * has to be known to this calendar system. If no Era is + * applicable to this calendar system, null is returned. + * + * @param eraName the name of the era + * @return the Era designated by + * eraName, or null if no Era is + * applicable to this calendar system or the specified era name is + * not known to this calendar system. + */ + public abstract Era getEra(String eraName); + + /** + * Returns valid Eras of this calendar system. The + * return value is sorted in the descendant order. (i.e., the first + * element of the returned array is the oldest era.) If no era is + * applicable to this calendar system, null is returned. + * + * @return an array of valid Eras, or + * null if no era is applicable to this calendar + * system. + */ + public abstract Era[] getEras(); + + /** + * @throws IllegalArgumentException if the specified era name is + * unknown to this calendar system. + * @see Era + */ + public abstract void setEra(CalendarDate date, String eraName); + + /** + * Returns a CalendarDate of the n-th day of week + * which is on, after or before the specified date. For example, the + * first Sunday in April 2002 (Gregorian) can be obtained as + * below: + * + *

+     * Gregorian cal = CalendarSystem.getGregorianCalendar();
+     * CalendarDate date = cal.newCalendarDate();
+     * date.setDate(2004, cal.APRIL, 1);
+     * CalendarDate firstSun = cal.getNthDayOfWeek(1, cal.SUNDAY, date);
+     * // firstSun represents April 4, 2004.
+     * 
+ * + * This method returns a new CalendarDate instance + * and doesn't modify the original date. + * + * @param nth specifies the n-th one. A positive number specifies + * on or after the date. A non-positive number + * specifies on or before the date. + * @param dayOfWeek the day of week + * @param date the date + * @return the date of the nth dayOfWeek after + * or before the specified CalendarDate + */ + public abstract CalendarDate getNthDayOfWeek(int nth, int dayOfWeek, + CalendarDate date); + + public abstract CalendarDate setTimeOfDay(CalendarDate date, int timeOfDay); + + /** + * Checks whether the calendar fields specified by date + * represents a valid date and time in this calendar system. If the + * given date is valid, date is marked as normalized. + * + * @param date the CalendarDate to be validated + * @return true if all the calendar fields are consistent, + * otherwise, false is returned. + * @exception NullPointerException if the specified + * date is null + */ + public abstract boolean validate(CalendarDate date); + + /** + * Normalizes calendar fields in the specified + * date. Also all {@link CalendarDate#FIELD_UNDEFINED + * undefined} fields are set to correct values. The actual + * normalization process is calendar system dependent. + * + * @param date the calendar date to be validated + * @return true if all fields have been normalized; + * false otherwise. + * @exception NullPointerException if the specified + * date is null + */ + public abstract boolean normalize(CalendarDate date); +}