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 }