24
24
import org .bson .types .BasicBSONList ;
25
25
import org .bson .types .ObjectId ;
26
26
27
+ import java .util .ArrayList ;
27
28
import java .util .Arrays ;
28
29
import java .util .Date ;
29
30
import java .util .LinkedHashMap ;
31
+ import java .util .List ;
30
32
import java .util .Map ;
31
33
import java .util .Set ;
32
34
import java .util .TreeSet ;
@@ -339,12 +341,12 @@ public boolean equals( Object o ) {
339
341
return false ;
340
342
}
341
343
342
- return Arrays .equals (canonicalize (this ).encode (), canonicalize (other ).encode ());
344
+ return Arrays .equals (canonicalizeBSONObject (this ).encode (), canonicalizeBSONObject (other ).encode ());
343
345
}
344
346
345
347
@ Override
346
348
public int hashCode () {
347
- return Arrays .hashCode (canonicalize (this ).encode ());
349
+ return Arrays .hashCode (canonicalizeBSONObject (this ).encode ());
348
350
}
349
351
350
352
private byte [] encode () {
@@ -356,15 +358,43 @@ private BSONObject decode(final byte[] encodedBytes) {
356
358
}
357
359
358
360
// create a copy of "from", but with keys ordered alphabetically
359
- private static BasicBSONObject canonicalize (final BSONObject from ) {
361
+ @ SuppressWarnings ("unchecked" )
362
+ private static Object canonicalize (final Object from ) {
363
+ if (from instanceof BSONObject && !(from instanceof BasicBSONList )) {
364
+ return canonicalizeBSONObject ((BSONObject ) from );
365
+ } else if (from instanceof List ) {
366
+ return canonicalizeList ((List <Object >) from );
367
+ } else if (from instanceof Map ) {
368
+ return canonicalizeMap ((Map <String , Object >) from );
369
+ } else {
370
+ return from ;
371
+ }
372
+ }
373
+
374
+ private static Map <String , Object > canonicalizeMap (final Map <String , Object > from ) {
375
+ Map <String , Object > canonicalized = new LinkedHashMap <String , Object >(from .size ());
376
+ TreeSet <String > keysInOrder = new TreeSet <String >(from .keySet ());
377
+ for (String key : keysInOrder ) {
378
+ Object val = from .get (key );
379
+ canonicalized .put (key , canonicalize (val ));
380
+ }
381
+ return canonicalized ;
382
+ }
383
+
384
+ private static BasicBSONObject canonicalizeBSONObject (final BSONObject from ) {
360
385
BasicBSONObject canonicalized = new BasicBSONObject ();
361
386
TreeSet <String > keysInOrder = new TreeSet <String >(from .keySet ());
362
387
for (String key : keysInOrder ) {
363
388
Object val = from .get (key );
364
- if (val instanceof BSONObject && ! (val instanceof BasicBSONList )) {
365
- val = canonicalize ((BSONObject ) val );
366
- }
367
- canonicalized .put (key , val );
389
+ canonicalized .put (key , canonicalize (val ));
390
+ }
391
+ return canonicalized ;
392
+ }
393
+
394
+ private static List canonicalizeList (final List <Object > list ) {
395
+ List <Object > canonicalized = new ArrayList <Object >(list .size ());
396
+ for (Object cur : list ) {
397
+ canonicalized .add (canonicalize (cur ));
368
398
}
369
399
return canonicalized ;
370
400
}
0 commit comments