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