Import atomix/{storage,utils}
[controller.git] / third-party / atomix / utils / src / main / java / io / atomix / utils / time / Versioned.java
1 /*
2  * Copyright 2015-present Open Networking Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.atomix.utils.time;
18
19 import com.google.common.base.MoreObjects;
20 import com.google.common.base.Objects;
21 import io.atomix.utils.misc.ArraySizeHashPrinter;
22 import io.atomix.utils.misc.TimestampPrinter;
23
24 import java.util.function.Function;
25
26 /**
27  * Versioned value.
28  *
29  * @param <V> value type.
30  */
31 public class Versioned<V> {
32   private final V value;
33   private final long version;
34   private final long creationTime;
35
36   /**
37    * Constructs a new versioned value.
38    *
39    * @param value        value
40    * @param version      version
41    * @param creationTime milliseconds of the creation event
42    *                     from the Java epoch of 1970-01-01T00:00:00Z
43    */
44   public Versioned(V value, long version, long creationTime) {
45     this.value = value;
46     this.version = version;
47     this.creationTime = creationTime;
48   }
49
50   /**
51    * Constructs a new versioned value.
52    *
53    * @param value   value
54    * @param version version
55    */
56   public Versioned(V value, long version) {
57     this(value, version, System.currentTimeMillis());
58   }
59
60   /**
61    * Returns the value.
62    *
63    * @return value.
64    */
65   public V value() {
66     return value;
67   }
68
69   /**
70    * Returns the version.
71    *
72    * @return version
73    */
74   public long version() {
75     return version;
76   }
77
78   /**
79    * Returns the system time when this version was created.
80    * <p>
81    * Care should be taken when relying on creationTime to
82    * implement any behavior in a distributed setting. Due
83    * to the possibility of clock skew it is likely that
84    * even creationTimes of causally related versions can be
85    * out or order.
86    *
87    * @return creation time
88    */
89   public long creationTime() {
90     return creationTime;
91   }
92
93   /**
94    * Maps this instance into another after transforming its
95    * value while retaining the same version and creationTime.
96    *
97    * @param transformer function for mapping the value
98    * @param <U>         value type of the returned instance
99    * @return mapped instance
100    */
101   public synchronized <U> Versioned<U> map(Function<V, U> transformer) {
102     return new Versioned<>(value != null ? transformer.apply(value) : null, version, creationTime);
103   }
104
105   /**
106    * Returns the value of the specified Versioned object if non-null or else returns
107    * a default value.
108    *
109    * @param versioned    versioned object
110    * @param defaultValue default value to return if versioned object is null
111    * @param <U>          type of the versioned value
112    * @return versioned value or default value if versioned object is null
113    */
114   public static <U> U valueOrElse(Versioned<U> versioned, U defaultValue) {
115     return versioned == null ? defaultValue : versioned.value();
116   }
117
118   /**
119    * Returns the value of the specified Versioned object if non-null or else returns null.
120    *
121    * @param versioned versioned object
122    * @param <U>       type of the versioned value
123    * @return versioned value or null if versioned object is null
124    */
125   public static <U> U valueOrNull(Versioned<U> versioned) {
126     return valueOrElse(versioned, null);
127   }
128
129   @Override
130   public int hashCode() {
131     return Objects.hashCode(value, version, creationTime);
132   }
133
134   @Override
135   public boolean equals(Object other) {
136     if (!(other instanceof Versioned)) {
137       return false;
138     }
139     Versioned<V> that = (Versioned) other;
140     return Objects.equal(this.value, that.value)
141         && Objects.equal(this.version, that.version)
142         && Objects.equal(this.creationTime, that.creationTime);
143   }
144
145   @Override
146   public String toString() {
147     return MoreObjects.toStringHelper(this)
148         .add("value", value instanceof byte[] ? ArraySizeHashPrinter.of((byte[]) value) : value)
149         .add("version", version)
150         .add("creationTime", new TimestampPrinter(creationTime))
151         .toString();
152   }
153 }