1 /*
2 * #%L
3 * ElementType.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;
21
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 /**
27 * Enumeration of the possible BSON types.
28 *
29 * @api.yes This enumeration is part of the driver's API. Public and protected
30 * members will be deprecated for at least 1 non-bugfix release
31 * (version numbers are <major>.<minor>.<bugfix>)
32 * before being removed or modified.
33 * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
34 */
35 public enum ElementType {
36
37 /** The BSON array type. */
38 ARRAY((byte) 0x04),
39
40 /** The BSON binary type. */
41 BINARY((byte) 0x05),
42
43 /** The BSON boolean type. */
44 BOOLEAN((byte) 0x08),
45
46 /**
47 * The BSON DB Pointer type.
48 *
49 * @deprecated See BSON specification.
50 */
51 @Deprecated
52 DB_POINTER((byte) 0x0C),
53
54 /** The BSON document type. */
55 DOCUMENT((byte) 0x03),
56
57 /** The BSON double type. */
58 DOUBLE((byte) 0x01),
59
60 /** The BSON 32-bit singed integer type. */
61 INTEGER((byte) 0x10),
62
63 /** The BSON JavaScript type. */
64 JAVA_SCRIPT((byte) 0x0D),
65
66 /** The BSON JavaScript w/ scope type. */
67 JAVA_SCRIPT_WITH_SCOPE((byte) 0x0F),
68
69 /** The BSON 32-bit singed integer (long) type. */
70 LONG((byte) 0x12),
71
72 /** The BSON MAX key type. */
73 MAX_KEY((byte) 0x7F),
74
75 /** The BSON MIN key type. */
76 MIN_KEY((byte) 0xFF),
77
78 /** The BSON MongoDB Timestamp type. */
79 MONGO_TIMESTAMP((byte) 0x11),
80
81 /** The BSON null type. */
82 NULL((byte) 0x0A),
83
84 /** The BSON ObjectIdElement type. */
85 OBJECT_ID((byte) 0x07),
86
87 /** The BSON regular expression type. */
88 REGEX((byte) 0x0B),
89
90 /** The BSON string type. */
91 STRING((byte) 0x02),
92
93 /** The BSON Symbol type. */
94 SYMBOL((byte) 0x0E),
95
96 /** The BSON UTC Timestamp type. */
97 UTC_TIMESTAMP((byte) 0x09);
98
99 /**
100 * Provides the ordering of the types as applied by MongoDB internally. The
101 * bulk of this ordering was determined from the <a href=
102 * "http://docs.mongodb.org/manual/faq/developers/#what-is-the-compare-order-for-bson-types"
103 * >MongoDB FAQ Entry</a> with non-listed types from the BSON Specification
104 * determine experimentally.
105 *
106 * @see <a
107 * href="http://docs.mongodb.org/manual/faq/developers/#what-is-the-compare-order-for-bson-types">MongoDB
108 * FAQ Entry</a>
109 */
110 private static final Map<ElementType, Integer> ourMongoDbOrdering;
111
112 static {
113 final Map<ElementType, Integer> mongoDbOrdering = new HashMap<ElementType, Integer>(
114 (int) Math.ceil(values().length / 0.75));
115
116 int ordinal = 0;
117
118 mongoDbOrdering.put(ElementType.MIN_KEY, Integer.valueOf(ordinal));
119 ordinal += 1;
120
121 mongoDbOrdering.put(ElementType.NULL, Integer.valueOf(ordinal));
122 ordinal += 1;
123
124 // Note - same value....
125 mongoDbOrdering.put(ElementType.DOUBLE, Integer.valueOf(ordinal));
126 mongoDbOrdering.put(ElementType.INTEGER, Integer.valueOf(ordinal));
127 mongoDbOrdering.put(ElementType.LONG, Integer.valueOf(ordinal));
128 ordinal += 1;
129
130 // Note - same value....
131 mongoDbOrdering.put(ElementType.SYMBOL, Integer.valueOf(ordinal));
132 mongoDbOrdering.put(ElementType.STRING, Integer.valueOf(ordinal));
133 ordinal += 1;
134
135 mongoDbOrdering.put(ElementType.DOCUMENT, Integer.valueOf(ordinal));
136 ordinal += 1;
137 mongoDbOrdering.put(ElementType.ARRAY, Integer.valueOf(ordinal));
138 ordinal += 1;
139 mongoDbOrdering.put(ElementType.BINARY, Integer.valueOf(ordinal));
140 ordinal += 1;
141 mongoDbOrdering.put(ElementType.OBJECT_ID, Integer.valueOf(ordinal));
142 ordinal += 1;
143 mongoDbOrdering.put(ElementType.BOOLEAN, Integer.valueOf(ordinal));
144 ordinal += 1;
145
146 // Note - same value....
147 mongoDbOrdering
148 .put(ElementType.UTC_TIMESTAMP, Integer.valueOf(ordinal));
149 mongoDbOrdering.put(ElementType.MONGO_TIMESTAMP,
150 Integer.valueOf(ordinal));
151 ordinal += 1;
152
153 mongoDbOrdering.put(ElementType.REGEX, Integer.valueOf(ordinal));
154 ordinal += 1;
155 mongoDbOrdering.put(ElementType.DB_POINTER, Integer.valueOf(ordinal));
156 ordinal += 1;
157 mongoDbOrdering.put(ElementType.JAVA_SCRIPT, Integer.valueOf(ordinal));
158 ordinal += 1;
159 mongoDbOrdering.put(ElementType.JAVA_SCRIPT_WITH_SCOPE,
160 Integer.valueOf(ordinal));
161 ordinal += 1;
162
163 mongoDbOrdering.put(ElementType.MAX_KEY, Integer.valueOf(ordinal));
164 ordinal += 1;
165
166 ourMongoDbOrdering = Collections.unmodifiableMap(mongoDbOrdering);
167 }
168
169 /**
170 * Returns the ElementType with the provided token or <code>null</code> if
171 * it is not found.
172 *
173 * @param token
174 * The BSON type token to find the ElementType for.
175 * @return The ElementType with the provided token or <code>null</code> if
176 * it is not found.
177 */
178 public static ElementType valueOf(final byte token) {
179 switch (token) {
180 case 0x01: {
181 return DOUBLE;
182 }
183 case 0x02: {
184 return STRING;
185 }
186 case 0x03: {
187 return DOCUMENT;
188 }
189 case 0x04: {
190 return ARRAY;
191 }
192 case 0x05: {
193 return BINARY;
194 }
195 // 0x06 not used.
196 case 0x07: {
197 return OBJECT_ID;
198 }
199 case 0x08: {
200 return BOOLEAN;
201 }
202 case 0x09: {
203 return UTC_TIMESTAMP;
204 }
205 case 0x0A: {
206 return NULL;
207 }
208 case 0x0B: {
209 return REGEX;
210 }
211 case 0x0C: {
212 return DB_POINTER;
213 }
214 case 0x0D: {
215 return JAVA_SCRIPT;
216 }
217 case 0x0E: {
218 return SYMBOL;
219 }
220 case 0x0F: {
221 return JAVA_SCRIPT_WITH_SCOPE;
222 }
223 case 0x10: {
224 return INTEGER;
225 }
226 case 0x11: {
227 return MONGO_TIMESTAMP;
228 }
229 case 0x12: {
230 return LONG;
231 }
232 case 0x7F: {
233 return MAX_KEY;
234 }
235 case (byte) 0xFF: {
236 return MIN_KEY;
237 }
238 default: {
239 for (final ElementType type : values()) {
240 if (token == type.getToken()) {
241 return type;
242 }
243 }
244
245 return null;
246 }
247 }
248 }
249
250 /** The token for the BSON type. */
251 private final byte myToken;
252
253 /**
254 * Create a new {@link ElementType}.
255 *
256 * @param token
257 * The token for the {@link ElementType}.
258 */
259 private ElementType(final byte token) {
260 myToken = token;
261 }
262
263 /**
264 * Similar to {@link #compareTo} but instead of comparing on the ordinal
265 * value compares the values based on the MongoDB sort order.
266 *
267 * @param rhs
268 * The right-hand-side of the ordering.
269 * @return A negative value if this {@link ElementType} is less than the
270 * {@code rhs}, zero if they are equal, and a positive value if it
271 * is greater than the {@code rhs}.
272 */
273 public int compare(final ElementType rhs) {
274
275 final int lhsValue = ourMongoDbOrdering.get(this).intValue();
276 final int rhsValue = ourMongoDbOrdering.get(rhs).intValue();
277
278 return lhsValue - rhsValue;
279 }
280
281 /**
282 * Returns the token for the BSON type.
283 *
284 * @return The token for the BSON type.
285 */
286 public byte getToken() {
287 return myToken;
288 }
289
290 }