Skip to content

Commit b718ddc

Browse files
committed
JAVA-1192: Handle Map and List in BasicBSONObject.equals and hashCode
1 parent 8f0a10a commit b718ddc

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

src/main/org/bson/BasicBSONObject.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import org.bson.types.BasicBSONList;
2525
import org.bson.types.ObjectId;
2626

27+
import java.util.ArrayList;
2728
import java.util.Arrays;
2829
import java.util.Date;
2930
import java.util.LinkedHashMap;
31+
import java.util.List;
3032
import java.util.Map;
3133
import java.util.Set;
3234
import java.util.TreeSet;
@@ -339,12 +341,12 @@ public boolean equals( Object o ) {
339341
return false;
340342
}
341343

342-
return Arrays.equals(canonicalize(this).encode(), canonicalize(other).encode());
344+
return Arrays.equals(canonicalizeBSONObject(this).encode(), canonicalizeBSONObject(other).encode());
343345
}
344346

345347
@Override
346348
public int hashCode() {
347-
return Arrays.hashCode(canonicalize(this).encode());
349+
return Arrays.hashCode(canonicalizeBSONObject(this).encode());
348350
}
349351

350352
private byte[] encode() {
@@ -356,15 +358,43 @@ private BSONObject decode(final byte[] encodedBytes) {
356358
}
357359

358360
// 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) {
360385
BasicBSONObject canonicalized = new BasicBSONObject();
361386
TreeSet<String> keysInOrder = new TreeSet<String>(from.keySet());
362387
for (String key : keysInOrder) {
363388
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));
368398
}
369399
return canonicalized;
370400
}

src/test/com/mongodb/BasicDBObjectTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import org.junit.Test;
2323

2424
import java.util.Date;
25+
import java.util.HashMap;
26+
import java.util.Map;
27+
import java.util.TreeMap;
2528

2629
import static java.util.Arrays.asList;
2730
import static org.junit.Assert.assertEquals;
@@ -141,6 +144,21 @@ public void testEqualsAndHashCode() {
141144

142145
assertEquality(new BasicDBObject("a", new BasicDBObject("y", 2).append("x", 1)),
143146
new BasicDBObject("a", new BasicDBObject("x", 1).append("y", 2)));
147+
148+
assertEquality(new BasicDBObject("a", asList(new BasicDBObject("y", 2).append("x", 1))),
149+
new BasicDBObject("a", asList(new BasicDBObject("x", 1).append("y", 2))));
150+
151+
assertEquality(new BasicDBObject("a", new BasicDBList().put(1, new BasicDBObject("y", 2).append("x", 1))),
152+
new BasicDBObject("a", new BasicDBList().put(1, new BasicDBObject("x", 1).append("y", 2))));
153+
154+
Map<String, Object> first = new HashMap<String, Object>();
155+
first.put("1", new BasicDBObject("y", 2).append("x", 1));
156+
first.put("2", new BasicDBObject("a", 2).append("b", 1));
157+
Map<String, Object> second = new TreeMap<String, Object>();
158+
second.put("2", new BasicDBObject("b", 1).append("a", 2));
159+
second.put("1", new BasicDBObject("x", 1).append("y", 2));
160+
161+
assertEquality(new BasicDBObject("a", first), new BasicDBObject("a", second));
144162
}
145163

146164
void assertEquality(final BasicBSONObject x, final BasicBSONObject y) {

0 commit comments

Comments
 (0)