1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.allanbank.mongodb.bson.element;
21
22 import static com.allanbank.mongodb.util.Assertions.assertNotNull;
23
24 import java.util.UUID;
25
26 import com.allanbank.mongodb.bson.io.EndianUtils;
27 import com.allanbank.mongodb.util.IOUtils;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class UuidElement extends BinaryElement {
48
49
50
51
52
53 public static final byte LEGACY_UUID_SUBTTYPE = 3;
54
55
56 public static final int UUID_BINARY_LENGTH = 16;
57
58
59 public static final byte UUID_SUBTTYPE = 4;
60
61
62 private static final long serialVersionUID = 6461067538910973839L;
63
64
65
66
67
68
69
70
71
72
73 private static byte[] toBytes(final byte uuidSubttype, final UUID value) {
74 assertNotNull(value,
75 "The UUID value for a UuidElement must not be null.");
76
77 long high = value.getMostSignificantBits();
78 long low = value.getLeastSignificantBits();
79
80 if (uuidSubttype == LEGACY_UUID_SUBTTYPE) {
81 high = EndianUtils.swap(high);
82 low = EndianUtils.swap(low);
83 }
84
85 final byte[] result = new byte[16];
86
87 result[0] = (byte) ((high >> 56) & 0xFF);
88 result[1] = (byte) ((high >> 48) & 0xFF);
89 result[2] = (byte) ((high >> 40) & 0xFF);
90 result[3] = (byte) ((high >> 32) & 0xFF);
91 result[4] = (byte) ((high >> 24) & 0xFF);
92 result[5] = (byte) ((high >> 16) & 0xFF);
93 result[6] = (byte) ((high >> 8) & 0xFF);
94 result[7] = (byte) (high & 0xFF);
95 result[8] = (byte) ((low >> 56) & 0xFF);
96 result[9] = (byte) ((low >> 48) & 0xFF);
97 result[10] = (byte) ((low >> 40) & 0xFF);
98 result[11] = (byte) ((low >> 32) & 0xFF);
99 result[12] = (byte) ((low >> 24) & 0xFF);
100 result[13] = (byte) ((low >> 16) & 0xFF);
101 result[14] = (byte) ((low >> 8) & 0xFF);
102 result[15] = (byte) (low & 0xFF);
103
104 return result;
105 }
106
107
108 private final UUID myUuid;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public UuidElement(final String name, final byte subType, final byte[] value) {
126 super(name, subType, value);
127
128 myUuid = toUuid(subType, value);
129 }
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 public UuidElement(final String name, final byte subType,
152 final byte[] value, final long size) {
153 super(name, subType, value, size);
154
155 myUuid = toUuid(subType, value);
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public UuidElement(final String name, final byte subType, final UUID value) {
171 super(name, subType, toBytes(subType, value));
172
173 myUuid = value;
174 }
175
176
177
178
179
180
181
182
183
184
185
186 public UuidElement(final String name, final UUID value) {
187 super(name, UUID_SUBTTYPE, toBytes(UUID_SUBTTYPE, value));
188
189 myUuid = value;
190 }
191
192
193
194
195
196
197
198
199
200
201 @Override
202 public boolean equals(final Object object) {
203 boolean result = false;
204 if (this == object) {
205 result = true;
206 }
207 else if ((object != null) && (getClass() == object.getClass())) {
208 final UuidElement other = (UuidElement) object;
209
210 result = super.equals(object) && myUuid.equals(other.myUuid);
211 }
212 return result;
213 }
214
215
216
217
218
219
220 public UUID getUuid() {
221 return myUuid;
222 }
223
224
225
226
227
228
229
230
231
232
233
234 @Override
235 public UUID getValueAsObject() {
236 return myUuid;
237 }
238
239
240
241
242
243
244
245 @Override
246 public String getValueAsString() {
247 return myUuid.toString();
248 }
249
250
251
252
253
254
255 @Override
256 public int hashCode() {
257 int result = 1;
258 result = (31 * result) + super.hashCode();
259 result = (31 * result) + myUuid.hashCode();
260 return result;
261 }
262
263
264
265
266
267
268
269 @Override
270 public UuidElement withName(final String name) {
271 if (getName().equals(name)) {
272 return this;
273 }
274 return new UuidElement(name, getSubType(), myUuid);
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289 private UUID toUuid(final byte subType, final byte[] value)
290 throws IllegalArgumentException {
291
292 if (value.length == UUID_BINARY_LENGTH) {
293 long high = 0;
294 long low = 0;
295
296 for (int i = 0; i < 8; ++i) {
297 high <<= Byte.SIZE;
298 high += (value[i] & 0xFF);
299 }
300 for (int i = 8; i < 16; ++i) {
301 low <<= Byte.SIZE;
302 low += (value[i] & 0xFF);
303 }
304
305 if (subType == LEGACY_UUID_SUBTTYPE) {
306 high = EndianUtils.swap(high);
307 low = EndianUtils.swap(low);
308 }
309 return new UUID(high, low);
310 }
311
312 throw new IllegalArgumentException(
313 "The value for a UUID must be 16 bytes long: "
314 + IOUtils.toHex(value));
315 }
316 }