View Javadoc
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 }