View Javadoc
1   /*
2    * #%L
3    * TimestampElement.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 java.util.Date;
23  
24  import com.allanbank.mongodb.bson.Element;
25  import com.allanbank.mongodb.bson.ElementType;
26  import com.allanbank.mongodb.bson.Visitor;
27  import com.allanbank.mongodb.bson.io.StringEncoder;
28  
29  /**
30   * A wrapper for a BSON timestamp as the milliseconds since the epoch.
31   * 
32   * @api.yes This class is part of the driver's API. Public and protected members
33   *          will be deprecated for at least 1 non-bugfix release (version
34   *          numbers are <major>.<minor>.<bugfix>) before being
35   *          removed or modified.
36   * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
37   */
38  public class TimestampElement extends AbstractElement {
39  
40      /** The BSON type for a long. */
41      public static final ElementType TYPE = ElementType.UTC_TIMESTAMP;
42  
43      /** Serialization version for the class. */
44      private static final long serialVersionUID = 949598909338399091L;
45  
46      /**
47       * Computes and returns the number of bytes that are used to encode the
48       * element.
49       * 
50       * @param name
51       *            The name for the element.
52       * @return The size of the element when encoded in bytes.
53       */
54      private static long computeSize(final String name) {
55          long result = 10; // type (1) + name null byte (1) + value (8).
56          result += StringEncoder.utf8Size(name);
57  
58          return result;
59      }
60  
61      /** The BSON timestamp value as the milliseconds since the epoch. */
62      private final long myTimestamp;
63  
64      /**
65       * Constructs a new {@link TimestampElement}.
66       * 
67       * @param name
68       *            The name for the BSON long.
69       * @param value
70       *            The BSON timestamp value as the milliseconds since the epoch.
71       * @throws IllegalArgumentException
72       *             If the {@code name} is <code>null</code>.
73       */
74      public TimestampElement(final String name, final long value) {
75          this(name, value, computeSize(name));
76      }
77  
78      /**
79       * Constructs a new {@link TimestampElement}.
80       * 
81       * @param name
82       *            The name for the BSON long.
83       * @param value
84       *            The BSON timestamp value as the milliseconds since the epoch.
85       * @param size
86       *            The size of the element when encoded in bytes. If not known
87       *            then use the
88       *            {@link TimestampElement#TimestampElement(String, long)}
89       *            constructor instead.
90       * @throws IllegalArgumentException
91       *             If the {@code name} is <code>null</code>.
92       */
93      public TimestampElement(final String name, final long value, final long size) {
94          super(name, size);
95  
96          myTimestamp = value;
97      }
98  
99      /**
100      * Accepts the visitor and calls the {@link Visitor#visitTimestamp} method.
101      * 
102      * @see Element#accept(Visitor)
103      */
104     @Override
105     public void accept(final Visitor visitor) {
106         visitor.visitTimestamp(getName(), getTime());
107     }
108 
109     /**
110      * {@inheritDoc}
111      * <p>
112      * Overridden to compare the times if the base class comparison is equals.
113      * </p>
114      * <p>
115      * Note that for MongoDB {@link MongoTimestampElement} and
116      * {@link TimestampElement} will return equal based on the type. Care is
117      * taken here to make sure that the values return the same value regardless
118      * of comparison order.
119      * </p>
120      */
121     @Override
122     public int compareTo(final Element otherElement) {
123         int result = super.compareTo(otherElement);
124 
125         if (result == 0) {
126             // Might be a MongoTimestampElement or TimestampElement.
127             final ElementType otherType = otherElement.getType();
128 
129             if (otherType == ElementType.UTC_TIMESTAMP) {
130                 result = compare(getTime(),
131                         ((TimestampElement) otherElement).getTime());
132             }
133             else {
134                 result = compare(getTime(),
135                         ((MongoTimestampElement) otherElement).getTime());
136             }
137         }
138 
139         return result;
140     }
141 
142     /**
143      * Determines if the passed object is of this same type as this object and
144      * if so that its fields are equal.
145      * 
146      * @param object
147      *            The object to compare to.
148      * 
149      * @see java.lang.Object#equals(java.lang.Object)
150      */
151     @Override
152     public boolean equals(final Object object) {
153         boolean result = false;
154         if (this == object) {
155             result = true;
156         }
157         else if ((object != null) && (getClass() == object.getClass())) {
158             final TimestampElement other = (TimestampElement) object;
159 
160             result = super.equals(object) && (myTimestamp == other.myTimestamp);
161         }
162         return result;
163     }
164 
165     /**
166      * Returns the BSON timestamp value as the milliseconds since the epoch.
167      * 
168      * @return The BSON timestamp value as the milliseconds since the epoch.
169      */
170     public long getTime() {
171         return myTimestamp;
172     }
173 
174     /**
175      * {@inheritDoc}
176      */
177     @Override
178     public ElementType getType() {
179         return TYPE;
180     }
181 
182     /**
183      * {@inheritDoc}
184      * <p>
185      * Returns the {@link Date}.
186      * </p>
187      */
188     @Override
189     public Date getValueAsObject() {
190         return new Date(getTime());
191     }
192 
193     /**
194      * Computes a reasonable hash code.
195      * 
196      * @return The hash code value.
197      */
198     @Override
199     public int hashCode() {
200         int result = 1;
201         result = (31 * result) + super.hashCode();
202         result = (31 * result) + (int) (myTimestamp & 0xFFFFFFFF);
203         result = (31 * result) + (int) ((myTimestamp >> 32) & 0xFFFFFFFF);
204         return result;
205     }
206 
207     /**
208      * {@inheritDoc}
209      * <p>
210      * Returns a new {@link TimestampElement}.
211      * </p>
212      */
213     @Override
214     public TimestampElement withName(final String name) {
215         if (getName().equals(name)) {
216             return this;
217         }
218         return new TimestampElement(name, myTimestamp);
219     }
220 }