| /* |
| ******************************************************************************* |
| * Copyright (C) 2008, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.impl.jdkadapter; |
| |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.TimeZone; |
| |
| import com.ibm.icu.impl.icuadapter.TimeZoneJDK; |
| import com.ibm.icu.text.DateFormatSymbols; |
| import com.ibm.icu.util.Calendar; |
| |
| /** |
| * CalendarICU is an adapter class which wraps ICU4J Calendar and |
| * implements java.util.Calendar APIs. |
| */ |
| public class CalendarICU extends java.util.Calendar { |
| |
| private static final long serialVersionUID = -8641226371713600671L; |
| |
| private Calendar fIcuCal; |
| |
| private CalendarICU(Calendar icuCal) { |
| fIcuCal = icuCal; |
| init(); |
| } |
| |
| public static java.util.Calendar wrap(Calendar icuCal) { |
| return new CalendarICU(icuCal); |
| } |
| |
| public Calendar unwrap() { |
| sync(); |
| return fIcuCal; |
| } |
| |
| @Override |
| public void add(int field, int amount) { |
| sync(); |
| fIcuCal.add(field, amount); |
| } |
| |
| // Note: We do not need to override followings. These methods |
| // call int compareTo(Calendar anotherCalendar) and we |
| // override the method. |
| //public boolean after(Object when) |
| //public boolean before(Object when) |
| |
| // Note: Jeez! These methods are final and we cannot override them. |
| // We do not want to rewrite ICU Calendar implementation classes |
| // as subclasses of java.util.Calendar. This adapter class |
| // wraps an ICU Calendar instance and the calendar calculation |
| // is actually done independently from java.util.Calendar |
| // implementation. Thus, we need to monitor the status of |
| // superclass fields in some methods and call ICU Calendar's |
| // clear if superclass clear update the status of superclass's |
| // calendar fields. See private void sync(). |
| //public void clear() |
| //public void clear(int field) |
| |
| @Override |
| public Object clone() { |
| sync(); |
| CalendarICU other = (CalendarICU)super.clone(); |
| other.fIcuCal = (Calendar)fIcuCal.clone(); |
| return other; |
| } |
| |
| public int compareTo(Calendar anotherCalendar) { |
| sync(); |
| long thisMillis = getTimeInMillis(); |
| long otherMillis = anotherCalendar.getTimeInMillis(); |
| return thisMillis > otherMillis ? 1 : (thisMillis == otherMillis ? 0 : -1); |
| } |
| |
| // Note: These methods are supposed to be implemented by java.util.Calendar |
| // subclasses. But we actually use a instance of ICU Calendar |
| // for all calendar calculation, we do nothing here. |
| @Override |
| protected void complete() {} |
| @Override |
| protected void computeFields() {} |
| @Override |
| protected void computeTime() {} |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof CalendarICU) { |
| sync(); |
| return ((CalendarICU)obj).fIcuCal.equals(fIcuCal); |
| } |
| return false; |
| } |
| |
| @Override |
| public int get(int field) { |
| sync(); |
| return fIcuCal.get(field); |
| } |
| |
| @Override |
| public int getActualMaximum(int field) { |
| return fIcuCal.getActualMaximum(field); |
| } |
| |
| @Override |
| public int getActualMinimum(int field) { |
| return fIcuCal.getActualMinimum(field); |
| } |
| |
| @Override |
| public String getDisplayName(int field, int style, Locale locale) { |
| if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) { |
| throw new IllegalArgumentException("Bad field or style."); |
| } |
| DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale); |
| String[] array = getFieldStrings(field, style, dfs); |
| if (array != null) { |
| int fieldVal = get(field); |
| if (fieldVal < array.length) { |
| return array[fieldVal]; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public Map<String,Integer> getDisplayNames(int field, int style, Locale locale) { |
| if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) { |
| throw new IllegalArgumentException("Bad field or style."); |
| } |
| DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale); |
| if (style != ALL_STYLES) { |
| return getFieldStringsMap(field, style, dfs); |
| } |
| |
| Map<String,Integer> result = getFieldStringsMap(field, SHORT, dfs); |
| if (result == null) { |
| return null; |
| } |
| if (field == MONTH || field == DAY_OF_WEEK) { |
| Map<String,Integer> longMap = getFieldStringsMap(field, LONG, dfs); |
| if (longMap != null) { |
| result.putAll(longMap); |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public int getGreatestMinimum(int field) { |
| return fIcuCal.getGreatestMinimum(field); |
| } |
| |
| @Override |
| public int getLeastMaximum(int field) { |
| return fIcuCal.getLeastMaximum(field); |
| } |
| |
| @Override |
| public int getMaximum(int field) { |
| return fIcuCal.getMaximum(field); |
| } |
| |
| @Override |
| public int getMinimalDaysInFirstWeek() { |
| return fIcuCal.getMinimalDaysInFirstWeek(); |
| } |
| |
| @Override |
| public int getMinimum(int field) { |
| return fIcuCal.getMinimum(field); |
| } |
| |
| // Note: getTime() calls getTimeInMillis() |
| //public Date getTime() |
| |
| @Override |
| public long getTimeInMillis() { |
| sync(); |
| return fIcuCal.getTimeInMillis(); |
| } |
| |
| @Override |
| public TimeZone getTimeZone() { |
| return TimeZoneICU.wrap(fIcuCal.getTimeZone()); |
| } |
| |
| @Override |
| public int hashCode() { |
| sync(); |
| return fIcuCal.hashCode(); |
| } |
| |
| //protected int internalGet(int field) |
| |
| @Override |
| public boolean isLenient() { |
| return fIcuCal.isLenient(); |
| } |
| |
| //public boolean isSet(int field) |
| |
| @Override |
| public void roll(int field, boolean up) { |
| sync(); |
| fIcuCal.roll(field, up); |
| } |
| |
| @Override |
| public void roll(int field, int amount) { |
| sync(); |
| fIcuCal.roll(field, amount); |
| } |
| |
| @Override |
| public void set(int field, int value) { |
| sync(); |
| fIcuCal.set(field, value); |
| } |
| |
| // Note: These set methods call set(int field, int value) for each field. |
| // These are final, so we cannot override them, but we override |
| // set(int field, int value), so the superclass implementations |
| // still work as we want. |
| //public void set(int year, int month, int date) |
| //public void set(int year, int month, int date, int hourOfDay, int minute) |
| //public void set(int year, int month, int date, int hourOfDay, int minute, int second) |
| |
| @Override |
| public void setFirstDayOfWeek(int value) { |
| fIcuCal.setFirstDayOfWeek(value); |
| } |
| |
| @Override |
| public void setLenient(boolean lenient) { |
| fIcuCal.setLenient(lenient); |
| } |
| |
| @Override |
| public void setMinimalDaysInFirstWeek(int value) { |
| fIcuCal.setMinimalDaysInFirstWeek(value); |
| } |
| |
| // Note: This method calls setTimeInMillis(long millis). |
| // This method is final, so we cannot override it, but we |
| // override setTimeInMillis(long millis), so the superclass |
| // implementation still works as we want. |
| //public void setTime(Date date) |
| |
| @Override |
| public void setTimeInMillis(long millis) { |
| fIcuCal.setTimeInMillis(millis); |
| } |
| |
| @Override |
| public void setTimeZone(TimeZone value) { |
| fIcuCal.setTimeZone(TimeZoneJDK.wrap(value)); |
| } |
| |
| @Override |
| public String toString() { |
| sync(); |
| return "CalendarICU: " + fIcuCal.toString(); |
| } |
| |
| private void sync() { |
| // Check if clear is called for each JDK Calendar field. |
| // If it was, then call clear for the field in the wrapped |
| // ICU Calendar. |
| for (int i = 0; i < isSet.length; i++) { |
| if (!isSet[i]) { |
| isSet[i] = true; |
| try { |
| fIcuCal.clear(i); |
| } catch (ArrayIndexOutOfBoundsException e) { |
| // More fields in JDK calendar, which is unlikely |
| } |
| } |
| } |
| } |
| |
| private void init() { |
| // Mark "set" for all fields, so we can detect the invocation of |
| // clear() later. |
| for (int i = 0; i < isSet.length; i++) { |
| isSet[i] = true; |
| } |
| } |
| |
| private static String[] getFieldStrings(int field, int style, DateFormatSymbols dfs) { |
| String[] result = null; |
| switch (field) { |
| case AM_PM: |
| result = dfs.getAmPmStrings(); |
| break; |
| case DAY_OF_WEEK: |
| result = (style == LONG) ? dfs.getWeekdays() : dfs.getShortWeekdays(); |
| break; |
| case ERA: |
| //result = (style == LONG) ? dfs.getEraNames() : dfs.getEras(); |
| result = dfs.getEras(); |
| break; |
| case MONTH: |
| result = (style == LONG) ? dfs.getMonths() : dfs.getShortMonths(); |
| break; |
| } |
| return result; |
| } |
| |
| private static Map<String,Integer> getFieldStringsMap(int field, int style, DateFormatSymbols dfs) { |
| String[] strings = getFieldStrings(field, style, dfs); |
| if (strings == null) { |
| return null; |
| } |
| Map<String,Integer> res = new HashMap<String,Integer>(); |
| for (int i = 0; i < strings.length; i++) { |
| if (strings[i].length() != 0) { |
| res.put(strings[i], Integer.valueOf(i)); |
| } |
| } |
| return res; |
| } |
| } |