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