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 }