T
- the underlying type representing the data, typically a Calendrical
,
Number
or Enum
, must be immutable, should be comparablepublic abstract class CalendricalRule<T> extends Object implements Comparable<CalendricalRule<?>>, Comparator<Calendrical>, Serializable
Calendrical rules may define fields like day-of-month, combinations like date-time, or other related types like time-zone.
Each rule uses an underlying type to represent the data.
This is captured in the generic type of the rule.
The underlying type is reified and made available via getReifiedType()
.
It is expected, but not enforced, that the underlying type is Comparable
.
CalendricalRule is an abstract class and must be implemented with care to ensure other classes in the framework operate correctly. All instantiable subclasses must be final, immutable and thread-safe and must ensure serialization works correctly.
Modifier | Constructor and Description |
---|---|
protected |
CalendricalRule(Class<T> reifiedClass,
Chronology chronology,
String name,
PeriodUnit periodUnit,
PeriodUnit periodRange)
Constructor used to create a rule.
|
Modifier and Type | Method and Description |
---|---|
int |
compare(Calendrical cal1,
Calendrical cal2)
Compares two
Calendrical implementations based on the value
of this rule extracted from each calendrical. |
int |
compareTo(CalendricalRule<?> other)
Compares this
CalendricalRule to another. |
protected T |
derive(Calendrical calendrical)
Derives the value of this rule from a calendrical.
|
<R> R |
deriveValueFor(CalendricalRule<R> rule,
T value,
Calendrical calendrical,
Chronology chronology)
Derives the value of the specified rule from a calendrical.
|
T |
deriveValueFrom(Calendrical calendrical)
Derives the value of this rule from a calendrical.
|
boolean |
equals(Object obj)
Compares two rules based on their ID.
|
Chronology |
getChronology()
Gets the chronology of the rule.
|
String |
getID()
Gets the ID of the rule.
|
String |
getName()
Gets the name of the rule.
|
PeriodUnit |
getPeriodRange()
Gets the range that the rule is bound by.
|
PeriodUnit |
getPeriodUnit()
Gets the unit that the rule is measured in.
|
Class<T> |
getReifiedType()
Gets the reified class representing the underlying type of the rule.
|
T |
getValue(Calendrical calendrical)
Gets the value of this rule from the specified calendrical returning
null if the value cannot be returned. |
T |
getValueChecked(Calendrical calendrical)
Gets the value of the rule from the specified calendrical throwing
an exception if the rule cannot be returned.
|
int |
hashCode()
Returns a hash code based on the ID.
|
protected T |
interpret(CalendricalMerger merger,
Object value)
Interprets the specified value converting it into an in range value of the
correct type for this rule.
|
protected void |
merge(CalendricalMerger merger)
Merges this field with other fields to form higher level fields.
|
T |
reify(Object value)
Returns the input value cast to the correct generic type.
|
String |
toString()
Returns a string representation of the rule.
|
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
comparing, comparing, comparingDouble, comparingInt, comparingLong, naturalOrder, nullsFirst, nullsLast, reversed, reverseOrder, thenComparing, thenComparing, thenComparing, thenComparingDouble, thenComparingInt, thenComparingLong
protected CalendricalRule(Class<T> reifiedClass, Chronology chronology, String name, PeriodUnit periodUnit, PeriodUnit periodRange)
reifiedClass
- the reified class, not nullchronology
- the chronology, not nullname
- the name of the type, not nullperiodUnit
- the period unit, may be nullperiodRange
- the period range, may be nullpublic final Chronology getChronology()
public final String getID()
The ID is of the form 'ChronologyName.RuleName'. No two fields should have the same ID.
public final String getName()
Implementations should use the name that best represents themselves. If the rule represents a field, then the form 'UnitOfRange' should be used. Otherwise, use the simple class name of the generic type, such as 'ZoneOffset'.
public PeriodUnit getPeriodUnit()
Most rules define a field such as 'hour of day' or 'month of year'. The unit is the period that varies within the range.
For example, the rule for hour-of-day will return Hours, while the rule for month-of-year will return Months. The rule for a date will return Days as a date could alternately be described as 'days of forever'.
The null
value is returned if the rule is not defined by a unit and range.
public PeriodUnit getPeriodRange()
Most rules define a field such as 'hour of day' or 'month of year'. The range is the period that the field varies within.
For example, the rule for hour-of-day will return Days, while the rule for month-of-year will return Years.
When the range is unbounded, such as for a date or the year field, then null
will be returned.
The null
value is also returned if the rule is not defined by a unit and range.
public final Class<T> getReifiedType()
Each rule uses an underlying type to represent the data.
This is captured in the generic type of the rule.
Since the generic implementation is Java is limited to the compiler, the
underlying type has been reified and made available through this method.
It is expected, but not enforced, that the underlying type is Comparable
.
public final T reify(Object value)
Each rule uses an underlying type to represent the data. This is captured in the generic type of the rule. Since the generic implementation is Java is limited to the compiler, the underlying type has been reified which allows this method to validate the generic type fully. The implementation simply returns the input value typed as the generic type.
value
- the value to reify, may be nullClassCastException
- if the value is not of the reified typepublic final T getValue(Calendrical calendrical)
null
if the value cannot be returned.
This method simply queries the calendrical.
calendrical
- the calendrical to get the field value from, not nullpublic final T getValueChecked(Calendrical calendrical)
This convenience method uses getValue(Calendrical)
to find the value
and then ensures it isn't null
.
calendrical
- the calendrical to get the field value from, not nullUnsupportedRuleException
- if the rule cannot be extractedpublic final <R> R deriveValueFor(CalendricalRule<R> rule, T value, Calendrical calendrical, Chronology chronology)
This method is provided for implementations of Calendrical.get(javax.time.calendar.CalendricalRule<T>)
and is rarely called directly by application code. It is used when the
calendrical has its own rule, and this method is called on the rule of the
calendrical implementation, not the rule passed into the get
method.
publicThe last parameter in the code snippet above is alwaysT get(CalendricalRule rule) { return IMPLEMENTATION_RULE.deriveValueFor(rule, this, this); }
this
, however
the second parameter may be a different representation, for example in Year.get(javax.time.calendar.CalendricalRule<T>)
.
If this rule and the specified rule are the same, then the value is returned.
Otherwise, an attempt is made to derive(javax.time.calendar.Calendrical)
the field value.
rule
- the rule to retrieve, not nullvalue
- the value to return if this rule is the specified rule, not nullcalendrical
- the calendrical to get the value from, not nullchronology
- the chronology the value belongs to, null if chronology neutralpublic final T deriveValueFrom(Calendrical calendrical)
This method is provided for implementations of Calendrical.get(javax.time.calendar.CalendricalRule<T>)
and is rarely called directly by application code. It is used when the
calendrical has its own values but does not have its own rule.
publicT get(CalendricalRule rule) { // return data, for example if (rule.equals(...)) { return valueForRule; } // call this method return rule.deriveValueFrom(this); }
calendrical
- the calendrical to get the value from, not nullprotected T derive(Calendrical calendrical)
This method derives the value for this field from other fields in the calendrical without directly querying the calendrical for the value.
For example, if this field is quarter-of-year, then the value can be derived from month-of-year.
The implementation only needs to derive the value based on its immediate parents.
The use of Calendrical.get(javax.time.calendar.CalendricalRule<T>)
will extract any further parents on demand.
A typical implementation of this method obtains the parent value and performs a calculation. For example, here is a simple implementation for the quarter-of-year field:
Integer moyVal = calendrical.get(ISOChronology.monthOfYearRule()); return (moyVal != null ? ((moyVal - 1) % 4) + 1) : null;
This method is designed to be overridden in subclasses. The subclass implementation must be thread-safe. The subclass implementation must not request the value of this rule from the specified calendrical, otherwise a stack overflow error will occur.
calendrical
- the calendrical to derive from, not nullprotected T interpret(CalendricalMerger merger, Object value)
Before this method is called, the value will be checked to ensure it is not of the type of this rule.
merger
- the merger instance controlling the merge process, not nullvalue
- the value to interpret, null if unable to interpret the valueprotected void merge(CalendricalMerger merger)
The aim of this method is to assist in the process of extracting the most date-time information possible from a map of field-value pairs. The merging process is controlled by the mutable merger instance and the input and output of the this merge are held there.
Subclasses that override this method may use methods on the merger to obtain the values to merge. The value is guaranteed to be available for this field if this method is called.
If the override successfully merged some fields then the following must be performed.
The merged field must be stored using CalendricalMerger.storeMerged(javax.time.calendar.CalendricalRule<T>, T)
.
Each field used in the merge must be marked as being used by calling
CalendricalMerger.removeProcessed(javax.time.calendar.CalendricalRule<?>)
.
An example to merge two fields into one - hour of AM/PM and AM/PM:
Integer hapVal = merger.getValue(ISOChronology.hourOfAmPmRule()); if (hapVal != null) { AmPmOfDay amPm = merger.getValue(this); int hourOfDay = MathUtils.safeAdd(MathUtils.safeMultiply(amPm, 12), hapVal); merger.storeMerged(ISOChronology.hourOfDayRule(), hourOfDay); merger.removeProcessed(this); merger.removeProcessed(ISOChronology.hourOfAmPmRule()); }
merger
- the merger instance controlling the merge process, not nullpublic int compare(Calendrical cal1, Calendrical cal2)
Calendrical
implementations based on the value
of this rule extracted from each calendrical.
This implements the Comparator
interface and allows any two
Calendrical
implementations to be compared using this rule.
The comparison is based on the result of calling Calendrical.get(javax.time.calendar.CalendricalRule<T>)
on each calendrical, and comparing those values.
For example, to sort a list into year order when the list may contain any
mixture of calendricals, such as a LocalDate
, YearMonth
and ZonedDateTime
:
ListIf the value of this rule cannot be obtained from a calendrical, then an exception is thrown.list = ... Collections.sort(list, ISOChronology.yearRule());
If the underlying type of this rule does not implement Comparable
then an exception will be thrown.
compare
in interface Comparator<Calendrical>
cal1
- the first calendrical to compare, not nullcal2
- the second calendrical to compare, not nullNullPointerException
- if either input is nullClassCastException
- if this rule has a type that is not comparableIllegalArgumentException
- if this rule cannot be extracted from either input parameterpublic int compareTo(CalendricalRule<?> other)
CalendricalRule
to another.
The comparison is based on the period unit followed by the period range followed by the rule ID. The period unit is compared first, so MinuteOfHour will be less than HourOfDay, which will be less than DayOfWeek. When the period unit is the same, the period range is compared, so DayOfWeek is less than DayOfMonth, which is less than DayOfYear. Finally, the rule ID is compared.
compareTo
in interface Comparable<CalendricalRule<?>>
other
- the other type to compare to, not nullNullPointerException
- if other is nullpublic boolean equals(Object obj)
equals
in interface Comparator<Calendrical>
equals
in class Object
public int hashCode()
Copyright © 2014. All rights reserved.