|
|
|
@@ -38,21 +38,21 @@ import javax.annotation.Nullable;
|
|
|
|
|
import org.joda.time.DateTime;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An entity property whose value transitions over time. Each value it takes on becomes active
|
|
|
|
|
* at a corresponding instant, and remains active until the next transition occurs. At least one
|
|
|
|
|
* "start of time" value (corresponding to START_OF_TIME, i.e. the Unix epoch) must be provided
|
|
|
|
|
* so that the property will have a value for all possible times.
|
|
|
|
|
* An entity property whose value transitions over time. Each value it takes on becomes active at a
|
|
|
|
|
* corresponding instant, and remains active until the next transition occurs. At least one "start
|
|
|
|
|
* of time" value (corresponding to START_OF_TIME, i.e. the Unix epoch) must be provided so that the
|
|
|
|
|
* property will have a value for all possible times.
|
|
|
|
|
*
|
|
|
|
|
* <p>This concept is naturally represented by a sorted map of {@code DateTime} to {@code V}, but
|
|
|
|
|
* the AppEngine datastore cannot natively represent a map keyed on non-strings. Instead, we store
|
|
|
|
|
* the App Engine Datastore cannot natively represent a map keyed on non-strings. Instead, we store
|
|
|
|
|
* an ordered list of transitions and use Objectify's @Mapify annotation to automatically recreate
|
|
|
|
|
* the sorted map on load from the datastore, which is used as a backing map for this property; the
|
|
|
|
|
* the sorted map on load from Datastore, which is used as a backing map for this property; the
|
|
|
|
|
* property itself also implements Map by way of extending ForwardingMap, so that this property can
|
|
|
|
|
* stored directly as the @Mapify field in the entity.
|
|
|
|
|
*
|
|
|
|
|
* <p>The type parameter {@code T} specifies a user-defined subclass of {@code TimedTransition<V>}
|
|
|
|
|
* to use for storing the list of transitions. The user is given this choice of subclass so that
|
|
|
|
|
* the field of the value type stored in the transition can be given a customized name.
|
|
|
|
|
* to use for storing the list of transitions. The user is given this choice of subclass so that the
|
|
|
|
|
* field of the value type stored in the transition can be given a customized name.
|
|
|
|
|
*/
|
|
|
|
|
public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedTransition<V>>
|
|
|
|
|
extends ForwardingMap<DateTime, T> {
|
|
|
|
@@ -62,7 +62,7 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|
|
|
|
* for the {@code DateTime}, which means that subclasses should supply the field of type {@code V}
|
|
|
|
|
* and implementations of the abstract getter and setter methods to access that field. This design
|
|
|
|
|
* is so that subclasses tagged with @Embed can define a custom field name for their value, for
|
|
|
|
|
* the purpose of backwards compatibility and better readability of the datastore representation.
|
|
|
|
|
* the purpose of backwards compatibility and better readability of the Datastore representation.
|
|
|
|
|
*
|
|
|
|
|
* <p>The public visibility of this class exists only so that it can be subclassed; clients should
|
|
|
|
|
* never call any methods on this class or attempt to access its members, but should instead treat
|
|
|
|
@@ -235,17 +235,15 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a new mutable {@code TimedTransitionProperty} representing the given map of DateTime
|
|
|
|
|
* to value, with transitions constructed using the given {@code TimedTransition} subclass.
|
|
|
|
|
* Returns a new mutable {@code TimedTransitionProperty} representing the given map of DateTime to
|
|
|
|
|
* value, with transitions constructed using the given {@code TimedTransition} subclass.
|
|
|
|
|
*
|
|
|
|
|
* <p>This method should only be used for initializing fields that are declared with the
|
|
|
|
|
* @Mapify annotation. The map for those fields must be mutable so that Objectify can load values
|
|
|
|
|
* from the datastore into the map, but clients should still never mutate the field's map
|
|
|
|
|
* directly.
|
|
|
|
|
* <p>This method should only be used for initializing fields that are declared with the @Mapify
|
|
|
|
|
* annotation. The map for those fields must be mutable so that Objectify can load values from
|
|
|
|
|
* Datastore into the map, but clients should still never mutate the field's map directly.
|
|
|
|
|
*/
|
|
|
|
|
public static <V, T extends TimedTransition<V>> TimedTransitionProperty<V, T> forMapify(
|
|
|
|
|
ImmutableSortedMap<DateTime, V> valueMap,
|
|
|
|
|
Class<T> timedTransitionSubclass) {
|
|
|
|
|
ImmutableSortedMap<DateTime, V> valueMap, Class<T> timedTransitionSubclass) {
|
|
|
|
|
return new TimedTransitionProperty<>(
|
|
|
|
|
new TreeMap<>(makeTransitionMap(valueMap, timedTransitionSubclass)));
|
|
|
|
|
}
|
|
|
|
@@ -254,10 +252,9 @@ public class TimedTransitionProperty<V, T extends TimedTransitionProperty.TimedT
|
|
|
|
|
* Returns a new mutable {@code TimedTransitionProperty} representing the given value being set at
|
|
|
|
|
* start of time, constructed using the given {@code TimedTransition} subclass.
|
|
|
|
|
*
|
|
|
|
|
* <p>This method should only be used for initializing fields that are declared with the
|
|
|
|
|
* @Mapify annotation. The map for those fields must be mutable so that Objectify can load values
|
|
|
|
|
* from the datastore into the map, but clients should still never mutate the field's map
|
|
|
|
|
* directly.
|
|
|
|
|
* <p>This method should only be used for initializing fields that are declared with the @Mapify
|
|
|
|
|
* annotation. The map for those fields must be mutable so that Objectify can load values from
|
|
|
|
|
* Datastore into the map, but clients should still never mutate the field's map directly.
|
|
|
|
|
*/
|
|
|
|
|
public static <V, T extends TimedTransition<V>> TimedTransitionProperty<V, T> forMapify(
|
|
|
|
|
V valueAtStartOfTime, Class<T> timedTransitionSubclass) {
|
|
|
|
|