1 /*
2 * #%L
3 * MongoTimestampElement.java - mongodb-async-driver - Allanbank Consulting, Inc.
4 * %%
5 * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6 * %%
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * #L%
19 */
20 package com.allanbank.mongodb.bson.element;
21
22 import com.allanbank.mongodb.bson.Element;
23 import com.allanbank.mongodb.bson.ElementType;
24 import com.allanbank.mongodb.bson.Visitor;
25 import com.allanbank.mongodb.bson.io.StringEncoder;
26
27 /**
28 * A wrapper for a BSON (signed 64-bit) Mongo timestamp as 4 byte increment and
29 * 4 byte timestamp.
30 *
31 * @api.yes This class is part of the driver's API. Public and protected members
32 * will be deprecated for at least 1 non-bugfix release (version
33 * numbers are <major>.<minor>.<bugfix>) before being
34 * removed or modified.
35 * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
36 */
37 public class MongoTimestampElement extends AbstractElement {
38
39 /** The BSON type for a long. */
40 public static final ElementType TYPE = ElementType.MONGO_TIMESTAMP;
41
42 /** Serialization version for the class. */
43 private static final long serialVersionUID = -402083578422199042L;
44
45 /**
46 * Computes and returns the number of bytes that are used to encode the
47 * element.
48 *
49 * @param name
50 * The name for the element.
51 * @return The size of the element when encoded in bytes.
52 */
53 private static long computeSize(final String name) {
54 long result = 10; // type (1) + name null byte (1) + value (8).
55 result += StringEncoder.utf8Size(name);
56
57 return result;
58 }
59
60 /** The BSON timestamp value as 4 byte increment and 4 byte timestamp. */
61 private final long myTimestamp;
62
63 /**
64 * Constructs a new {@link MongoTimestampElement}.
65 *
66 * @param name
67 * The name for the BSON long.
68 * @param value
69 * The BSON timestamp value as 4 byte increment and 4 byte
70 * timestamp.
71 * @throws IllegalArgumentException
72 * If the {@code name} is <code>null</code>.
73 */
74 public MongoTimestampElement(final String name, final long value) {
75 this(name, value, computeSize(name));
76 }
77
78 /**
79 * Constructs a new {@link MongoTimestampElement}.
80 *
81 * @param name
82 * The name for the BSON long.
83 * @param value
84 * The BSON timestamp value as 4 byte increment and 4 byte
85 * timestamp.
86 * @param size
87 * The size of the element when encoded in bytes. If not known
88 * then use the
89 * {@link MongoTimestampElement#MongoTimestampElement(String, long)}
90 * constructor instead.
91 * @throws IllegalArgumentException
92 * If the {@code name} is <code>null</code>.
93 */
94 public MongoTimestampElement(final String name, final long value,
95 final long size) {
96 super(name, size);
97
98 myTimestamp = value;
99 }
100
101 /**
102 * Accepts the visitor and calls the {@link Visitor#visitMongoTimestamp}
103 * method.
104 *
105 * @see Element#accept(Visitor)
106 */
107 @Override
108 public void accept(final Visitor visitor) {
109 visitor.visitMongoTimestamp(getName(), getTime());
110 }
111
112 /**
113 * {@inheritDoc}
114 * <p>
115 * Overridden to compare the times if the base class comparison is equals.
116 * </p>
117 * <p>
118 * Note that for MongoDB {@link MongoTimestampElement} and
119 * {@link TimestampElement} will return equal based on the type. Care is
120 * taken here to make sure that the values return the same value regardless
121 * of comparison order.
122 * </p>
123 */
124 @Override
125 public int compareTo(final Element otherElement) {
126 int result = super.compareTo(otherElement);
127
128 if (result == 0) {
129 // Might be a MongoTimestampElement or TimestampElement.
130 final ElementType otherType = otherElement.getType();
131
132 if (otherType == ElementType.MONGO_TIMESTAMP) {
133 result = compare(getTime(),
134 ((MongoTimestampElement) otherElement).getTime());
135 }
136 else {
137 result = compare(getTime(),
138 ((TimestampElement) otherElement).getTime());
139 }
140 }
141
142 return result;
143 }
144
145 /**
146 * Determines if the passed object is of this same type as this object and
147 * if so that its fields are equal.
148 *
149 * @param object
150 * The object to compare to.
151 *
152 * @see java.lang.Object#equals(java.lang.Object)
153 */
154 @Override
155 public boolean equals(final Object object) {
156 boolean result = false;
157 if (this == object) {
158 result = true;
159 }
160 else if ((object != null) && (getClass() == object.getClass())) {
161 final MongoTimestampElement other = (MongoTimestampElement) object;
162
163 result = super.equals(object) && (myTimestamp == other.myTimestamp);
164 }
165 return result;
166 }
167
168 /**
169 * Returns the BSON Mongo timestamp value as 4 byte increment and 4 byte
170 * timestamp.
171 *
172 * @return The BSON Mongo timestamp value as 4 byte increment and 4 byte
173 * timestamp.
174 */
175 public long getTime() {
176 return myTimestamp;
177 }
178
179 /**
180 * {@inheritDoc}
181 */
182 @Override
183 public ElementType getType() {
184 return TYPE;
185 }
186
187 /**
188 * {@inheritDoc}
189 * <p>
190 * Returns a {@link Long} with the value of the timestamp.
191 * </p>
192 * <p>
193 * <b>Note:</b> This value will not be recreated is a Object-->Element
194 * conversion. Long with the value of the timestamp is created instead.
195 * </p>
196 */
197 @Override
198 public Long getValueAsObject() {
199 return Long.valueOf(myTimestamp);
200 }
201
202 /**
203 * Computes a reasonable hash code.
204 *
205 * @return The hash code value.
206 */
207 @Override
208 public int hashCode() {
209 int result = 1;
210 result = (31 * result) + super.hashCode();
211 result = (31 * result) + (int) ((myTimestamp >> 32) & 0xFFFFFFFF);
212 result = (31 * result) + (int) (myTimestamp & 0xFFFFFFFF);
213 return result;
214 }
215
216 /**
217 * {@inheritDoc}
218 * <p>
219 * Returns a new {@link MongoTimestampElement}.
220 * </p>
221 */
222 @Override
223 public MongoTimestampElement withName(final String name) {
224 if (getName().equals(name)) {
225 return this;
226 }
227 return new MongoTimestampElement(name, myTimestamp);
228 }
229 }