Class CalendricalRule<T>
- java.lang.Object
-
- javax.time.calendar.CalendricalRule<T>
-
- Type Parameters:
T- the underlying type representing the data, typically aCalendrical,NumberorEnum, must be immutable, should be comparable
- All Implemented Interfaces:
java.io.Serializable,java.lang.Comparable<CalendricalRule<?>>,java.util.Comparator<Calendrical>
- Direct Known Subclasses:
Chronology.Rule,CopticDate.Rule,DateTimeFieldRule,HistoricDate.Rule,ISOChronology.EpochDaysRule,ISOChronology.NanoOfDayRule,LocalDate.Rule,LocalDateTime.Rule,LocalTime.Rule,MonthDay.Rule,OffsetDate.Rule,OffsetDateTime.Rule,OffsetTime.Rule,TimeZone.Rule,YearMonth.Rule,ZonedDateTime.Rule,ZoneOffset.Rule
public abstract class CalendricalRule<T> extends java.lang.Object implements java.lang.Comparable<CalendricalRule<?>>, java.util.Comparator<Calendrical>, java.io.Serializable
A rule defining how a single well-defined calendrical element operates.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 isComparable.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.
- See Also:
- Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description private ChronologychronologyThe chronology of the rule, not null.private java.lang.StringidThe id of the rule, not null.private java.lang.StringnameThe name of the rule, not null.private PeriodUnitperiodRangeThe period range, not null.private PeriodUnitperiodUnitThe period unit, not null.private java.lang.Class<T>reifiedThe reified class for the generic type.private static longserialVersionUIDA serialization identifier for this class.
-
Constructor Summary
Constructors Modifier Constructor Description protectedCalendricalRule(java.lang.Class<T> reifiedClass, Chronology chronology, java.lang.String name, PeriodUnit periodUnit, PeriodUnit periodRange)Constructor used to create a rule.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description intcompare(Calendrical cal1, Calendrical cal2)Compares twoCalendricalimplementations based on the value of this rule extracted from each calendrical.intcompareTo(CalendricalRule<?> other)Compares thisCalendricalRuleto another.protected Tderive(Calendrical calendrical)Derives the value of this rule from a calendrical.<R> RderiveValueFor(CalendricalRule<R> rule, T value, Calendrical calendrical, Chronology chronology)Derives the value of the specified rule from a calendrical.TderiveValueFrom(Calendrical calendrical)Derives the value of this rule from a calendrical.booleanequals(java.lang.Object obj)Compares two rules based on their ID.ChronologygetChronology()Gets the chronology of the rule.java.lang.StringgetID()Gets the ID of the rule.java.lang.StringgetName()Gets the name of the rule.PeriodUnitgetPeriodRange()Gets the range that the rule is bound by.PeriodUnitgetPeriodUnit()Gets the unit that the rule is measured in.java.lang.Class<T>getReifiedType()Gets the reified class representing the underlying type of the rule.TgetValue(Calendrical calendrical)Gets the value of this rule from the specified calendrical returningnullif the value cannot be returned.TgetValueChecked(Calendrical calendrical)Gets the value of the rule from the specified calendrical throwing an exception if the rule cannot be returned.inthashCode()Returns a hash code based on the ID.protected Tinterpret(CalendricalMerger merger, java.lang.Object value)Interprets the specified value converting it into an in range value of the correct type for this rule.(package private) TinterpretValue(CalendricalMerger merger, java.lang.Object value)Interprets the specified value converting it into an in range value of the correct type for this rule.protected voidmerge(CalendricalMerger merger)Merges this field with other fields to form higher level fields.Treify(java.lang.Object value)Returns the input value cast to the correct generic type.java.lang.StringtoString()Returns a string representation of the rule.
-
-
-
Field Detail
-
serialVersionUID
private static final long serialVersionUID
A serialization identifier for this class.- See Also:
- Constant Field Values
-
reified
private final java.lang.Class<T> reified
The reified class for the generic type.
-
chronology
private final Chronology chronology
The chronology of the rule, not null.
-
id
private final java.lang.String id
The id of the rule, not null.
-
name
private final java.lang.String name
The name of the rule, not null.
-
periodUnit
private final PeriodUnit periodUnit
The period unit, not null.
-
periodRange
private final PeriodUnit periodRange
The period range, not null.
-
-
Constructor Detail
-
CalendricalRule
protected CalendricalRule(java.lang.Class<T> reifiedClass, Chronology chronology, java.lang.String name, PeriodUnit periodUnit, PeriodUnit periodRange)
Constructor used to create a rule.- Parameters:
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 null
-
-
Method Detail
-
getChronology
public final Chronology getChronology()
Gets the chronology of the rule.- Returns:
- the chronology of the rule, never null
-
getID
public final java.lang.String getID()
Gets the ID of the rule.The ID is of the form 'ChronologyName.RuleName'. No two fields should have the same ID.
- Returns:
- the ID of the rule, never null
-
getName
public final java.lang.String getName()
Gets the name of the rule.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'.
- Returns:
- the name of the rule, never null
-
getPeriodUnit
public PeriodUnit getPeriodUnit()
Gets the unit that the rule is measured in.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
nullvalue is returned if the rule is not defined by a unit and range.- Returns:
- the unit defining the rule unit, null if this rule isn't based on a period
-
getPeriodRange
public PeriodUnit getPeriodRange()
Gets the range that the rule is bound by.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
nullwill be returned. Thenullvalue is also returned if the rule is not defined by a unit and range.- Returns:
- the unit defining the rule range, null if unbounded, or if this rule isn't based on a period
-
getReifiedType
public final java.lang.Class<T> getReifiedType()
Gets the reified class representing the underlying type of the rule.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.- Returns:
- the reified type of values of the rule, never null
-
reify
public final T reify(java.lang.Object value)
Returns the input value cast to the correct generic type.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.
- Parameters:
value- the value to reify, may be null- Returns:
- the type-cast input value, may be null
- Throws:
java.lang.ClassCastException- if the value is not of the reified type
-
getValue
public final T getValue(Calendrical calendrical)
Gets the value of this rule from the specified calendrical returningnullif the value cannot be returned.This method simply queries the calendrical.
- Parameters:
calendrical- the calendrical to get the field value from, not null- Returns:
- the value of the field, null if unable to extract the field
-
getValueChecked
public final T getValueChecked(Calendrical calendrical)
Gets the value of the rule from the specified calendrical throwing an exception if the rule cannot be returned.This convenience method uses
getValue(Calendrical)to find the value and then ensures it isn'tnull.- Parameters:
calendrical- the calendrical to get the field value from, not null- Returns:
- the value of the field, never null
- Throws:
UnsupportedRuleException- if the rule cannot be extracted
-
deriveValueFor
public final <R> R deriveValueFor(CalendricalRule<R> rule, T value, Calendrical calendrical, Chronology chronology)
Derives the value of the specified rule from a 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 rule, and this method is called on the rule of the calendrical implementation, not the rule passed into thegetmethod.public
The 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 inYear.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.- Parameters:
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 neutral- Returns:
- the value, null if unable to derive the value
-
deriveValueFrom
public final T deriveValueFrom(Calendrical calendrical)
Derives the value of this rule from a 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.public
T get(CalendricalRule rule) { // return data, for example if (rule.equals(...)) { return valueForRule; } // call this method return rule.deriveValueFrom(this); } - Parameters:
calendrical- the calendrical to get the value from, not null- Returns:
- the value, null if unable to derive the value
-
derive
protected T derive(Calendrical calendrical)
Derives the value of this rule from a 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.
- Parameters:
calendrical- the calendrical to derive from, not null- Returns:
- the derived value, null if unable to derive
-
interpretValue
final T interpretValue(CalendricalMerger merger, java.lang.Object value)
Interprets the specified value converting it into an in range value of the correct type for this rule.- Parameters:
merger- the merger instance controlling the merge process, not nullvalue- the value to interpret, not null
-
interpret
protected T interpret(CalendricalMerger merger, java.lang.Object value)
Interprets the specified value converting it into an in range value of the correct type for this rule.Before this method is called, the value will be checked to ensure it is not of the type of this rule.
- Parameters:
merger- the merger instance controlling the merge process, not nullvalue- the value to interpret, null if unable to interpret the value- Returns:
- the interpreted value
-
merge
protected void merge(CalendricalMerger merger)
Merges this field with other fields to form higher level fields.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 callingCalendricalMerger.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()); }- Parameters:
merger- the merger instance controlling the merge process, not null
-
compare
public int compare(Calendrical cal1, Calendrical cal2)
Compares twoCalendricalimplementations based on the value of this rule extracted from each calendrical.This implements the
Comparatorinterface and allows any twoCalendricalimplementations to be compared using this rule. The comparison is based on the result of callingCalendrical.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,YearMonthandZonedDateTime:List
If 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
Comparablethen an exception will be thrown.- Specified by:
comparein interfacejava.util.Comparator<T>- Parameters:
cal1- the first calendrical to compare, not nullcal2- the second calendrical to compare, not null- Returns:
- the comparator result, negative if first is less, positive if first is greater, zero if equal
- Throws:
java.lang.NullPointerException- if either input is nulljava.lang.ClassCastException- if this rule has a type that is not comparablejava.lang.IllegalArgumentException- if this rule cannot be extracted from either input parameter
-
compareTo
public int compareTo(CalendricalRule<?> other)
Compares thisCalendricalRuleto 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.
- Specified by:
compareToin interfacejava.lang.Comparable<T>- Parameters:
other- the other type to compare to, not null- Returns:
- the comparator result, negative if less, positive if greater, zero if equal
- Throws:
java.lang.NullPointerException- if other is null
-
equals
public boolean equals(java.lang.Object obj)
Compares two rules based on their ID.- Specified by:
equalsin interfacejava.util.Comparator<T>- Overrides:
equalsin classjava.lang.Object- Returns:
- true if the rules are the same
-
hashCode
public int hashCode()
Returns a hash code based on the ID.- Overrides:
hashCodein classjava.lang.Object- Returns:
- a description of the rule
-
toString
public java.lang.String toString()
Returns a string representation of the rule.- Overrides:
toStringin classjava.lang.Object- Returns:
- a description of the rule, never null
-
-