1 /*
   2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 import java.util.Calendar;
  26 import sun.util.calendar.CalendarUtils;
  27 
  28 public class CalendarAdapter extends Calendar {
  29     public static enum Type {
  30         GREGORIAN, BUDDHIST, JAPANESE;
  31     }
  32 
  33     static final String[] FIELD_NAMES = {
  34         "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
  35         "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
  36         "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
  37         "DST_OFFSET"
  38     };
  39 
  40     Calendar cal;
  41     GregorianAdapter gcal;
  42     private Type type;
  43 
  44     public CalendarAdapter(Calendar cal) {
  45         if (cal == null)
  46             throw new NullPointerException();
  47 
  48         this.cal = cal;
  49         if (cal instanceof sun.util.BuddhistCalendar) {
  50             type = Type.BUDDHIST;
  51         } else if (cal instanceof GregorianAdapter) {
  52             type = Type.GREGORIAN;
  53             gcal = (GregorianAdapter) cal;
  54         } else {
  55             type = Type.JAPANESE;
  56         }
  57     }
  58 
  59     public void setFirstDayOfWeek(int w) {
  60         cal.setFirstDayOfWeek(w);
  61     }
  62 
  63     public int getFirstDayOfWeek() {
  64         return cal.getFirstDayOfWeek();
  65     }
  66 
  67     public void setMinimalDaysInFirstWeek(int value) {
  68         cal.setMinimalDaysInFirstWeek(value);
  69     }
  70 
  71     public int getMinimalDaysInFirstWeek() {
  72         return getMinimalDaysInFirstWeek();
  73     }
  74 
  75     public long getTimeInMillis() {
  76         return cal.getTimeInMillis();
  77     }
  78 
  79     public void setTimeInMillis(long millis) {
  80         cal.setTimeInMillis(millis);
  81     }
  82 
  83     public int get(int field) {
  84         return cal.get(field);
  85     }
  86 
  87     public void set(int field, int value) {
  88         cal.set(field, value);
  89     }
  90 
  91     public void add(int field, int amount) {
  92         cal.add(field, amount);
  93     }
  94 
  95     public void roll(int field, boolean dir) {
  96         cal.roll(field, dir);
  97     }
  98 
  99     public void roll(int field, int amount) {
 100         cal.roll(field, amount);
 101     }
 102 
 103     public void setDate(int year, int month, int date)
 104     {
 105         cal.set(year, month, date);
 106     }
 107 
 108     public void setDate(int era, int year, int month, int date) {
 109         cal.set(ERA, era);
 110         cal.set(year, month, date);
 111     }
 112 
 113     public void setDateTime(int year, int month, int date, int hourOfDay, int minute, int second)
 114     {
 115         cal.set(year, month, date, hourOfDay, minute, second);
 116     }
 117 
 118     public void clearAll() {
 119         cal.clear();
 120     }
 121 
 122     public void clearField(int field)
 123     {
 124         cal.clear(field);
 125     }
 126 
 127     public boolean isSetField(int field)
 128     {
 129         return cal.isSet(field);
 130     }
 131 
 132     public int getMaximum(int field) {
 133         return cal.getMaximum(field);
 134     }
 135 
 136     public int getLeastMaximum(int field) {
 137         return cal.getLeastMaximum(field);
 138     }
 139 
 140     public int getActualMaximum(int field) {
 141         return cal.getActualMaximum(field);
 142     }
 143 
 144     public int getMinimum(int field) {
 145         return cal.getMinimum(field);
 146     }
 147 
 148     public int getGreatestMinimum(int field) {
 149         return cal.getGreatestMinimum(field);
 150     }
 151 
 152     public int getActualMinimum(int field) {
 153         return cal.getActualMinimum(field);
 154     }
 155 
 156     public void setLenient(boolean lenient) {
 157         cal.setLenient(lenient);
 158     }
 159 
 160     public String toString() {
 161         return cal.toString();
 162     }
 163 
 164     protected void computeFields() {
 165     }
 166 
 167     protected void computeTime() {
 168     }
 169 
 170     void setTimeOfDay(int hourOfDay, int minute, int second, int ms) {
 171         cal.set(HOUR_OF_DAY, hourOfDay);
 172         cal.set(MINUTE, minute);
 173         cal.set(SECOND, second);
 174         cal.set(MILLISECOND, ms);
 175     }
 176 
 177     // GregorianAdapter specific methods
 178 
 179     // When gcal is null, the methods throw a NPE.
 180 
 181     int getSetStateFields() {
 182         return gcal.getSetStateFields();
 183     }
 184 
 185     int[] getFields() {
 186         return gcal.getFields();
 187     }
 188 
 189     boolean checkInternalDate(int year, int month, int dayOfMonth) {
 190         return gcal.checkInternalDate(year, month, dayOfMonth);
 191     }
 192 
 193     boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) {
 194         return gcal.checkInternalDate(year, month, dayOfMonth, dayOfWeek);
 195     }
 196 
 197     boolean checkInternalField(int field, int expectedValue) {
 198         return checkInternalField(field, expectedValue);
 199     }
 200 
 201     // check methods
 202 
 203     boolean checkAllSet() {
 204         initTest();
 205         for (int i = 0; i < FIELD_COUNT; i++) {
 206             checkFieldState(i, true);
 207         }
 208         return getStatus();
 209     }
 210 
 211     boolean checkMaximum(int field, int expectedValue) {
 212         int val;
 213         if ((val = getMaximum(field)) != expectedValue) {
 214             appendMessage("getMaximum("+FIELD_NAMES[field]+"): got " + val
 215                           + " expected " + expectedValue);
 216         }
 217         return getStatus();
 218     }
 219 
 220     boolean checkActualMaximum(int field, int expectedValue) {
 221         int val;
 222         if ((val = getActualMaximum(field)) != expectedValue) {
 223             appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val
 224                           + " expected " + expectedValue);
 225         }
 226         return getStatus();
 227     }
 228 
 229     boolean checkLeastMaximum(int field, int expectedValue) {
 230         int val;
 231         if ((val = getLeastMaximum(field)) != expectedValue) {
 232             appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val
 233                           + " expected " + expectedValue);
 234         }
 235         return getStatus();
 236     }
 237 
 238     boolean checkMinimum(int field, int expectedValue) {
 239         int val;
 240         if ((val = getMinimum(field)) != expectedValue) {
 241             appendMessage("getMinimum("+FIELD_NAMES[field]+"): got " + val
 242                           + " expected " + expectedValue);
 243         }
 244         return getStatus();
 245     }
 246 
 247     boolean checkActualMinimum(int field, int expectedValue) {
 248         int val;
 249         if ((val = getActualMinimum(field)) != expectedValue) {
 250             appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val
 251                           + " expected " + expectedValue);
 252         }
 253         return getStatus();
 254     }
 255 
 256     boolean checkGreatestMinimum(int field, int expectedValue) {
 257         int val;
 258         if ((val = getGreatestMinimum(field)) != expectedValue) {
 259             appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val
 260                           + " expected " + expectedValue);
 261         }
 262         return getStatus();
 263     }
 264 
 265     boolean checkDate(int year, int month, int dayOfMonth) {
 266         initTest();
 267         checkField(YEAR, year);
 268         checkField(MONTH, month);
 269         checkField(DAY_OF_MONTH, dayOfMonth);
 270         return getStatus();
 271     }
 272 
 273     boolean checkDate(int era, int year, int month, int dayOfMonth) {
 274         initTest();
 275         checkField(ERA, era);
 276         checkField(YEAR, year);
 277         checkField(MONTH, month);
 278         checkField(DAY_OF_MONTH, dayOfMonth);
 279         return getStatus();
 280     }
 281 
 282     boolean checkDateTime(int year, int month, int dayOfMonth,
 283                           int hourOfDay, int minute, int second) {
 284         initTest();
 285         checkField(YEAR, year);
 286         checkField(MONTH, month);
 287         checkField(DAY_OF_MONTH, dayOfMonth);
 288         checkField(HOUR_OF_DAY, hourOfDay);
 289         checkField(MINUTE, minute);
 290         checkField(SECOND, second);
 291         return getStatus();
 292     }
 293 
 294     boolean checkDateTime(int year, int month, int dayOfMonth,
 295                           int hourOfDay, int minute, int second, int ms) {
 296         initTest();
 297         checkField(YEAR, year);
 298         checkField(MONTH, month);
 299         checkField(DAY_OF_MONTH, dayOfMonth);
 300         checkField(HOUR_OF_DAY, hourOfDay);
 301         checkField(MINUTE, minute);
 302         checkField(SECOND, second);
 303         checkField(MILLISECOND, ms);
 304         return getStatus();
 305     }
 306 
 307     boolean checkTimeOfDay(int hourOfDay, int minute, int second, int ms) {
 308         initTest();
 309         checkField(HOUR_OF_DAY, hourOfDay);
 310         checkField(MINUTE, minute);
 311         checkField(SECOND, second);
 312         checkField(MILLISECOND, ms);
 313         return getStatus();
 314     }
 315 
 316     boolean checkMillis(long millis) {
 317         initTest();
 318         long t = cal.getTimeInMillis();
 319         if (t != millis) {
 320             appendMessage("wrong millis: got " + t + ", expected " + millis);
 321             return false;
 322         }
 323         return true;
 324     }
 325 
 326     boolean checkFieldState(int field, boolean expectedState) {
 327         if (isSet(field) != expectedState) {
 328             appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; ");
 329             return false;
 330         }
 331         return true;
 332     }
 333 
 334     boolean checkField(int field, int expectedValue) {
 335         int val;
 336         if ((val = get(field)) != expectedValue) {
 337             appendMessage("get(" + FIELD_NAMES[field] + "): got " + val +
 338                           ", expected " + expectedValue + "; ");
 339             return false;
 340         }
 341         return true;
 342     }
 343 
 344     static final String fieldName(int field) {
 345         return FIELD_NAMES[field];
 346     }
 347 
 348     String toDateString() {
 349         StringBuffer sb = new StringBuffer();
 350         String[] eraNames = null;
 351         switch (type) {
 352         case GREGORIAN:
 353             eraNames = new String[] { "BCE", "" };
 354             break;
 355 
 356         case BUDDHIST:
 357             eraNames = new String[] { "Before BE", "BE"};
 358             break;
 359 
 360         case JAPANESE:
 361             eraNames = new String[] {
 362                 "BeforeMeiji",
 363                 "Meiji",
 364                 "Taisho",
 365                 "Showa",
 366                 "Heisei",
 367                 "NewEra"
 368             };
 369             break;
 370         }
 371 
 372         sb.append(eraNames[cal.get(ERA)]);
 373         if (sb.length() > 0)
 374             sb.append(' ');
 375         CalendarUtils.sprintf0d(sb, cal.get(YEAR), 4).append('-');
 376         CalendarUtils.sprintf0d(sb, cal.get(MONTH)+1, 2).append('-');
 377         CalendarUtils.sprintf0d(sb, cal.get(DAY_OF_MONTH), 2);
 378         return sb.toString();
 379     }
 380 
 381     String toTimeString() {
 382         StringBuffer sb = new StringBuffer();
 383         CalendarUtils.sprintf0d(sb, cal.get(HOUR_OF_DAY), 2).append(':');
 384         CalendarUtils.sprintf0d(sb, cal.get(MINUTE), 2).append(':');
 385         CalendarUtils.sprintf0d(sb, cal.get(SECOND),2 ).append('.');
 386         CalendarUtils.sprintf0d(sb, cal.get(MILLISECOND), 3);
 387         int zoneOffset = cal.get(ZONE_OFFSET) + cal.get(DST_OFFSET);
 388         if (zoneOffset == 0) {
 389             sb.append('Z');
 390         } else {
 391             int offset;
 392             char sign;
 393             if (zoneOffset > 0) {
 394                 offset = zoneOffset;
 395                 sign = '+';
 396             } else {
 397                 offset = -zoneOffset;
 398                 sign = '-';
 399             }
 400             offset /= 60000;
 401             sb.append(sign);
 402             CalendarUtils.sprintf0d(sb, offset / 60, 2);
 403             CalendarUtils.sprintf0d(sb, offset % 60, 2);
 404         }
 405         return sb.toString();
 406     }
 407 
 408     String toDateTimeString() {
 409         return toDateString() + "T" + toTimeString();
 410     }
 411 
 412     // Message handling
 413 
 414     StringBuffer msg = new StringBuffer();
 415 
 416     private void initTest() {
 417         msg = new StringBuffer();
 418     }
 419 
 420     String getMessage() {
 421         String s = msg.toString();
 422         msg = new StringBuffer();
 423         return "    " + s;
 424     }
 425 
 426     private void setMessage(String msg) {
 427         this.msg = new StringBuffer(msg);
 428     }
 429 
 430     private void appendMessage(String msg) {
 431         this.msg.append(msg);
 432     }
 433 
 434     boolean getStatus() {
 435         return msg.length() == 0;
 436     }
 437 }