1 /*
2 * #%L
3 * LongElement.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.NumericElement;
25 import com.allanbank.mongodb.bson.Visitor;
26 import com.allanbank.mongodb.bson.io.StringEncoder;
27
28 /**
29 * A wrapper for a BSON (signed 64-bit) integer or long.
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 LongElement extends AbstractElement implements NumericElement {
38
39 /** The BSON type for a long. */
40 public static final ElementType TYPE = ElementType.LONG;
41
42 /** Serialization version for the class. */
43 private static final long serialVersionUID = -2599658746763036474L;
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 long value. */
61 private final long myValue;
62
63 /**
64 * Constructs a new {@link LongElement}.
65 *
66 * @param name
67 * The name for the BSON long.
68 * @param value
69 * The BSON integer value.
70 * @throws IllegalArgumentException
71 * If the {@code name} is <code>null</code>.
72 */
73 public LongElement(final String name, final long value) {
74 this(name, value, computeSize(name));
75 }
76
77 /**
78 * Constructs a new {@link LongElement}.
79 *
80 * @param name
81 * The name for the BSON long.
82 * @param value
83 * The BSON integer value.
84 * @param size
85 * The size of the element when encoded in bytes. If not known
86 * then use the {@link LongElement#LongElement(String, long)}
87 * constructor instead.
88 * @throws IllegalArgumentException
89 * If the {@code name} is <code>null</code>.
90 */
91 public LongElement(final String name, final long value, final long size) {
92 super(name, size);
93
94 myValue = value;
95 }
96
97 /**
98 * Accepts the visitor and calls the {@link Visitor#visitLong} method.
99 *
100 * @see Element#accept(Visitor)
101 */
102 @Override
103 public void accept(final Visitor visitor) {
104 visitor.visitLong(getName(), getValue());
105 }
106
107 /**
108 * {@inheritDoc}
109 * <p>
110 * Overridden to compare the values if the base class comparison is equals.
111 * </p>
112 * <p>
113 * Note that for MongoDB integers, longs, and doubles will return equal
114 * based on the type. Care is taken here to make sure that double, integer,
115 * and long values return the same value regardless of comparison order by
116 * using the lowest resolution representation of the value.
117 * </p>
118 */
119 @Override
120 public int compareTo(final Element otherElement) {
121 int result = super.compareTo(otherElement);
122
123 if (result == 0) {
124 // Might be a IntegerElement, LongElement, or DoubleElement.
125 // Compare as integer or long.
126 final NumericElement other = (NumericElement) otherElement;
127 final ElementType otherType = other.getType();
128
129 if (otherType == ElementType.DOUBLE) {
130 result = Double.compare(getDoubleValue(),
131 other.getDoubleValue());
132 }
133 else {
134 result = compare(getLongValue(), other.getLongValue());
135 }
136 }
137
138 return result;
139 }
140
141 /**
142 * Determines if the passed object is of this same type as this object and
143 * if so that its fields are equal.
144 *
145 * @param object
146 * The object to compare to.
147 *
148 * @see java.lang.Object#equals(java.lang.Object)
149 */
150 @Override
151 public boolean equals(final Object object) {
152 boolean result = false;
153 if (this == object) {
154 result = true;
155 }
156 else if ((object != null) && (getClass() == object.getClass())) {
157 final LongElement other = (LongElement) object;
158
159 result = super.equals(object) && (myValue == other.myValue);
160 }
161 return result;
162 }
163
164 /**
165 * {@inheritDoc}
166 * <p>
167 * Overridden to return the value as a double.
168 * </p>
169 */
170 @Override
171 public double getDoubleValue() {
172 return myValue;
173 }
174
175 /**
176 * {@inheritDoc}
177 * <p>
178 * Overridden to cast the long value to an integer.
179 * </p>
180 */
181 @Override
182 public int getIntValue() {
183 return (int) myValue;
184 }
185
186 /**
187 * {@inheritDoc}
188 * <p>
189 * Overridden to return the value.
190 * </p>
191 */
192 @Override
193 public long getLongValue() {
194 return myValue;
195 }
196
197 /**
198 * {@inheritDoc}
199 */
200 @Override
201 public ElementType getType() {
202 return TYPE;
203 }
204
205 /**
206 * Returns the BSON long value.
207 *
208 * @return The BSON long value.
209 */
210 public long getValue() {
211 return myValue;
212 }
213
214 /**
215 * {@inheritDoc}
216 * <p>
217 * Returns a {@link Long} with the value.
218 * </p>
219 */
220 @Override
221 public Long getValueAsObject() {
222 return Long.valueOf(myValue);
223 }
224
225 /**
226 * {@inheritDoc}
227 * <p>
228 * Returns the result of {@link Long#toString(long)}.
229 * </p>
230 */
231 @Override
232 public String getValueAsString() {
233 return Long.toString(myValue);
234 }
235
236 /**
237 * Computes a reasonable hash code.
238 *
239 * @return The hash code value.
240 */
241 @Override
242 public int hashCode() {
243 int result = 1;
244 result = (31 * result) + super.hashCode();
245 result = (31 * result) + (int) (myValue & 0xFFFFFFFF);
246 result = (31 * result) + (int) ((myValue >> 32) & 0xFFFFFFFF);
247 return result;
248 }
249
250 /**
251 * {@inheritDoc}
252 * <p>
253 * Returns a new {@link LongElement}.
254 * </p>
255 */
256 @Override
257 public LongElement withName(final String name) {
258 if (getName().equals(name)) {
259 return this;
260 }
261 return new LongElement(name, myValue);
262 }
263 }