View Javadoc
1   /*
2    * #%L
3    * IntegerElement.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 32-bit) integer.
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 IntegerElement extends AbstractElement implements NumericElement {
38  
39      /** The BSON type for a integer. */
40      public static final ElementType TYPE = ElementType.INTEGER;
41  
42      /** Serialization version for the class. */
43      private static final long serialVersionUID = 3738845320555958508L;
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 = 6; // type (1) + name null byte (1) + value (4).
55          result += StringEncoder.utf8Size(name);
56  
57          return result;
58      }
59  
60      /** The BSON integer value. */
61      private final int myValue;
62  
63      /**
64       * Constructs a new {@link IntegerElement}.
65       * 
66       * @param name
67       *            The name for the BSON integer.
68       * @param value
69       *            The BSON integer value.
70       * @throws IllegalArgumentException
71       *             If the {@code name} is <code>null</code>.
72       */
73      public IntegerElement(final String name, final int value) {
74          this(name, value, computeSize(name));
75      }
76  
77      /**
78       * Constructs a new {@link IntegerElement}.
79       * 
80       * @param name
81       *            The name for the BSON integer.
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
87       *            {@link IntegerElement#IntegerElement(String, int)} constructor
88       *            instead.
89       * @throws IllegalArgumentException
90       *             If the {@code name} is <code>null</code>.
91       */
92      public IntegerElement(final String name, final int value, final long size) {
93          super(name, size);
94  
95          myValue = value;
96      }
97  
98      /**
99       * Accepts the visitor and calls the {@link Visitor#visitInteger} method.
100      * 
101      * @see Element#accept(Visitor)
102      */
103     @Override
104     public void accept(final Visitor visitor) {
105         visitor.visitInteger(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             final ElementType otherType = other.getType();
128 
129             // Integer is the lowest resolution.
130             result = compare(getIntValue(), other.getIntValue());
131             if (otherType == ElementType.INTEGER) {
132                 result = compare(getIntValue(), other.getIntValue());
133             }
134             else if (otherType == ElementType.LONG) {
135                 result = compare(getLongValue(), other.getLongValue());
136             }
137             else {
138                 result = Double.compare(getDoubleValue(),
139                         other.getDoubleValue());
140 
141             }
142         }
143 
144         return result;
145     }
146 
147     /**
148      * Determines if the passed object is of this same type as this object and
149      * if so that its fields are equal.
150      * 
151      * @param object
152      *            The object to compare to.
153      * 
154      * @see java.lang.Object#equals(java.lang.Object)
155      */
156     @Override
157     public boolean equals(final Object object) {
158         boolean result = false;
159         if (this == object) {
160             result = true;
161         }
162         else if ((object != null) && (getClass() == object.getClass())) {
163             final IntegerElement other = (IntegerElement) object;
164 
165             result = super.equals(object) && (myValue == other.myValue);
166         }
167         return result;
168     }
169 
170     /**
171      * {@inheritDoc}
172      * <p>
173      * Overridden to return the integer value as a double.
174      * </p>
175      */
176     @Override
177     public double getDoubleValue() {
178         return myValue;
179     }
180 
181     /**
182      * {@inheritDoc}
183      * <p>
184      * Overridden to return the integer value.
185      * </p>
186      */
187     @Override
188     public int getIntValue() {
189         return myValue;
190     }
191 
192     /**
193      * {@inheritDoc}
194      * <p>
195      * Overridden to return the integer value as a long.
196      * </p>
197      */
198     @Override
199     public long getLongValue() {
200         return myValue;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
207     public ElementType getType() {
208         return TYPE;
209     }
210 
211     /**
212      * Returns the BSON integer value.
213      * 
214      * @return The BSON integer value.
215      */
216     public int getValue() {
217         return myValue;
218     }
219 
220     /**
221      * {@inheritDoc}
222      * <p>
223      * Returns a {@link Integer} with the value.
224      * </p>
225      */
226     @Override
227     public Integer getValueAsObject() {
228         return Integer.valueOf(myValue);
229     }
230 
231     /**
232      * {@inheritDoc}
233      * <p>
234      * Returns the result of {@link Integer#toString(int)}.
235      * </p>
236      */
237     @Override
238     public String getValueAsString() {
239         return Integer.toString(myValue);
240     }
241 
242     /**
243      * Computes a reasonable hash code.
244      * 
245      * @return The hash code value.
246      */
247     @Override
248     public int hashCode() {
249         int result = 1;
250         result = (31 * result) + super.hashCode();
251         result = (31 * result) + myValue;
252         return result;
253     }
254 
255     /**
256      * {@inheritDoc}
257      * <p>
258      * Returns a new {@link IntegerElement}.
259      * </p>
260      */
261     @Override
262     public IntegerElement withName(final String name) {
263         if (getName().equals(name)) {
264             return this;
265         }
266         return new IntegerElement(name, myValue);
267     }
268 }