12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2008, International Business Machines Corporation and         *
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.impl.jdkadapter;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashMap;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.TimeZone;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.icuadapter.TimeZoneJDK;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DateFormatSymbols;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Calendar;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * CalendarICU is an adapter class which wraps ICU4J Calendar and
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * implements java.util.Calendar APIs.
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class CalendarICU extends java.util.Calendar {
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final long serialVersionUID = -8641226371713600671L;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Calendar fIcuCal;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private CalendarICU(Calendar icuCal) {
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal = icuCal;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        init();
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static java.util.Calendar wrap(Calendar icuCal) {
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return new CalendarICU(icuCal);
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Calendar unwrap() {
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal;
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void add(int field, int amount) {
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.add(field, amount);
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    We do not need to override followings.  These methods
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          call int compareTo(Calendar anotherCalendar) and we
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          override the method.
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public boolean after(Object when)
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public boolean before(Object when)
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    Jeez!  These methods are final and we cannot override them.
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          We do not want to rewrite ICU Calendar implementation classes
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          as subclasses of java.util.Calendar.  This adapter class
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          wraps an ICU Calendar instance and the calendar calculation
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          is actually done independently from java.util.Calendar
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          implementation.  Thus, we need to monitor the status of
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          superclass fields in some methods and call ICU Calendar's
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          clear if superclass clear update the status of superclass's
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          calendar fields.  See private void sync().
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void clear()
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void clear(int field)
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Object clone() {
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CalendarICU other = (CalendarICU)super.clone();
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        other.fIcuCal = (Calendar)fIcuCal.clone();
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return other;
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int compareTo(Calendar anotherCalendar)  {
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        long thisMillis = getTimeInMillis();
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        long otherMillis = anotherCalendar.getTimeInMillis();
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return thisMillis > otherMillis ? 1 : (thisMillis == otherMillis ? 0 : -1);
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    These methods are supposed to be implemented by java.util.Calendar
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          subclasses.  But we actually use a instance of ICU Calendar
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          for all calendar calculation, we do nothing here.
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void complete() {}
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void computeFields() {}
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected void computeTime() {}
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean equals(Object obj) {
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (obj instanceof CalendarICU) {
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sync();
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return ((CalendarICU)obj).fIcuCal.equals(fIcuCal);
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return false;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int get(int field) {
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.get(field);
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getActualMaximum(int field) {
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getActualMaximum(field);
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getActualMinimum(int field) {
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getActualMinimum(field);
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getDisplayName(int field, int style, Locale locale) {
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) {
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Bad field or style.");
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] array = getFieldStrings(field, style, dfs);
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (array != null) {
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int fieldVal = get(field);
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldVal < array.length) {
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return array[fieldVal];
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return null;
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Map<String,Integer> getDisplayNames(int field, int style, Locale locale) {
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) {
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Bad field or style.");
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style != ALL_STYLES) {
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getFieldStringsMap(field, style, dfs);
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map<String,Integer> result = getFieldStringsMap(field, SHORT, dfs);
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result == null) {
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (field == MONTH || field == DAY_OF_WEEK) {
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Map<String,Integer> longMap = getFieldStringsMap(field, LONG, dfs);
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (longMap != null) {
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.putAll(longMap);
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getGreatestMinimum(int field) {
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getGreatestMinimum(field);
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getLeastMaximum(int field) {
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getLeastMaximum(field);
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMaximum(int field) {
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getMaximum(field);
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMinimalDaysInFirstWeek() {
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getMinimalDaysInFirstWeek();
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMinimum(int field) {
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getMinimum(field);
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    getTime() calls getTimeInMillis()
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public Date getTime()
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public long getTimeInMillis() {
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.getTimeInMillis();
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public TimeZone getTimeZone() {
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return TimeZoneICU.wrap(fIcuCal.getTimeZone());
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int hashCode() {
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.hashCode();
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //protected int internalGet(int field)
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isLenient() {
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return fIcuCal.isLenient();
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public boolean isSet(int field)
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void roll(int field, boolean up) {
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.roll(field, up);
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void roll(int field, int amount) {
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.roll(field, amount);
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void set(int field, int value) {
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.set(field, value);
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    These set methods call set(int field, int value) for each field.
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          These are final, so we cannot override them, but we override
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          set(int field, int value), so the superclass implementations
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          still work as we want.
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void set(int year, int month, int date)
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void set(int year, int month, int date, int hourOfDay, int minute)
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void set(int year, int month, int date, int hourOfDay, int minute, int second)
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setFirstDayOfWeek(int value) {
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.setFirstDayOfWeek(value);
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setLenient(boolean lenient) {
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.setLenient(lenient);
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMinimalDaysInFirstWeek(int value) {
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.setMinimalDaysInFirstWeek(value);
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note:    This method calls setTimeInMillis(long millis).
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          This method is final, so we cannot override it, but we
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          override setTimeInMillis(long millis), so the superclass
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //          implementation still works as we want.
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //public void setTime(Date date)
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setTimeInMillis(long millis) {
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.setTimeInMillis(millis);
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setTimeZone(TimeZone value) {
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fIcuCal.setTimeZone(TimeZoneJDK.wrap(value));
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String toString() {
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        sync();
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return "CalendarICU: " + fIcuCal.toString();
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void sync() {
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Check if clear is called for each JDK Calendar field.
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If it was, then call clear for the field in the wrapped
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ICU Calendar.
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < isSet.length; i++) {
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!isSet[i]) {
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                isSet[i] = true;
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                try {
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fIcuCal.clear(i);
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } catch (ArrayIndexOutOfBoundsException e) {
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // More fields in JDK calendar, which is unlikely
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void init() {
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Mark "set" for all fields, so we can detect the invocation of
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // clear() later.
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < isSet.length; i++) {
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            isSet[i] = true;
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static String[] getFieldStrings(int field, int style, DateFormatSymbols dfs) {
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] result = null;
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch (field) {
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case AM_PM:
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result = dfs.getAmPmStrings();
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case DAY_OF_WEEK:
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result = (style == LONG) ? dfs.getWeekdays() : dfs.getShortWeekdays();
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ERA:
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //result = (style == LONG) ? dfs.getEraNames() : dfs.getEras();
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result = dfs.getEras();
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case MONTH:
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result = (style == LONG) ? dfs.getMonths() : dfs.getShortMonths();
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static Map<String,Integer> getFieldStringsMap(int field, int style, DateFormatSymbols dfs) {
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String[] strings = getFieldStrings(field, style, dfs);
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (strings == null) {
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Map<String,Integer> res = new HashMap<String,Integer>();
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < strings.length; i++) {
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (strings[i].length() != 0) {
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                res.put(strings[i], Integer.valueOf(i));
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return res;
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
332