/*
 *******************************************************************************
 * Copyright (C) 1996-2005, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.text;

import com.ibm.icu.impl.ICULocaleData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.impl.ZoneMeta;
import com.ibm.icu.util.ULocale;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * <code>DateFormatSymbols</code> is a public class for encapsulating
 * localizable date-time formatting data, such as the names of the
 * months, the names of the days of the week, and the time zone data.
 * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
 * <code>DateFormatSymbols</code> to encapsulate this information.
 *
 * <p>
 * Typically you shouldn't use <code>DateFormatSymbols</code> directly.
 * Rather, you are encouraged to create a date-time formatter with the
 * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
 * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
 * These methods automatically create a <code>DateFormatSymbols</code> for
 * the formatter so that you don't have to. After the
 * formatter is created, you may modify its format pattern using the
 * <code>setPattern</code> method. For more information about
 * creating formatters using <code>DateFormat</code>'s factory methods,
 * see {@link DateFormat}.
 *
 * <p>
 * If you decide to create a date-time formatter with a specific
 * format pattern for a specific locale, you can do so with:
 * <blockquote>
 * <pre>
 * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
 * </pre>
 * </blockquote>
 *
 * <p>
 * <code>DateFormatSymbols</code> objects are clonable. When you obtain
 * a <code>DateFormatSymbols</code> object, feel free to modify the
 * date-time formatting data. For instance, you can replace the localized
 * date-time format pattern characters with the ones that you feel easy
 * to remember. Or you can change the representative cities
 * to your favorite ones.
 *
 * <p>
 * New <code>DateFormatSymbols</code> subclasses may be added to support
 * <code>SimpleDateFormat</code> for date-time formatting for additional locales.

 * @see          DateFormat
 * @see          SimpleDateFormat
 * @see          com.ibm.icu.util.SimpleTimeZone
 * @author       Chen-Lieh Huang
 * @stable ICU 2.0
 */
public class DateFormatSymbols implements Serializable, Cloneable {

    // TODO make sure local pattern char string is 18 characters long,
    // that is, that it encompasses the new 'u' char for
    // EXTENDED_YEAR.  Two options: 1. Make sure resource data is
    // correct; 2. Make code add in 'u' at end if len == 17.

    // Constants for context
    /**
     * Constant for context.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int FORMAT = 0;

    /**
     * Constant for context.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int STANDALONE = 1;

    /**
     * Constant for context.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int DT_CONTEXT_COUNT = 2;

    // Constants for width

    /**
     * Constant for width.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int ABBREVIATED = 0;

    /**
     * Constant for width.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int WIDE = 1;

    /**
     * Constant for width.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int NARROW = 2;

    /**
     * Constant for width.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static final int DT_WIDTH_COUNT = 3;

    /**
     * Construct a DateFormatSymbols object by loading format data from
     * resources for the default locale.
     *
     * @throws  java.util.MissingResourceException
     *          if the resources for the default locale cannot be
     *          found or cannot be loaded.
     * @stable ICU 2.0
     */
    public DateFormatSymbols()
    {
        initializeData(ULocale.getDefault(), ""); // TODO: type?
    }
    
    /**
     * Construct a DateFormatSymbols object by loading format data from
     * resources for the given locale.
     *
     * @throws  java.util.MissingResourceException
     *          if the resources for the specified locale cannot be
     *          found or cannot be loaded.
     * @stable ICU 2.0
     */
    public DateFormatSymbols(Locale locale)
    {
        initializeData(ULocale.forLocale(locale), ""); // TODO: type?
    }

    /**
     * Construct a DateFormatSymbols object by loading format data from
     * resources for the given ulocale.
     *
     * @throws  java.util.MissingResourceException
     *          if the resources for the specified locale cannot be
     *          found or cannot be loaded.
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public DateFormatSymbols(ULocale locale)
    {
        initializeData(locale, ""); // TODO: type?
    }

    /**
     * Era strings. For example: "AD" and "BC".  An array of 2 strings,
     * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
     * @serial
     */
    String eras[] = null;

    /**
     * Era name strings. For example: "Anno Domini" and "Before Christ".  An array of 2 strings,
     * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
     * @serial
     */
    String eraNames[] = null;

    /**
     * Month strings. For example: "January", "February", etc.  An array
     * of 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
     * @serial
     */
    String months[] = null;

    /**
     * Short month strings. For example: "Jan", "Feb", etc.  An array of
     * 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.

     * @serial
     */
    String shortMonths[] = null;

    /**
     * Narrow month strings. For example: "J", "F", etc.  An array of
     * 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.

     * @serial
     */
    String narrowMonths[] = null;

    /**
     * Standalone month strings. For example: "January", "February", etc.  An array
     * of 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
     * @serial
     */
    String standaloneMonths[] = null;

    /**
     * Standalone short month strings. For example: "Jan", "Feb", etc.  An array of
     * 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.

     * @serial
     */
    String standaloneShortMonths[] = null;

    /**
     * Standalone narrow month strings. For example: "J", "F", etc.  An array of
     * 13 strings (some calendars have 13 months), indexed by
     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.

     * @serial
     */
    String standaloneNarrowMonths[] = null;

    /**
     * Weekday strings. For example: "Sunday", "Monday", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>weekdays[0]</code> is ignored.
     * @serial
     */
    String weekdays[] = null;

    /**
     * Short weekday strings. For example: "Sun", "Mon", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>shortWeekdays[0]</code> is ignored.
     * @serial
     */
    String shortWeekdays[] = null;

    /**
     * Narrow weekday strings. For example: "S", "M", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>narrowWeekdays[0]</code> is ignored.
     * @serial
     */
    String narrowWeekdays[] = null;

    /**
     * Standalone weekday strings. For example: "Sunday", "Monday", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>standaloneWeekdays[0]</code> is ignored.
     * @serial
     */
    String standaloneWeekdays[] = null;

    /**
     * Standalone short weekday strings. For example: "Sun", "Mon", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>standaloneShortWeekdays[0]</code> is ignored.
     * @serial
     */
    String standaloneShortWeekdays[] = null;

    /**
     * Standalone narrow weekday strings. For example: "S", "M", etc.  An array
     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * The element <code>standaloneNarrowWeekdays[0]</code> is ignored.
     * @serial
     */
    String standaloneNarrowWeekdays[] = null;

    /**
     * AM and PM strings. For example: "AM" and "PM".  An array of
     * 2 strings, indexed by <code>Calendar.AM</code> and
     * <code>Calendar.PM</code>.
     * @serial
     */
    String ampms[] = null;

    /**
     * Localized names of time zones in this locale.  This is a
     * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
     * where <em>m</em> is at least 5 and up to 8.  Each of the <em>n</em> rows is an
     * entry containing the localized names for a single <code>TimeZone</code>.
     * Each such row contains (with <code>i</code> ranging from
     * 0..<em>n</em>-1):
     * <ul>
     * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
     * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
     * time</li>
     * <li><code>zoneStrings[i][2]</code> - short name of zone in
     * standard time</li>
     * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
     * savings time</li>
     * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
     * savings time</li>
     * <li>The remainder varies depending on whether there is data 
     * on city name or generic time.  The city name, if available, comes
     * first.  The long and short generic times, if available, come next,
     * in that order. The length of the array (m) can be examined to 
     * determine which optional information is available.</li>
     * </ul>
     * The zone ID is <em>not</em> localized; it corresponds to the ID
     * value associated with a system time zone object.  All other entries
     * are localized names.  If a zone does not implement daylight savings
     * time, the daylight savings time names are ignored.
     * @see com.ibm.icu.util.TimeZone
     * @serial
     */
     private String zoneStrings[][] = null;

    /**
     * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
     * All locales use the same unlocalized pattern characters.
     */
    static final String  patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcL";

    /**
     * Localized date-time pattern characters. For example, a locale may
     * wish to use 'u' rather than 'y' to represent years in its date format
     * pattern strings.
     * This string must be exactly 18 characters long, with the index of
     * the characters described by <code>DateFormat.ERA_FIELD</code>,
     * <code>DateFormat.YEAR_FIELD</code>, etc.  Thus, if the string were
     * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
     * @serial
     */
    String  localPatternChars = null;

    /* use serialVersionUID from JDK 1.1.4 for interoperability */
    private static final long serialVersionUID = -5987973545549424702L;

    /**
     * Gets era strings. For example: "AD" and "BC".
     * @return the era strings.
     * @stable ICU 2.0
     */
    public String[] getEras() {
        return duplicate(eras);
    }

    /**
     * Sets era strings. For example: "AD" and "BC".
     * @param newEras the new era strings.
     * @stable ICU 2.0
     */
    public void setEras(String[] newEras) {
        eras = duplicate(newEras);
    }

    /**
     * Gets era name strings. For example: "Anno Domini" and "Before Christ".
     * @return the era strings.
     * @draft ICU 3.4
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public String[] getEraNames() {
        return duplicate(eraNames);
    }

    /**
     * Sets era name strings. For example: "Anno Domini" and "Before Christ".
     * @param newEras the new era strings.
     * @draft ICU 3.6
     */
    public void setEraNames(String[] newEraNames) {
        eraNames = duplicate(newEraNames);
    }
    /**
     * Gets month strings. For example: "January", "February", etc.
     * @return the month strings.
     * @stable ICU 2.0
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public String[] getMonths() {
        return duplicate(months);
    }

    /**
     * Gets month strings. For example: "January", "February", etc.
     * @param context    The month context, FORMAT or STANDALONE.
     * @param width      The width or the returned month string,
     *                   either WIDE, ABBREVIATED, or NARROW.
     * @return the month strings.
     * @draft ICU 3.4
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public String[] getMonths(int context, int width) {
        String [] returnValue = null;
        switch (context) {
           case FORMAT :
              switch(width) {
                 case WIDE :
                    returnValue = months;
                    break;
                 case ABBREVIATED :
                    returnValue = shortMonths;
                    break;
                 case NARROW :
                    returnValue = narrowMonths;
                    break;
              }
              break;
           case STANDALONE :
              switch(width) {
                 case WIDE :
                    returnValue = standaloneMonths;
                    break;
                 case ABBREVIATED :
                    returnValue = standaloneShortMonths;
                    break;
                 case NARROW :
                    returnValue = standaloneNarrowMonths;
                    break;
              }
              break;
        }
        return duplicate(returnValue);
    }

    /**
     * Sets month strings. For example: "January", "February", etc.
     * @param newMonths the new month strings.
     * @stable ICU 2.0
     */
    public void setMonths(String[] newMonths) {
        months = duplicate(newMonths);
    }

    /**
     * Sets month strings. For example: "January", "February", etc.
     * @param newMonths the new month strings.
     * @param context    The formatting context, FORMAT or STANDALONE.
     * @param width      The width of the month string,
     *                   either WIDE, ABBREVIATED, or NARROW.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */

    public void setMonths(String[] newMonths, int context, int width) {
        switch (context) {
           case FORMAT :
              switch(width) {
                 case WIDE :
                    months = duplicate(newMonths);
                    break;
                 case ABBREVIATED :
                    shortMonths = duplicate(newMonths);
                    break;
                 case NARROW :
                    narrowMonths = duplicate(newMonths);
                    break;
              }
              break;
           case STANDALONE :
              switch(width) {
                 case WIDE :
                    standaloneMonths = duplicate(newMonths);
                    break;
                 case ABBREVIATED :
                    standaloneShortMonths = duplicate(newMonths);
                    break;
                 case NARROW :
                    standaloneNarrowMonths = duplicate(newMonths);
                    break;
              }
              break;
        }
    }
    
    /**
     * Gets short month strings. For example: "Jan", "Feb", etc.
     * @return the short month strings.
     * @stable ICU 2.0
     */
    public String[] getShortMonths() {
        return duplicate(shortMonths);
    }

    /**
     * Sets short month strings. For example: "Jan", "Feb", etc.
     * @param newShortMonths the new short month strings.
     * @stable ICU 2.0
     */
    public void setShortMonths(String[] newShortMonths) {
        shortMonths = duplicate(newShortMonths);
    }

    /**
     * Gets weekday strings. For example: "Sunday", "Monday", etc.
     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc. to index the result array.
     * @stable ICU 2.0
     */
    public String[] getWeekdays() {
        return duplicate(weekdays);
    }

    /**
     * Gets weekday strings. For example: "Sunday", "Monday", etc.
     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc. to index the result array.
     * @param context    Formatting context, either FORMAT or STANDALONE.
     * @param width      Width of strings to be returned, either
     *                   WIDE, ABBREVIATED, or NARROW
     * @draft ICU 3.4
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public String[] getWeekdays(int context, int width) {
        String [] returnValue = null;
        switch (context) {
           case FORMAT :
              switch(width) {
                 case WIDE :
                    returnValue = weekdays;
                    break;
                 case ABBREVIATED :
                    returnValue = shortWeekdays;
                    break;
                 case NARROW :
                    returnValue = narrowWeekdays;
                    break;
              }
              break;
           case STANDALONE :
              switch(width) {
                 case WIDE :
                    returnValue = standaloneWeekdays;
                    break;
                 case ABBREVIATED :
                    returnValue = standaloneShortWeekdays;
                    break;
                 case NARROW :
                    returnValue = standaloneNarrowWeekdays;
                    break;
              }
              break;
        }
        return duplicate(returnValue);
    }

    /**
     * Sets weekday strings. For example: "Sunday", "Monday", etc.
     * @param newWeekdays The new weekday strings.
     * @param context     The formatting context, FORMAT or STANDALONE.
     * @param width       The width of the strings,
     *                    either WIDE, ABBREVIATED, or NARROW.
     * @draft ICU 3.6
     * @deprecated This is a draft API and might change in a future release of ICU.
     */

    public void setWeekdays(String[] newWeekdays, int context, int width) {
        switch (context) {
           case FORMAT :
              switch(width) {
                 case WIDE :
                    weekdays = duplicate(newWeekdays);
                    break;
                 case ABBREVIATED :
                    shortWeekdays = duplicate(newWeekdays);
                    break;
                 case NARROW :
                    narrowWeekdays = duplicate(newWeekdays);
                    break;
              }
              break;
           case STANDALONE :
              switch(width) {
                 case WIDE :
                    standaloneWeekdays = duplicate(newWeekdays);
                    break;
                 case ABBREVIATED :
                    standaloneShortWeekdays = duplicate(newWeekdays);
                    break;
                 case NARROW :
                    standaloneNarrowWeekdays = duplicate(newWeekdays);
                    break;
              }
              break;
        }
    }

    /**
     * Sets weekday strings. For example: "Sunday", "Monday", etc.
     * @param newWeekdays the new weekday strings. The array should
     * be indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * @stable ICU 2.0
     */
    public void setWeekdays(String[] newWeekdays) {
        weekdays = duplicate(newWeekdays);
    }

    /**
     * Gets short weekday strings. For example: "Sun", "Mon", etc.
     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc. to index the result array.
     * @stable ICU 2.0
     */
    public String[] getShortWeekdays() {
        return duplicate(shortWeekdays);
    }

    /**
     * Sets short weekday strings. For example: "Sun", "Mon", etc.
     * @param newShortWeekdays the new short weekday strings. The array should
     * be indexed by <code>Calendar.SUNDAY</code>,
     * <code>Calendar.MONDAY</code>, etc.
     * @stable ICU 2.0
     */
    public void setShortWeekdays(String[] newShortWeekdays) {
        shortWeekdays = duplicate(newShortWeekdays);
    }

    /**
     * Gets ampm strings. For example: "AM" and "PM".
     * @return the weekday strings.
     * @stable ICU 2.0
     */
    public String[] getAmPmStrings() {
        return duplicate(ampms);
    }

    /**
     * Sets ampm strings. For example: "AM" and "PM".
     * @param newAmpms the new ampm strings.
     * @stable ICU 2.0
     */
    public void setAmPmStrings(String[] newAmpms) {
        ampms = duplicate(newAmpms);
    }

    /**
     * Gets timezone strings.
     * @return the timezone strings.
     * @stable ICU 2.0
     */
    public String[][] getZoneStrings() {
        if(zoneStrings==null){ 
            initZoneStrings();
        }
        return duplicate(zoneStrings);
    }

    /**
     * Sets timezone strings.
     * @param newZoneStrings the new timezone strings.
     * @stable ICU 2.0
     */
    public void setZoneStrings(String[][] newZoneStrings) {
        zoneStrings = duplicate(newZoneStrings);
        if(zoneStringsHash==null){
            zoneStringsHash = new HashMap();
        }
        initZoneStrings(newZoneStrings);
        // reset the zone strings.
        zoneStrings=null;
    }

    /**
     * Gets localized date-time pattern characters. For example: 'u', 't', etc.
     * @return the localized date-time pattern characters.
     * @stable ICU 2.0
     */
    public String getLocalPatternChars() {
        return new String(localPatternChars);
    }

    /**
     * Sets localized date-time pattern characters. For example: 'u', 't', etc.
     * @param newLocalPatternChars the new localized date-time
     * pattern characters.
     * @stable ICU 2.0
     */
    public void setLocalPatternChars(String newLocalPatternChars) {
        localPatternChars = newLocalPatternChars;
    }

    /**
     * Overrides Cloneable
     * @stable ICU 2.0
     */
    public Object clone()
    {
        try {
            DateFormatSymbols other = (DateFormatSymbols)super.clone();
            copyMembers(this, other);
            return other;
        } catch (CloneNotSupportedException e) {
            ///CLOVER:OFF
            throw new InternalError();
            ///CLOVER:ON
        }
    }

    /**
     * Override hashCode.
     * Generates a hash code for the DateFormatSymbols object.
     * @stable ICU 2.0
     */
    public int hashCode() {
        int hashcode = 0;
        hashcode ^= requestedLocale.toString().hashCode();
        if(zoneStringsHash!=null){
            for(Iterator iter=zoneStringsHash.keySet().iterator(); iter.hasNext();){
                String key = (String)iter.next();
                String[] strings = (String[])zoneStringsHash.get(key); 
                hashcode ^= key.hashCode();
                for(int i=0; i< strings.length; i++){
                    if(strings[i]!=null){
                        hashcode ^= strings[i].hashCode();
                    }
                }
            }
        }
        return hashcode;
    }

    /**
     * Override equals
     * @stable ICU 2.0
     */
    public boolean equals(Object obj)
    {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        DateFormatSymbols that = (DateFormatSymbols) obj;
        return (Utility.arrayEquals(eras, that.eras)
                && Utility.arrayEquals(eraNames, that.eraNames)
                && Utility.arrayEquals(months, that.months)
                && Utility.arrayEquals(shortMonths, that.shortMonths)
                && Utility.arrayEquals(narrowMonths, that.narrowMonths)
                && Utility.arrayEquals(standaloneMonths, that.standaloneMonths)
                && Utility.arrayEquals(standaloneShortMonths, that.standaloneShortMonths)
                && Utility.arrayEquals(standaloneNarrowMonths, that.standaloneNarrowMonths)
                && Utility.arrayEquals(weekdays, that.weekdays)
                && Utility.arrayEquals(shortWeekdays, that.shortWeekdays)
                && Utility.arrayEquals(narrowWeekdays, that.narrowWeekdays)
                && Utility.arrayEquals(standaloneWeekdays, that.standaloneWeekdays)
                && Utility.arrayEquals(standaloneShortWeekdays, that.standaloneShortWeekdays)
                && Utility.arrayEquals(standaloneNarrowWeekdays, that.standaloneNarrowWeekdays)
                && Utility.arrayEquals(ampms, that.ampms)
                && hashEquals(zoneStringsHash, that.zoneStringsHash)
                // getDiplayName maps deprecated country and language codes to the current ones
                // too bad there is no way to get the current codes!
                // I thought canolicalize() would map the codes but .. alas! it doesn't.
                && requestedLocale.getDisplayName().equals(that.requestedLocale.getDisplayName())
                && Utility.arrayEquals(localPatternChars,
                                       that.localPatternChars));
    }

    // =======================privates===============================

    /**
     * Useful constant for defining timezone offsets.
     */
    static final int millisPerHour = 60*60*1000;
    /**
     * 
     * @param desiredLocale
     * @param type
     * @draft ICU 3.0
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    protected void initializeData(ULocale desiredLocale, String type)
    {
        CalendarData calData = new CalendarData(desiredLocale, type);
        initializeData(desiredLocale, calData);
    }

    /**
     * 
     * @param desiredLocale
     * @param calData
     * @draft ICU 3.0
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    protected void initializeData(ULocale desiredLocale, CalendarData calData)
    {

        // FIXME: cache only ResourceBundle. Hence every time, will do
        // getObject(). This won't be necessary if the Resource itself
        // is cached.
        eras = calData.getEras("abbreviated");

        try {
           eraNames = calData.getEras("wide");
        }
        catch (MissingResourceException e) {
           eraNames = calData.getEras("abbreviated");
        }

        months = calData.getStringArray("monthNames", "wide");
        shortMonths = calData.getStringArray("monthNames", "abbreviated");

        try {
           narrowMonths = calData.getStringArray("monthNames", "narrow");
        } 
        catch (MissingResourceException e) {
           narrowMonths = calData.getStringArray("monthNames", "abbreviated");
        }

        try {
           standaloneMonths = calData.getStringArray("monthNames", "stand-alone", "wide");
        } 
        catch (MissingResourceException e) {
           standaloneMonths = calData.getStringArray("monthNames", "format", "wide");
        }

        try {
           standaloneShortMonths = calData.getStringArray("monthNames", "stand-alone", "abbreviated");
        } 
        catch (MissingResourceException e) {
           standaloneShortMonths = calData.getStringArray("monthNames", "format", "abbreviated");
        }

        try {
           standaloneNarrowMonths = calData.getStringArray("monthNames", "stand-alone", "narrow");
        } 
        catch (MissingResourceException e) {
           try {
              standaloneNarrowMonths = calData.getStringArray("monthNames", "format", "narrow");
           }
           catch (MissingResourceException e1) {
              standaloneNarrowMonths = calData.getStringArray("monthNames", "format", "abbreviated");
           }
        }

        String[] lWeekdays = calData.getStringArray("dayNames", "wide");
        weekdays = new String[8];
        weekdays[0] = "";  // 1-based
        System.arraycopy(lWeekdays, 0, weekdays, 1, lWeekdays.length);

        String[] sWeekdays = calData.getStringArray("dayNames", "abbreviated");
        shortWeekdays = new String[8];
        shortWeekdays[0] = "";  // 1-based
        System.arraycopy(sWeekdays, 0, shortWeekdays, 1, sWeekdays.length);

        String [] nWeekdays = null;
        try {
           nWeekdays = calData.getStringArray("dayNames", "narrow");
        }
        catch (MissingResourceException e) {
           nWeekdays = calData.getStringArray("dayNames", "abbreviated");
        }
        narrowWeekdays = new String[8];
        narrowWeekdays[0] = "";  // 1-based
        System.arraycopy(nWeekdays, 0, narrowWeekdays, 1, nWeekdays.length);

        String [] saWeekdays = null;
        try {
           saWeekdays = calData.getStringArray("dayNames", "stand-alone", "wide");
        }
        catch (MissingResourceException e) {
           saWeekdays = calData.getStringArray("dayNames", "format", "wide");
        }
        standaloneWeekdays = new String[8];
        standaloneWeekdays[0] = "";  // 1-based
        System.arraycopy(saWeekdays, 0, standaloneWeekdays, 1, saWeekdays.length);

        String [] ssWeekdays = null;
        try {
           ssWeekdays = calData.getStringArray("dayNames", "stand-alone", "abbreviated");
        }
        catch (MissingResourceException e) {
           ssWeekdays = calData.getStringArray("dayNames", "format", "abbreviated");
        }
        standaloneShortWeekdays = new String[8];
        standaloneShortWeekdays[0] = "";  // 1-based
        System.arraycopy(ssWeekdays, 0, standaloneShortWeekdays, 1, ssWeekdays.length);

        String [] snWeekdays = null;
        try {
           snWeekdays = calData.getStringArray("dayNames", "stand-alone", "narrow");
        }
        catch (MissingResourceException e) {
           try {
              snWeekdays = calData.getStringArray("dayNames", "format", "narrow");
           }
           catch (MissingResourceException e1) {
              snWeekdays = calData.getStringArray("dayNames", "format", "abbreviated");
           }
        }
        standaloneNarrowWeekdays = new String[8];
        standaloneNarrowWeekdays[0] = "";  // 1-based
        System.arraycopy(snWeekdays, 0, standaloneNarrowWeekdays, 1, snWeekdays.length);

        ampms = calData.getStringArray("AmPmMarkers");

/*  THE FOLLOWING DOESN'T WORK; A COUNTRY LOCALE WITH ONE ZONE BLOCKS THE LANGUAGE LOCALE
        // These really do use rb and not calData
        ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, desiredLocale);
        // hack around class cast problem
        // zoneStrings = (String[][])rb.getObject("zoneStrings");
        ICUResourceBundle zoneObject = rb.get("zoneStrings");
        zoneStrings = new String[zoneObject.getSize()][];
        for(int i =0; i< zoneObject.getSize(); i++){
            ICUResourceBundle zoneArr = zoneObject.get(i);
            String[] strings = new String[zoneArr.getSize()];
            for(int j=0; j<zoneArr.getSize(); j++){
                strings[j]=zoneArr.get(j).getString();
            }
            zoneStrings[i] = strings;
        }
*/        
        requestedLocale = desiredLocale;
     
        ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, desiredLocale);
        localPatternChars = rb.getString("localPatternChars");

        // TODO: obtain correct actual/valid locale later
        ULocale uloc = rb.getULocale();
        setLocale(uloc, uloc);
    }
    private static final boolean hashEquals(HashMap h1, HashMap h2){
        if(h1==h2){ // both are null 
             return true;
        }
        if(h1==null || h2==null){ // one is null and the other is not
            return false;
        }
        if(h1.size() != h2.size()){
            return false;
        }
        Iterator i1 = h1.keySet().iterator();
        Iterator i2 = h2.keySet().iterator();

        while(i1.hasNext()){
            String key = (String) i1.next();
            String[] s1 = (String[])h1.get(key);
            String[] s2 = (String[])h2.get(key);
            if(Utility.arrayEquals(s1, s2)==false){
                return false;
            }
        }
        return true;
    }
    private void initZoneStrings(){
        if(zoneStringsHash==null){
            initZoneStringsHash();
        }
        zoneStrings = new String[zoneStringsHash.size()][8];
        int i = 0;
        for (Iterator it = zoneStringsKeyList.iterator(); it.hasNext();) {
            String key =  (String)it.next();
            String[] strings =  (String[])zoneStringsHash.get(key);
            zoneStrings[i][0] = key;
            zoneStrings[i][1] = strings[TIMEZONE_LONG_STANDARD];
            zoneStrings[i][2] = strings[TIMEZONE_SHORT_STANDARD];
            zoneStrings[i][3] = strings[TIMEZONE_LONG_DAYLIGHT];
            zoneStrings[i][4] = strings[TIMEZONE_SHORT_DAYLIGHT];
            zoneStrings[i][5] = strings[TIMEZONE_EXEMPLAR_CITY];
            if(zoneStrings[i][5]==null){
                zoneStrings[i][5] = strings[TIMEZONE_LONG_GENERIC];
            }else{
                zoneStrings[i][6] = strings[TIMEZONE_LONG_GENERIC];
            }
            if(zoneStrings[i][6]==null){
                zoneStrings[i][6] = strings[TIMEZONE_SHORT_GENERIC];
            }else{
                zoneStrings[i][7] = strings[TIMEZONE_SHORT_GENERIC];
            }
            i++;
        }
    }
    private void initZoneStringsHash(){
    
        zoneStringsHash = new HashMap();
        zoneStringsKeyList = new ArrayList();
        for (ULocale tempLocale = requestedLocale; tempLocale != null; tempLocale = tempLocale.getFallback()) {
            ICUResourceBundle bundle = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, tempLocale);
            ICUResourceBundle zoneStringsBundle = bundle.getWithFallback("zoneStrings");
            for(int i=0; i<zoneStringsBundle.getSize(); i++){
                ICUResourceBundle zoneTable = zoneStringsBundle.get(i);
                String key = Utility.replaceAll(zoneTable.getKey(),":","/");
                // hack for the root zone strings
                if(key.length()==0|| zoneTable.getType()!=ICUResourceBundle.TABLE){
                    continue;
                }
                String[] strings = new String[TIMEZONE_COUNT];
                try{
                    strings[TIMEZONE_SHORT_GENERIC] = zoneTable.getStringWithFallback(SHORT_GENERIC);
                }catch( MissingResourceException ex){
                    // throw away the exception   
                }
                try{
                    strings[TIMEZONE_SHORT_STANDARD] = zoneTable.getStringWithFallback(SHORT_STANDARD);
                }catch( MissingResourceException ex){
                    // throw away the exception   
                }
                try{
                    strings[TIMEZONE_SHORT_DAYLIGHT] = zoneTable.getStringWithFallback(SHORT_DAYLIGHT);
                }catch( MissingResourceException ex){
                    //  throw away the exception    
                }
                try{
                    strings[TIMEZONE_LONG_GENERIC] = zoneTable.getStringWithFallback(LONG_GENERIC);
                }catch( MissingResourceException ex){
                    // throw away the exception                 
                }
                try{
                    strings[TIMEZONE_LONG_STANDARD] = zoneTable.getStringWithFallback(LONG_STANDARD);
                }catch( MissingResourceException ex){
                    // throw away the exception   
                }
                try{
                    strings[TIMEZONE_LONG_DAYLIGHT] = zoneTable.getStringWithFallback(LONG_DAYLIGHT);
                }catch( MissingResourceException ex){
                    // throw away the exception   
                }
                try{
                    strings[TIMEZONE_EXEMPLAR_CITY] = zoneTable.getStringWithFallback(EXEMPLAR_CITY);
                }catch( MissingResourceException ex){
                    // throw away the exception   
                }
                if(!zoneStringsHash.containsKey(key)){
                    zoneStringsHash.put(key, strings); // only add if we don't have already
                    zoneStringsKeyList.add(key);
                }
            }
        }  
    }
    
    private ArrayList zoneStringsKeyList;
    private void initZoneStrings(String[][] newZoneStrings){
        if(newZoneStrings==null){
            return;
        }
        zoneStringsKeyList = new ArrayList();
        for(int row=0; row<newZoneStrings.length; row++){
            String key = newZoneStrings[row][0];
            String[] strings = (String[])zoneStringsHash.get(key);
            if(strings == null){
                strings = new String[TIMEZONE_COUNT];
            }
            int colCount = zoneStrings[row].length;
            for (int col=1; col<colCount; ++col) {
                // fastCopyFrom() - see assignArray comments
                switch (col){
                    case 1:
                        strings[TIMEZONE_LONG_STANDARD] = newZoneStrings[row][col];
                        break;
                    case 2:
                        strings[TIMEZONE_SHORT_STANDARD] = newZoneStrings[row][col];
                        break;
                    case 3:
                        strings[TIMEZONE_LONG_DAYLIGHT] = newZoneStrings[row][col];
                        break;
                    case 4:
                        strings[TIMEZONE_SHORT_DAYLIGHT] = newZoneStrings[row][col];
                         break;
                    case 5:
                        if(colCount==6 || colCount==8){
                            strings[TIMEZONE_EXEMPLAR_CITY] = newZoneStrings[row][col];
                        }else{
                            strings[TIMEZONE_LONG_GENERIC] = newZoneStrings[row][col];
                        }
                        break;
                    case 6:
                        if(colCount==8){
                            strings[TIMEZONE_LONG_GENERIC] = newZoneStrings[row][col];
                        }else{
                            strings[TIMEZONE_SHORT_GENERIC] = newZoneStrings[row][col];
                        }
                        break; 
                    case 7:
                        strings[TIMEZONE_SHORT_GENERIC] = newZoneStrings[row][col];
                        break;
                    default:
                        throw new IllegalArgumentException();
                }
            } 
            zoneStringsHash.put(key, strings);
            zoneStringsKeyList.add(key);
        }
    }
    Iterator getZoneStringIDs(){
        return zoneStringsHash.keySet().iterator();
    }
    
    String getZoneString(String zid, int type){

        if(zoneStringsHash == null){
            //lazy initialization
            initZoneStringsHash();
        }

        String[] stringsArray = (String[])zoneStringsHash.get(zid);
        if(stringsArray != null){
            return stringsArray[type];
        }

        return null;
    }
    String getZoneID(String zid){
        if(zoneStringsHash == null){
            initZoneStringsHash();
        }
        String[] strings = (String[])zoneStringsHash.get(zid);
        if (strings != null) {
            return zid;
        }
        try{
	        // Do a search through the equivalency group for the given ID
	        int n = TimeZone.countEquivalentIDs(zid);
	        if (n > 1) {
	            int i;
	            for (i=0; i<n; ++i) {
	                String equivID = TimeZone.getEquivalentID(zid, i);
	                if (equivID != zid) {
	                    strings = (String[])zoneStringsHash.get(equivID);
	                    if (strings != null) {
	                        return equivID;
	                    }
	                }
	            }
	        }
        }catch(MissingResourceException ex){
        	// throw away the exception
        }
        return null;
    }
    class ZoneItem{
        String value;
        int type;
        String zid;
    }
    ZoneItem getZoneItem(String zid, String text, int start){
        if(zoneStringsHash == null){
            initZoneStringsHash();
        }
        ZoneItem item = new ZoneItem();

        String[] strings = (String[])zoneStringsHash.get(zid);
        if(strings != null){
            for(int j=0; j<TIMEZONE_COUNT; j++){
                if(strings[j] != null && text.regionMatches(true, start, strings[j],0, strings[j].length())){
                    item.type = j;
                    item.value = strings[j];
                    item.zid = zid;
                    return item;
                }
            }
        }
        return null;
    }
    ZoneItem findZoneIDTypeValue(String text, int start){
        if(zoneStringsHash == null){
            initZoneStringsHash();
        }
        ZoneItem item = new ZoneItem();
        for (Iterator it = zoneStringsHash.keySet().iterator(); it.hasNext();) {
            String key = (String)it.next();
            String[] strings = (String[])zoneStringsHash.get(key);
            if(strings != null){
                for(int j=0; j<TIMEZONE_COUNT; j++){
                    if(strings[j]!=null && text.regionMatches(true, start, strings[j],0, strings[j].length())){
                        item.type = j;
                        item.value = strings[j];
                        item.zid = key;
                        return item;
                    }
                }
            }
        }
        return null;
    }

    private HashMap zoneStringsHash;
    /**
     * save the input locale
     */
    private ULocale requestedLocale; 
 
    /**
     * The translation type of the translated zone strings
     * @internal ICU 3.6
     */
     private static final String   SHORT_GENERIC  = "sg",
                                   SHORT_STANDARD = "ss",
                                   SHORT_DAYLIGHT = "sd",
                                   LONG_GENERIC   = "lg",
                                   LONG_STANDARD  = "ls",
                                   LONG_DAYLIGHT  = "ld",
                                   EXEMPLAR_CITY  = "ec";
    /**
     * The translation type of the translated zone strings
     * @internal ICU 3.6
     */
     static final int   TIMEZONE_SHORT_GENERIC  = 0,
                        TIMEZONE_SHORT_STANDARD = 1,
                        TIMEZONE_SHORT_DAYLIGHT = 2,
                        TIMEZONE_LONG_GENERIC   = 3,
                        TIMEZONE_LONG_STANDARD  = 4,
                        TIMEZONE_LONG_DAYLIGHT  = 5,
                        TIMEZONE_EXEMPLAR_CITY  = 6,
                        TIMEZONE_COUNT          = 7;
    
    /**
     * Package private: used by SimpleDateFormat
     * Gets the index for the given time zone ID to obtain the timezone
     * strings for formatting. The time zone ID is just for programmatic
     * lookup. NOT LOCALIZED!!!
     * @param ID the given time zone ID.
     * @return the index of the given time zone ID.  Returns -1 if
     * the given time zone ID can't be located in the DateFormatSymbols object.
     * @see com.ibm.icu.util.SimpleTimeZone
     */
    final int getZoneIndex(String ID) {
        int result = _getZoneIndex(ID);
        if (result >= 0) {
            return result;
        }
        // Do a search through the equivalency group for the given ID
        int n = ZoneMeta.countEquivalentIDs(ID);
        if (n > 1) {
            for (int i=0; i<n; ++i) {
                String equivID = ZoneMeta.getEquivalentID(ID, i);
                if (!equivID.equals(ID)) {
                    int equivResult = _getZoneIndex(equivID);
                    if (equivResult >= 0) {
                        return equivResult;
                    }
                }
            }
        }
        return -1;
    }
    
    /**
     * Lookup the given ID.  Do NOT do an equivalency search.
     */
    private int _getZoneIndex(String ID)
    {
        for (int index=0; index<zoneStrings.length; index++) {
            if (ID.equalsIgnoreCase(zoneStrings[index][0])) return index;
        }
        return -1;
    }

    /**
     * Clones an array of Strings.
     * @param srcArray the source array to be cloned.
     * @param count the number of elements in the given source array.
     * @return a cloned array.
     */
    private final String[] duplicate(String[] srcArray)
    {
        return (String[])srcArray.clone();
    }

    private final String[][] duplicate(String[][] srcArray)
    {
        String[][] aCopy = new String[srcArray.length][];
        for (int i = 0; i < srcArray.length; ++i)
            aCopy[i] = duplicate(srcArray[i]);
        return aCopy;
    }

    /**
     * Clones all the data members from the source DateFormatSymbols to
     * the target DateFormatSymbols. This is only for subclasses.
     * @param src the source DateFormatSymbols.
     * @param dst the target DateFormatSymbols.
     */
    private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
    {
        dst.eras = duplicate(src.eras);
        dst.eraNames = duplicate(src.eraNames);
        dst.months = duplicate(src.months);
        dst.shortMonths = duplicate(src.shortMonths);
        dst.narrowMonths = duplicate(src.narrowMonths);
        dst.standaloneMonths = duplicate(src.standaloneMonths);
        dst.standaloneShortMonths = duplicate(src.standaloneShortMonths);
        dst.standaloneNarrowMonths = duplicate(src.standaloneNarrowMonths);
        dst.weekdays = duplicate(src.weekdays);
        dst.shortWeekdays = duplicate(src.shortWeekdays);
        dst.narrowWeekdays = duplicate(src.narrowWeekdays);
        dst.standaloneWeekdays = duplicate(src.standaloneWeekdays);
        dst.standaloneShortWeekdays = duplicate(src.standaloneShortWeekdays);
        dst.standaloneNarrowWeekdays = duplicate(src.standaloneNarrowWeekdays);
        dst.ampms = duplicate(src.ampms);
        if(src.zoneStringsHash != null){
            dst.zoneStringsHash = (HashMap)src.zoneStringsHash.clone();
        }
        dst.requestedLocale = new ULocale(src.requestedLocale.toString());
        //dst.zoneStrings = duplicate(src.zoneStrings);
        dst.localPatternChars = new String (src.localPatternChars);
    }

    /**
     * Compares the equality of the two arrays of String.
     * @param current this String array.
     * @param other that String array.
    private final boolean equals(String[] current, String[] other)
    {
        int count = current.length;

        for (int i = 0; i < count; ++i)
            if (!current[i].equals(other[i]))
                return false;
        return true;
    }
     */

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Get the {@link DateFormatSymbols} object that should be used to format a
     * calendar system's dates in the given locale.
     * <p>
     * <b>Subclassing:</b><br>
     * When creating a new Calendar subclass, you must create the
     * {@link ResourceBundle ResourceBundle}
     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
     * The resource bundle name is based on the calendar's fully-specified
     * class name, with ".resources" inserted at the end of the package name
     * (just before the class name) and "Symbols" appended to the end.
     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
     * <p>
     * Within the ResourceBundle, this method searches for five keys:
     * <ul>
     * <li><b>DayNames</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
     *      This array is 0-based; the name for Sunday goes in the
     *      first position, at index 0.  If this key is not found
     *      in the bundle, the day names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     *
     * <li><b>DayAbbreviations</b> -
     *      An array of abbreviated day names corresponding
     *      to the values in the "DayNames" array.  If this key
     *      is not found in the resource bundle, the "DayNames"
     *      values are used instead.  If neither key is found,
     *      the day abbreviations are inherited from the default
     *      <code>DateFormatSymbols</code> for the locale.
     *
     * <li><b>MonthNames</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>MONTH</code> field.  If this key is not found
     *      in the bundle, the month names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     *
     * <li><b>MonthAbbreviations</b> -
     *      An array of abbreviated day names corresponding
     *      to the values in the "MonthNames" array.  If this key
     *      is not found in the resource bundle, the "MonthNames"
     *      values are used instead.  If neither key is found,
     *      the day abbreviations are inherited from the default
     *      <code>DateFormatSymbols</code> for the locale.
     *
     * <li><b>Eras</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>ERA</code> field.  If this key is not found
     *      in the bundle, the era names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     * </ul>
     * <p>
     * @param cal       The calendar system whose date format symbols are desired.
     * @param locale    The locale whose symbols are desired.
     *
     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
     * @stable ICU 2.0
     */
    public DateFormatSymbols(Calendar cal, Locale locale) {
        initializeData(ULocale.forLocale(locale), cal.getType());
    }

    /**
     * Get the {@link DateFormatSymbols} object that should be used to format a
     * calendar system's dates in the given locale.
     * <p>
     * <b>Subclassing:</b><br>
     * When creating a new Calendar subclass, you must create the
     * {@link ResourceBundle ResourceBundle}
     * containing its {@link DateFormatSymbols DateFormatSymbols} in a specific place.
     * The resource bundle name is based on the calendar's fully-specified
     * class name, with ".resources" inserted at the end of the package name
     * (just before the class name) and "Symbols" appended to the end.
     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
     * <p>
     * Within the ResourceBundle, this method searches for five keys:
     * <ul>
     * <li><b>DayNames</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>DAY_OF_WEEK</code> field.  Even though
     *      <code>DAY_OF_WEEK</code> starts with <code>SUNDAY</code> = 1,
     *      This array is 0-based; the name for Sunday goes in the
     *      first position, at index 0.  If this key is not found
     *      in the bundle, the day names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     *
     * <li><b>DayAbbreviations</b> -
     *      An array of abbreviated day names corresponding
     *      to the values in the "DayNames" array.  If this key
     *      is not found in the resource bundle, the "DayNames"
     *      values are used instead.  If neither key is found,
     *      the day abbreviations are inherited from the default
     *      <code>DateFormatSymbols</code> for the locale.
     *
     * <li><b>MonthNames</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>MONTH</code> field.  If this key is not found
     *      in the bundle, the month names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     *
     * <li><b>MonthAbbreviations</b> -
     *      An array of abbreviated day names corresponding
     *      to the values in the "MonthNames" array.  If this key
     *      is not found in the resource bundle, the "MonthNames"
     *      values are used instead.  If neither key is found,
     *      the day abbreviations are inherited from the default
     *      <code>DateFormatSymbols</code> for the locale.
     *
     * <li><b>Eras</b> -
     *      An array of strings corresponding to each possible
     *      value of the <code>ERA</code> field.  If this key is not found
     *      in the bundle, the era names are inherited from the
     *      default <code>DateFormatSymbols</code> for the requested locale.
     * </ul>
     * <p>
     * @param cal       The calendar system whose date format symbols are desired.
     * @param locale    The ulocale whose symbols are desired.
     *
     * @see DateFormatSymbols#DateFormatSymbols(java.util.Locale)
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public DateFormatSymbols(Calendar cal, ULocale locale) {
        initializeData(locale, cal.getType());
    }

    /**
     * Variant of DateFormatSymbols(Calendar, Locale) that takes the Calendar class
     * instead of a Calandar instance.
     * @see #DateFormatSymbols(Calendar, Locale)
     * @stable ICU 2.2
     */
    public DateFormatSymbols(Class calendarClass, Locale locale) {
        this(calendarClass, ULocale.forLocale(locale));
    }

    /**
     * Variant of DateFormatSymbols(Calendar, ULocale) that takes the Calendar class
     * instead of a Calandar instance.
     * @see #DateFormatSymbols(Calendar, Locale)
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public DateFormatSymbols(Class calendarClass, ULocale locale) {
        String fullName = calendarClass.getName();
        int lastDot = fullName.lastIndexOf('.');
        String className = fullName.substring(lastDot+1);
        String calType = Utility.replaceAll(className, "Calendar", "").toLowerCase();
        
        initializeData(locale, calType);
    }

    /**
     * Fetch a custom calendar's DateFormatSymbols out of the given resource
     * bundle.  Symbols that are not overridden are inherited from the
     * default DateFormatSymbols for the locale.
     * @see DateFormatSymbols#DateFormatSymbols
     * @stable ICU 2.0
     */
    public DateFormatSymbols(ResourceBundle bundle, Locale locale) {
        this(bundle, ULocale.forLocale(locale));
    }

    /**
     * Fetch a custom calendar's DateFormatSymbols out of the given resource
     * bundle.  Symbols that are not overridden are inherited from the
     * default DateFormatSymbols for the locale.
     * @see DateFormatSymbols#DateFormatSymbols
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public DateFormatSymbols(ResourceBundle bundle, ULocale locale) {
        initializeData(locale, 
            new CalendarData((ICUResourceBundle)bundle, null));
    }

    /**
     * Find the ResourceBundle containing the date format information for
     * a specified calendar subclass in a given locale.
     * <p>
     * The resource bundle name is based on the calendar's fully-specified
     * class name, with ".resources" inserted at the end of the package name
     * (just before the class name) and "Symbols" appended to the end.
     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
     * @stable ICU 2.0
     */
    static public ResourceBundle getDateFormatBundle(Class calendarClass, Locale locale)
        throws MissingResourceException {
        return getDateFormatBundle(calendarClass, ULocale.forLocale(locale));
    }
        
    /**
     * Find the ResourceBundle containing the date format information for
     * a specified calendar subclass in a given locale.
     * <p>
     * The resource bundle name is based on the calendar's fully-specified
     * class name, with ".resources" inserted at the end of the package name
     * (just before the class name) and "Symbols" appended to the end.
     * For example, the bundle corresponding to "com.ibm.icu.util.HebrewCalendar"
     * is "com.ibm.icu.impl.data.HebrewCalendarSymbols".
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    static public ResourceBundle getDateFormatBundle(Class calendarClass, ULocale locale)
        throws MissingResourceException {
        
        // Find the calendar's class name, which we're going to use to construct the
        // resource bundle name.
        String fullName = calendarClass.getName();
        int lastDot = fullName.lastIndexOf('.');
        String className = fullName.substring(lastDot+1);

        String bundleName = className + "Symbols";

        ResourceBundle result = null;
        try {
            result = ICULocaleData.getResourceBundle(bundleName, locale);
        }
        catch (MissingResourceException e) {
            ///CLOVER:OFF
            // coverage requires test without data, so skip
            //if (!(cal instanceof GregorianCalendar)) {
            if (!(GregorianCalendar.class.isAssignableFrom(calendarClass))) {
                // Ok for symbols to be missing for a Gregorian calendar, but
                // not for any other type.
                throw e;
            }
            ///CLOVER:ON
        }
        return result;
    }

    /**
     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
     * a Calendar instance instead of a Calendar class.
     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
     * @stable ICU 2.2
     */
    public static ResourceBundle getDateFormatBundle(Calendar cal, Locale locale)
        throws MissingResourceException {
        return getDateFormatBundle(cal.getClass(), ULocale.forLocale(locale));
    }
    
    /**
     * Variant of getDateFormatBundle(java.lang.Class, java.util.Locale) that takes
     * a Calendar instance instead of a Calendar class.
     * @see #getDateFormatBundle(java.lang.Class, java.util.Locale)
     * @draft ICU 3.2
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public static ResourceBundle getDateFormatBundle(Calendar cal, ULocale locale)
        throws MissingResourceException {
        return getDateFormatBundle(cal.getClass(), locale);
    }
    
    // -------- BEGIN ULocale boilerplate --------

    /**
     * Return the locale that was used to create this object, or null.
     * This may may differ from the locale requested at the time of
     * this object's creation.  For example, if an object is created
     * for locale <tt>en_US_CALIFORNIA</tt>, the actual data may be
     * drawn from <tt>en</tt> (the <i>actual</i> locale), and
     * <tt>en_US</tt> may be the most specific locale that exists (the
     * <i>valid</i> locale).
     *
     * <p>Note: This method will be implemented in ICU 3.0; ICU 2.8
     * contains a partial preview implementation.  The * <i>actual</i>
     * locale is returned correctly, but the <i>valid</i> locale is
     * not, in most cases.
     * @param type type of information requested, either {@link
     * com.ibm.icu.util.ULocale#VALID_LOCALE} or {@link
     * com.ibm.icu.util.ULocale#ACTUAL_LOCALE}.
     * @return the information specified by <i>type</i>, or null if
     * this object was not constructed from locale data.
     * @see com.ibm.icu.util.ULocale
     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
     * @draft ICU 2.8 (retain)
     * @deprecated This is a draft API and might change in a future release of ICU.
     */
    public final ULocale getLocale(ULocale.Type type) {
        return type == ULocale.ACTUAL_LOCALE ?
            this.actualLocale : this.validLocale;
    }

    /**
     * Set information about the locales that were used to create this
     * object.  If the object was not constructed from locale data,
     * both arguments should be set to null.  Otherwise, neither
     * should be null.  The actual locale must be at the same level or
     * less specific than the valid locale.  This method is intended
     * for use by factories or other entities that create objects of
     * this class.
     * @param valid the most specific locale containing any resource
     * data, or null
     * @param actual the locale containing data used to construct this
     * object, or null
     * @see com.ibm.icu.util.ULocale
     * @see com.ibm.icu.util.ULocale#VALID_LOCALE
     * @see com.ibm.icu.util.ULocale#ACTUAL_LOCALE
     * @internal
     */
    final void setLocale(ULocale valid, ULocale actual) {
        // Change the following to an assertion later
        if ((valid == null) != (actual == null)) {
            ///CLOVER:OFF
            throw new IllegalArgumentException();
            ///CLOVER:ON
        }
        // Another check we could do is that the actual locale is at
        // the same level or less specific than the valid locale.
        this.validLocale = valid;
        this.actualLocale = actual;
    }

    /**
     * The most specific locale containing any resource data, or null.
     * @see com.ibm.icu.util.ULocale
     * @internal
     */
    private ULocale validLocale;

    /**
     * The locale containing data used to construct this object, or
     * null.
     * @see com.ibm.icu.util.ULocale
     * @internal
     */
    private ULocale actualLocale;

    // -------- END ULocale boilerplate --------
}
