Skip to content

Instantly share code, notes, and snippets.

@jamel
Created March 11, 2016 12:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamel/892f871c35a8a2e3bda9 to your computer and use it in GitHub Desktop.
Save jamel/892f871c35a8a2e3bda9 to your computer and use it in GitHub Desktop.
fixed BuildersHelper class to support arrays, collections and maps
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bson.BsonDocument;
import org.bson.BsonDocumentWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.Encoder;
import org.bson.codecs.EncoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
/**
* see https://jira.mongodb.org/browse/JAVA-2056
*/
public final class BuildersHelper {
private BuildersHelper() {}
@SuppressWarnings("unchecked")
static <TItem> void encodeValue(final BsonDocumentWriter writer, final TItem value, final CodecRegistry codecRegistry) {
if (value == null) {
writer.writeNull();
} else if (value instanceof Bson) {
((Encoder) codecRegistry.get(BsonDocument.class)).encode(writer,
((Bson) value).toBsonDocument(BsonDocument.class, codecRegistry),
EncoderContext.builder().build());
} else {
Class<?> valueClass = value.getClass();
if (valueClass.isArray()) {
writeArray(writer, (Object[]) value, codecRegistry);
} else if (Collection.class.isAssignableFrom(valueClass)) {
writeCollection(writer, (Collection) value, codecRegistry);
} else if (Map.class.isAssignableFrom(valueClass)) {
writeMap(writer, (Map<Object, Object>) value, codecRegistry);
} else {
Codec codec = codecRegistry.get(valueClass);
codec.encode(writer, value, EncoderContext.builder().build());
}
}
}
@SuppressWarnings("unchecked")
private static void writeArray(BsonDocumentWriter writer, Object[] value, CodecRegistry codecRegistry) {
writer.writeStartArray();
if (value.length > 0) {
Class<?> itemType = value[0].getClass();
Codec codec = codecRegistry.get(itemType);
EncoderContext ctx = EncoderContext.builder().build();
for (Object item : value) {
codec.encode(writer, item, ctx);
}
}
writer.writeEndArray();
}
@SuppressWarnings("unchecked")
private static void writeCollection(BsonDocumentWriter writer, Collection value, CodecRegistry codecRegistry) {
writer.writeStartArray();
if (!value.isEmpty()) {
Class<?> itemType = value.iterator().next().getClass();
Codec codec = codecRegistry.get(itemType);
EncoderContext ctx = EncoderContext.builder().build();
for (Object item : value) {
codec.encode(writer, item, ctx);
}
}
writer.writeEndArray();
}
@SuppressWarnings("unchecked")
private static void writeMap(BsonDocumentWriter writer, Map<Object, Object> value, CodecRegistry codecRegistry) {
writer.writeStartDocument();
if (!value.isEmpty()) {
Set<Entry<Object, Object>> entries = value.entrySet();
Entry<Object, Object> first = entries.iterator().next();
if (first.getKey().getClass() != String.class) {
throw new IllegalStateException("key must be a String");
}
Codec codec = codecRegistry.get(first.getValue().getClass());
EncoderContext ctx = EncoderContext.builder().build();
for (Entry<Object, Object> entry : entries) {
writer.writeName((String) entry.getKey());
codec.encode(writer, entry.getValue(), ctx);
}
}
writer.writeEndDocument();
}
}
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import com.mongodb.async.client.MongoClients;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonInt32;
import org.bson.codecs.configuration.CodecRegistry;
import org.junit.Assert;
import org.junit.Test;
public class UpdatesTest {
private static CodecRegistry codecRegistry = MongoClients.getDefaultCodecRegistry();
@Test
public void arrayValue() {
BsonDocument generated = Updates.set("items", new Integer[]{1, 2, 3})
.toBsonDocument(Object.class, codecRegistry);
BsonDocument expected = new BsonDocument("$set",
new BsonDocument("items", new BsonArray(Arrays.asList(
new BsonInt32(1),
new BsonInt32(2),
new BsonInt32(3)
))));
Assert.assertEquals(expected, generated);
}
@Test
public void collectionValue() {
BsonDocument generated = Updates.set("items", new HashSet<>(Arrays.asList(1, 2, 3, 2, 1)))
.toBsonDocument(Object.class, codecRegistry);
BsonDocument expected = new BsonDocument("$set",
new BsonDocument("items", new BsonArray(Arrays.asList(
new BsonInt32(1),
new BsonInt32(2),
new BsonInt32(3)
))));
Assert.assertEquals(expected, generated);
}
@Test
public void mapValue() {
BsonDocument generated = Updates.set("map",
new HashMap<String, Integer>() {{
put("one", 1);
put("two", 2);
}})
.toBsonDocument(Object.class, codecRegistry);
BsonDocument expected = new BsonDocument("$set",
new BsonDocument("map",
new BsonDocument("one", new BsonInt32(1)).append("two", new BsonInt32(2))
));
Assert.assertEquals(expected, generated);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment