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