DATAMONGO-863 - UpdateMapper doesn't convert raw DBObjects anymore.

UpdateMapper now only performs simple conversion if it encounters a DBObject, instead of deep inspection on keywords used. This allows to use custom clauses nested in Update for operations not directly supported.

Original Pull Request: #138.
This commit is contained in:
Christoph Strobl
2014-03-03 21:29:10 +01:00
committed by Oliver Gierke
parent c66b9a538c
commit 84040518cf
3 changed files with 66 additions and 7 deletions

View File

@@ -138,7 +138,7 @@ public class QueryMapper {
value = getMappedValue(field, rawValue);
}
return Collections.singletonMap(key, value).entrySet().iterator().next();
return createMapEntry(key, value);
}
/**
@@ -168,7 +168,7 @@ public class QueryMapper {
BasicDBList newConditions = new BasicDBList();
for (Object condition : conditions) {
newConditions.add(condition instanceof DBObject ? getMappedObject((DBObject) condition, entity)
newConditions.add(isDBObject(condition) ? getMappedObject((DBObject) condition, entity)
: convertSimpleOrDBObject(condition, entity));
}
@@ -209,7 +209,7 @@ public class QueryMapper {
if (documentField.isIdField()) {
if (value instanceof DBObject) {
if (isDBObject(value)) {
DBObject valueDbo = (DBObject) value;
DBObject resultDbo = new BasicDBObject(valueDbo.toMap());
@@ -267,13 +267,13 @@ public class QueryMapper {
* @param entity
* @return
*/
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
protected Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
if (source instanceof BasicDBList) {
return delegateConvertToMongoType(source, entity);
}
if (source instanceof DBObject) {
if (isDBObject(source)) {
return getMappedObject((DBObject) source, entity);
}
@@ -329,6 +329,40 @@ public class QueryMapper {
return createDbRefFor(source, property);
}
/**
* Checks whether the given value is a {@link DBObject}.
*
* @param value can be {@literal null}.
* @return
*/
protected final boolean isDBObject(Object value) {
return value instanceof DBObject;
}
/**
* Creates a new {@link Entry} for the given {@link Field} with the given value.
*
* @param field must not be {@literal null}.
* @param value can be {@literal null}.
* @return
*/
protected final Entry<String, Object> createMapEntry(Field field, Object value) {
return createMapEntry(field.getMappedKey(), value);
}
/**
* Creates a new {@link Entry} with the given key and value.
*
* @param key must not be {@literal null} or empty.
* @param value can be {@literal null}
* @return
*/
private Entry<String, Object> createMapEntry(String key, Object value) {
Assert.hasText(key, "Key must not be null or empty!");
return Collections.singletonMap(key, value).entrySet().iterator().next();
}
private DBRef createDbRefFor(Object source, MongoPersistentProperty property) {
if (source instanceof DBRef) {

View File

@@ -16,7 +16,6 @@
package org.springframework.data.mongodb.core.convert;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
@@ -76,6 +75,10 @@ public class UpdateMapper extends QueryMapper {
@Override
protected Entry<String, Object> getMappedObjectForField(Field field, Object rawValue) {
if (isDBObject(rawValue)) {
return createMapEntry(field, convertSimpleOrDBObject(rawValue, field.getPropertyEntity()));
}
if (!isUpdateModifier(rawValue)) {
return super.getMappedObjectForField(field, getMappedValue(field, rawValue));
}
@@ -100,7 +103,7 @@ public class UpdateMapper extends QueryMapper {
throw new IllegalArgumentException(String.format("Unable to map value of type '%s'!", rawValue.getClass()));
}
return Collections.singletonMap(field.getMappedKey(), value).entrySet().iterator().next();
return createMapEntry(field, value);
}
/*

View File

@@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.List;
import org.hamcrest.Matcher;
import org.hamcrest.collection.IsIterableContainingInOrder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -390,6 +391,27 @@ public class UpdateMapperUnitTests {
assertThat(setClause.containsField("listOfInterface.$.value"), is(true));
}
/**
* @see DATAMONGO-863
*/
@Test
public void doesNotConvertRawDbObjects() {
Update update = new Update();
update.pull("options",
new BasicDBObject("_id", new BasicDBObject("$in", converter.convertToMongoType(Arrays.asList(1L, 2L)))));
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(ParentClass.class));
DBObject setClause = getAsDBObject(mappedObject, "$pull");
DBObject options = getAsDBObject(setClause, "options");
DBObject idClause = getAsDBObject(options, "_id");
BasicDBList inClause = getAsDBList(idClause, "$in");
assertThat(inClause, IsIterableContainingInOrder.<Object> contains(1L, 2L));
}
static interface Model {}
static class ModelImpl implements Model {