001 /* 002 * Copyright 2001-2005 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time.chrono; 017 018 import java.io.IOException; 019 import java.io.ObjectInputStream; 020 021 import org.joda.time.Chronology; 022 import org.joda.time.DateTimeField; 023 import org.joda.time.DateTimeZone; 024 import org.joda.time.DurationField; 025 026 /** 027 * Abstract Chronology that enables chronologies to be assembled from 028 * a container of fields. 029 * <p> 030 * AssembledChronology is thread-safe and immutable. 031 * 032 * @author Brian S O'Neill 033 * @since 1.0 034 */ 035 public abstract class AssembledChronology extends BaseChronology { 036 037 private static final long serialVersionUID = -6728465968995518215L; 038 039 private final Chronology iBase; 040 private final Object iParam; 041 042 private transient DurationField iMillis; 043 private transient DurationField iSeconds; 044 private transient DurationField iMinutes; 045 private transient DurationField iHours; 046 private transient DurationField iHalfdays; 047 048 private transient DurationField iDays; 049 private transient DurationField iWeeks; 050 private transient DurationField iWeekyears; 051 private transient DurationField iMonths; 052 private transient DurationField iYears; 053 private transient DurationField iCenturies; 054 private transient DurationField iEras; 055 056 private transient DateTimeField iMillisOfSecond; 057 private transient DateTimeField iMillisOfDay; 058 private transient DateTimeField iSecondOfMinute; 059 private transient DateTimeField iSecondOfDay; 060 private transient DateTimeField iMinuteOfHour; 061 private transient DateTimeField iMinuteOfDay; 062 private transient DateTimeField iHourOfDay; 063 private transient DateTimeField iClockhourOfDay; 064 private transient DateTimeField iHourOfHalfday; 065 private transient DateTimeField iClockhourOfHalfday; 066 private transient DateTimeField iHalfdayOfDay; 067 068 private transient DateTimeField iDayOfWeek; 069 private transient DateTimeField iDayOfMonth; 070 private transient DateTimeField iDayOfYear; 071 private transient DateTimeField iWeekOfWeekyear; 072 private transient DateTimeField iWeekyear; 073 private transient DateTimeField iWeekyearOfCentury; 074 private transient DateTimeField iMonthOfYear; 075 private transient DateTimeField iYear; 076 private transient DateTimeField iYearOfEra; 077 private transient DateTimeField iYearOfCentury; 078 private transient DateTimeField iCenturyOfEra; 079 private transient DateTimeField iEra; 080 081 // Bit set determines which base fields are used 082 // bit 1 set: hourOfDay, minuteOfHour, secondOfMinute, and millisOfSecond fields 083 // bit 2 set: millisOfDayField 084 // bit 3 set: year, monthOfYear, and dayOfMonth fields 085 private transient int iBaseFlags; 086 087 /** 088 * Constructor calls the assemble method, enabling subclasses to define its 089 * supported fields. If a base chronology is supplied, the field set 090 * initially contains references to each base chronology field. 091 * <p> 092 * Other methods in this class will delegate to the base chronology, if it 093 * can be determined that the base chronology will produce the same results 094 * as AbstractChronology. 095 * 096 * @param base optional base chronology to copy initial fields from 097 * @param param optional param object avalable for assemble method 098 */ 099 protected AssembledChronology(Chronology base, Object param) { 100 iBase = base; 101 iParam = param; 102 setFields(); 103 } 104 105 public DateTimeZone getZone() { 106 Chronology base; 107 if ((base = iBase) != null) { 108 return base.getZone(); 109 } 110 return null; 111 } 112 113 public long getDateTimeMillis(int year, int monthOfYear, int dayOfMonth, 114 int millisOfDay) 115 throws IllegalArgumentException 116 { 117 Chronology base; 118 if ((base = iBase) != null && (iBaseFlags & 6) == 6) { 119 // Only call specialized implementation if applicable fields are the same. 120 return base.getDateTimeMillis(year, monthOfYear, dayOfMonth, millisOfDay); 121 } 122 return super.getDateTimeMillis(year, monthOfYear, dayOfMonth, millisOfDay); 123 } 124 125 public long getDateTimeMillis(int year, int monthOfYear, int dayOfMonth, 126 int hourOfDay, int minuteOfHour, 127 int secondOfMinute, int millisOfSecond) 128 throws IllegalArgumentException 129 { 130 Chronology base; 131 if ((base = iBase) != null && (iBaseFlags & 5) == 5) { 132 // Only call specialized implementation if applicable fields are the same. 133 return base.getDateTimeMillis(year, monthOfYear, dayOfMonth, 134 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 135 } 136 return super.getDateTimeMillis(year, monthOfYear, dayOfMonth, 137 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 138 } 139 140 public long getDateTimeMillis(long instant, 141 int hourOfDay, int minuteOfHour, 142 int secondOfMinute, int millisOfSecond) 143 throws IllegalArgumentException 144 { 145 Chronology base; 146 if ((base = iBase) != null && (iBaseFlags & 1) == 1) { 147 // Only call specialized implementation if applicable fields are the same. 148 return base.getDateTimeMillis 149 (instant, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 150 } 151 return super.getDateTimeMillis 152 (instant, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 153 } 154 155 public final DurationField millis() { 156 return iMillis; 157 } 158 159 public final DateTimeField millisOfSecond() { 160 return iMillisOfSecond; 161 } 162 163 public final DateTimeField millisOfDay() { 164 return iMillisOfDay; 165 } 166 167 public final DurationField seconds() { 168 return iSeconds; 169 } 170 171 public final DateTimeField secondOfMinute() { 172 return iSecondOfMinute; 173 } 174 175 public final DateTimeField secondOfDay() { 176 return iSecondOfDay; 177 } 178 179 public final DurationField minutes() { 180 return iMinutes; 181 } 182 183 public final DateTimeField minuteOfHour() { 184 return iMinuteOfHour; 185 } 186 187 public final DateTimeField minuteOfDay() { 188 return iMinuteOfDay; 189 } 190 191 public final DurationField hours() { 192 return iHours; 193 } 194 195 public final DateTimeField hourOfDay() { 196 return iHourOfDay; 197 } 198 199 public final DateTimeField clockhourOfDay() { 200 return iClockhourOfDay; 201 } 202 203 public final DurationField halfdays() { 204 return iHalfdays; 205 } 206 207 public final DateTimeField hourOfHalfday() { 208 return iHourOfHalfday; 209 } 210 211 public final DateTimeField clockhourOfHalfday() { 212 return iClockhourOfHalfday; 213 } 214 215 public final DateTimeField halfdayOfDay() { 216 return iHalfdayOfDay; 217 } 218 219 public final DurationField days() { 220 return iDays; 221 } 222 223 public final DateTimeField dayOfWeek() { 224 return iDayOfWeek; 225 } 226 227 public final DateTimeField dayOfMonth() { 228 return iDayOfMonth; 229 } 230 231 public final DateTimeField dayOfYear() { 232 return iDayOfYear; 233 } 234 235 public final DurationField weeks() { 236 return iWeeks; 237 } 238 239 public final DateTimeField weekOfWeekyear() { 240 return iWeekOfWeekyear; 241 } 242 243 public final DurationField weekyears() { 244 return iWeekyears; 245 } 246 247 public final DateTimeField weekyear() { 248 return iWeekyear; 249 } 250 251 public final DateTimeField weekyearOfCentury() { 252 return iWeekyearOfCentury; 253 } 254 255 public final DurationField months() { 256 return iMonths; 257 } 258 259 public final DateTimeField monthOfYear() { 260 return iMonthOfYear; 261 } 262 263 public final DurationField years() { 264 return iYears; 265 } 266 267 public final DateTimeField year() { 268 return iYear; 269 } 270 271 public final DateTimeField yearOfEra() { 272 return iYearOfEra; 273 } 274 275 public final DateTimeField yearOfCentury() { 276 return iYearOfCentury; 277 } 278 279 public final DurationField centuries() { 280 return iCenturies; 281 } 282 283 public final DateTimeField centuryOfEra() { 284 return iCenturyOfEra; 285 } 286 287 public final DurationField eras() { 288 return iEras; 289 } 290 291 public final DateTimeField era() { 292 return iEra; 293 } 294 295 /** 296 * Invoked by the constructor and after deserialization to allow subclasses 297 * to define all of its supported fields. All unset fields default to 298 * unsupported instances. 299 * 300 * @param fields container of fields 301 */ 302 protected abstract void assemble(Fields fields); 303 304 /** 305 * Returns the same base chronology as passed into the constructor. 306 */ 307 protected final Chronology getBase() { 308 return iBase; 309 } 310 311 /** 312 * Returns the same param object as passed into the constructor. 313 */ 314 protected final Object getParam() { 315 return iParam; 316 } 317 318 private void setFields() { 319 Fields fields = new Fields(); 320 if (iBase != null) { 321 fields.copyFieldsFrom(iBase); 322 } 323 assemble(fields); 324 325 { 326 DurationField f; 327 iMillis = (f = fields.millis) != null ? f : super.millis(); 328 iSeconds = (f = fields.seconds) != null ? f : super.seconds(); 329 iMinutes = (f = fields.minutes) != null ? f : super.minutes(); 330 iHours = (f = fields.hours) != null ? f : super.hours(); 331 iHalfdays = (f = fields.halfdays) != null ? f : super.halfdays(); 332 iDays = (f = fields.days) != null ? f : super.days(); 333 iWeeks = (f = fields.weeks) != null ? f : super.weeks(); 334 iWeekyears = (f = fields.weekyears) != null ? f : super.weekyears(); 335 iMonths = (f = fields.months) != null ? f : super.months(); 336 iYears = (f = fields.years) != null ? f : super.years(); 337 iCenturies = (f = fields.centuries) != null ? f : super.centuries(); 338 iEras = (f = fields.eras) != null ? f : super.eras(); 339 } 340 341 { 342 DateTimeField f; 343 iMillisOfSecond = (f = fields.millisOfSecond) != null ? f : super.millisOfSecond(); 344 iMillisOfDay = (f = fields.millisOfDay) != null ? f : super.millisOfDay(); 345 iSecondOfMinute = (f = fields.secondOfMinute) != null ? f : super.secondOfMinute(); 346 iSecondOfDay = (f = fields.secondOfDay) != null ? f : super.secondOfDay(); 347 iMinuteOfHour = (f = fields.minuteOfHour) != null ? f : super.minuteOfHour(); 348 iMinuteOfDay = (f = fields.minuteOfDay) != null ? f : super.minuteOfDay(); 349 iHourOfDay = (f = fields.hourOfDay) != null ? f : super.hourOfDay(); 350 iClockhourOfDay = (f = fields.clockhourOfDay) != null ? f : super.clockhourOfDay(); 351 iHourOfHalfday = (f = fields.hourOfHalfday) != null ? f : super.hourOfHalfday(); 352 iClockhourOfHalfday = (f = fields.clockhourOfHalfday) != null ? f : super.clockhourOfHalfday(); 353 iHalfdayOfDay = (f = fields.halfdayOfDay) != null ? f : super.halfdayOfDay(); 354 iDayOfWeek = (f = fields.dayOfWeek) != null ? f : super.dayOfWeek(); 355 iDayOfMonth = (f = fields.dayOfMonth) != null ? f : super.dayOfMonth(); 356 iDayOfYear = (f = fields.dayOfYear) != null ? f : super.dayOfYear(); 357 iWeekOfWeekyear = (f = fields.weekOfWeekyear) != null ? f : super.weekOfWeekyear(); 358 iWeekyear = (f = fields.weekyear) != null ? f : super.weekyear(); 359 iWeekyearOfCentury = (f = fields.weekyearOfCentury) != null ? f : super.weekyearOfCentury(); 360 iMonthOfYear = (f = fields.monthOfYear) != null ? f : super.monthOfYear(); 361 iYear = (f = fields.year) != null ? f : super.year(); 362 iYearOfEra = (f = fields.yearOfEra) != null ? f : super.yearOfEra(); 363 iYearOfCentury = (f = fields.yearOfCentury) != null ? f : super.yearOfCentury(); 364 iCenturyOfEra = (f = fields.centuryOfEra) != null ? f : super.centuryOfEra(); 365 iEra = (f = fields.era) != null ? f : super.era(); 366 } 367 368 int flags; 369 if (iBase == null) { 370 flags = 0; 371 } else { 372 flags = 373 ((iHourOfDay == iBase.hourOfDay() && 374 iMinuteOfHour == iBase.minuteOfHour() && 375 iSecondOfMinute == iBase.secondOfMinute() && 376 iMillisOfSecond == iBase.millisOfSecond() ) ? 1 : 0) | 377 378 ((iMillisOfDay == iBase.millisOfDay()) ? 2 : 0) | 379 380 ((iYear == iBase.year() && 381 iMonthOfYear == iBase.monthOfYear() && 382 iDayOfMonth == iBase.dayOfMonth() ) ? 4 : 0); 383 } 384 385 iBaseFlags = flags; 386 } 387 388 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 389 in.defaultReadObject(); 390 setFields(); 391 } 392 393 /** 394 * A container of fields used for assembling a chronology. 395 */ 396 public static final class Fields { 397 public DurationField millis; 398 public DurationField seconds; 399 public DurationField minutes; 400 public DurationField hours; 401 public DurationField halfdays; 402 403 public DurationField days; 404 public DurationField weeks; 405 public DurationField weekyears; 406 public DurationField months; 407 public DurationField years; 408 public DurationField centuries; 409 public DurationField eras; 410 411 public DateTimeField millisOfSecond; 412 public DateTimeField millisOfDay; 413 public DateTimeField secondOfMinute; 414 public DateTimeField secondOfDay; 415 public DateTimeField minuteOfHour; 416 public DateTimeField minuteOfDay; 417 public DateTimeField hourOfDay; 418 public DateTimeField clockhourOfDay; 419 public DateTimeField hourOfHalfday; 420 public DateTimeField clockhourOfHalfday; 421 public DateTimeField halfdayOfDay; 422 423 public DateTimeField dayOfWeek; 424 public DateTimeField dayOfMonth; 425 public DateTimeField dayOfYear; 426 public DateTimeField weekOfWeekyear; 427 public DateTimeField weekyear; 428 public DateTimeField weekyearOfCentury; 429 public DateTimeField monthOfYear; 430 public DateTimeField year; 431 public DateTimeField yearOfEra; 432 public DateTimeField yearOfCentury; 433 public DateTimeField centuryOfEra; 434 public DateTimeField era; 435 436 Fields() { 437 } 438 439 /** 440 * Copy the supported fields from a chronology into this container. 441 */ 442 public void copyFieldsFrom(Chronology chrono) { 443 { 444 DurationField f; 445 if (isSupported(f = chrono.millis())) { 446 millis = f; 447 } 448 if (isSupported(f = chrono.seconds())) { 449 seconds = f; 450 } 451 if (isSupported(f = chrono.minutes())) { 452 minutes = f; 453 } 454 if (isSupported(f = chrono.hours())) { 455 hours = f; 456 } 457 if (isSupported(f = chrono.halfdays())) { 458 halfdays = f; 459 } 460 if (isSupported(f = chrono.days())) { 461 days = f; 462 } 463 if (isSupported(f = chrono.weeks())) { 464 weeks = f; 465 } 466 if (isSupported(f = chrono.weekyears())) { 467 weekyears = f; 468 } 469 if (isSupported(f = chrono.months())) { 470 months = f; 471 } 472 if (isSupported(f = chrono.years())) { 473 years = f; 474 } 475 if (isSupported(f = chrono.centuries())) { 476 centuries = f; 477 } 478 if (isSupported(f = chrono.eras())) { 479 eras = f; 480 } 481 } 482 483 { 484 DateTimeField f; 485 if (isSupported(f = chrono.millisOfSecond())) { 486 millisOfSecond = f; 487 } 488 if (isSupported(f = chrono.millisOfDay())) { 489 millisOfDay = f; 490 } 491 if (isSupported(f = chrono.secondOfMinute())) { 492 secondOfMinute = f; 493 } 494 if (isSupported(f = chrono.secondOfDay())) { 495 secondOfDay = f; 496 } 497 if (isSupported(f = chrono.minuteOfHour())) { 498 minuteOfHour = f; 499 } 500 if (isSupported(f = chrono.minuteOfDay())) { 501 minuteOfDay = f; 502 } 503 if (isSupported(f = chrono.hourOfDay())) { 504 hourOfDay = f; 505 } 506 if (isSupported(f = chrono.clockhourOfDay())) { 507 clockhourOfDay = f; 508 } 509 if (isSupported(f = chrono.hourOfHalfday())) { 510 hourOfHalfday = f; 511 } 512 if (isSupported(f = chrono.clockhourOfHalfday())) { 513 clockhourOfHalfday = f; 514 } 515 if (isSupported(f = chrono.halfdayOfDay())) { 516 halfdayOfDay = f; 517 } 518 if (isSupported(f = chrono.dayOfWeek())) { 519 dayOfWeek = f; 520 } 521 if (isSupported(f = chrono.dayOfMonth())) { 522 dayOfMonth = f; 523 } 524 if (isSupported(f = chrono.dayOfYear())) { 525 dayOfYear = f; 526 } 527 if (isSupported(f = chrono.weekOfWeekyear())) { 528 weekOfWeekyear = f; 529 } 530 if (isSupported(f = chrono.weekyear())) { 531 weekyear = f; 532 } 533 if (isSupported(f = chrono.weekyearOfCentury())) { 534 weekyearOfCentury = f; 535 } 536 if (isSupported(f = chrono.monthOfYear())) { 537 monthOfYear = f; 538 } 539 if (isSupported(f = chrono.year())) { 540 year = f; 541 } 542 if (isSupported(f = chrono.yearOfEra())) { 543 yearOfEra = f; 544 } 545 if (isSupported(f = chrono.yearOfCentury())) { 546 yearOfCentury = f; 547 } 548 if (isSupported(f = chrono.centuryOfEra())) { 549 centuryOfEra = f; 550 } 551 if (isSupported(f = chrono.era())) { 552 era = f; 553 } 554 } 555 } 556 557 private static boolean isSupported(DurationField field) { 558 return field == null ? false : field.isSupported(); 559 } 560 561 private static boolean isSupported(DateTimeField field) { 562 return field == null ? false : field.isSupported(); 563 } 564 } 565 }