Browse Source

DATAMONGO-812 - Add support for $push $each since $pushAll is deprecated.

$pushAll has been deprecated in MongoDB 2.4. Instead of calling pushAll one can use push in combination with each. The abstraction for pushAll will remain in code for now but may be removed in a subsequent version.

Original pull request: #112.
pull/122/merge
Christoph Strobl 12 years ago committed by Oliver Gierke
parent
commit
49eee40f7e
  1. 15
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  2. 33
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java
  3. 42
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java
  4. 149
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java
  5. 2
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DBObjectTestUtils.java
  6. 55
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
  7. 62
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java
  8. 107
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

15
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

@ -56,6 +56,7 @@ import org.springframework.data.util.ClassTypeInformation; @@ -56,6 +56,7 @@ import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import com.mongodb.BasicDBList;
@ -71,6 +72,7 @@ import com.mongodb.DBRef; @@ -71,6 +72,7 @@ import com.mongodb.DBRef;
* @author Jon Brisbin
* @author Patrik Wasik
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
@ -942,13 +944,24 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -942,13 +944,24 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
public BasicDBList maybeConvertList(Iterable<?> source) {
BasicDBList newDbl = new BasicDBList();
for (Object element : source) {
newDbl.add(convertToMongoType(element));
Object convertedTypeDdo = convertToMongoType(element);
if (!isSimpleOrCollectionType(element.getClass())) {
this.getTypeMapper().writeType(element.getClass(), (DBObject) convertedTypeDdo);
}
newDbl.add(convertedTypeDdo);
}
return newDbl;
}
private boolean isSimpleOrCollectionType(Class<?> type) {
return this.conversions.isSimpleType(type) || type.getClass().isArray()
|| ClassUtils.isAssignable(Collection.class, type);
}
/**
* Removes the type information from the conversion result.
*

33
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

@ -47,6 +47,7 @@ import com.mongodb.DBRef; @@ -47,6 +47,7 @@ import com.mongodb.DBRef;
* @author Oliver Gierke
* @author Patryk Wasik
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class QueryMapper {
@ -109,17 +110,29 @@ public class QueryMapper { @@ -109,17 +110,29 @@ public class QueryMapper {
Object rawValue = query.get(key);
String newKey = field.getMappedKey();
if (isNestedKeyword(rawValue) && !field.isIdField()) {
Keyword keyword = new Keyword((DBObject) rawValue);
result.put(newKey, getMappedKeyword(field, keyword));
} else {
result.put(newKey, getMappedValue(field, rawValue));
}
result.put(newKey, getMappedObjectForField(field, rawValue));
}
return result;
}
/**
* Extracts the mapped object value for given field out of rawValue taking nested {@link Keyword}s into account
*
* @param field
* @param rawValue
* @return
*/
protected Object getMappedObjectForField(Field field, Object rawValue) {
if (isNestedKeyword(rawValue) && !field.isIdField()) {
Keyword keyword = new Keyword((DBObject) rawValue);
return getMappedKeyword(field, keyword);
}
return getMappedValue(field, rawValue);
}
/**
* @param entity
* @param key
@ -138,7 +151,7 @@ public class QueryMapper { @@ -138,7 +151,7 @@ public class QueryMapper {
* @param entity
* @return
*/
private DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
// $or/$nor
if (keyword.isOrOrNor() || keyword.hasIterableValue()) {
@ -164,7 +177,7 @@ public class QueryMapper { @@ -164,7 +177,7 @@ public class QueryMapper {
* @param keyword
* @return
*/
private DBObject getMappedKeyword(Field property, Keyword keyword) {
protected DBObject getMappedKeyword(Field property, Keyword keyword) {
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
Object value = keyword.getValue();
@ -184,7 +197,7 @@ public class QueryMapper { @@ -184,7 +197,7 @@ public class QueryMapper {
* @param newKey the key the value will be bound to eventually
* @return
*/
private Object getMappedValue(Field documentField, Object value) {
protected Object getMappedValue(Field documentField, Object value) {
if (documentField.isIdField()) {
@ -360,7 +373,7 @@ public class QueryMapper { @@ -360,7 +373,7 @@ public class QueryMapper {
*
* @author Oliver Gierke
*/
private static class Keyword {
static class Keyword {
private static final String N_OR_PATTERN = "\\$.*or";

42
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/UpdateMapper.java

@ -23,17 +23,23 @@ import org.springframework.data.mapping.context.MappingContext; @@ -23,17 +23,23 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty.PropertyToFieldNameConverter;
import org.springframework.data.mongodb.core.query.Update.Modifier;
import org.springframework.data.mongodb.core.query.Update.Modifiers;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* A subclass of {@link QueryMapper} that retains type information on the mongo types.
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class UpdateMapper extends QueryMapper {
private final MongoWriter<?> converter;
private final MongoConverter converter;
/**
* Creates a new {@link UpdateMapper} using the given {@link MongoConverter}.
@ -59,6 +65,40 @@ public class UpdateMapper extends QueryMapper { @@ -59,6 +65,40 @@ public class UpdateMapper extends QueryMapper {
entity.getTypeInformation());
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper#getMappedObjectForField(org.springframework.data.mongodb.core.convert.QueryMapper.Field, java.lang.Object)
*/
@Override
protected Object getMappedObjectForField(Field field, Object rawValue) {
if (!isUpdateModifier(rawValue)) {
return super.getMappedObjectForField(field, rawValue);
}
if (rawValue instanceof Modifier) {
return getMappedValue((Modifier) rawValue);
} else if (rawValue instanceof Modifiers) {
DBObject modificationOperations = new BasicDBObject();
for (Modifier modifier : ((Modifiers) rawValue).getModifiers()) {
modificationOperations.putAll(getMappedValue(modifier).toMap());
}
return modificationOperations;
}
throw new IllegalArgumentException(String.format("Unable to map value of type '%s'!", rawValue.getClass()));
}
private boolean isUpdateModifier(Object value) {
return (value instanceof Modifier || value instanceof Modifiers);
}
private DBObject getMappedValue(Modifier modifier) {
return new BasicDBObject(modifier.getKey(), this.converter.convertToMongoType(modifier.getValue()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.QueryMapper#createPropertyField(org.springframework.data.mongodb.core.mapping.MongoPersistentEntity, java.lang.String, org.springframework.data.mapping.context.MappingContext)

149
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Update.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +16,12 @@ @@ -16,9 +16,12 @@
package org.springframework.data.mongodb.core.query;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@ -32,6 +35,7 @@ import com.mongodb.DBObject; @@ -32,6 +35,7 @@ import com.mongodb.DBObject;
* @author Mark Pollack
* @author Oliver Gierke
* @author Becca Gaspard
* @author Christoph Strobl
*/
public class Update {
@ -39,7 +43,8 @@ public class Update { @@ -39,7 +43,8 @@ public class Update {
LAST, FIRST
}
private HashMap<String, Object> modifierOps = new LinkedHashMap<String, Object>();
private Map<String, Object> modifierOps = new LinkedHashMap<String, Object>();
private Map<String, PushOperatorBuilder> pushCommandBuilders = new LinkedHashMap<String, PushOperatorBuilder>(1);
/**
* Static factory method to create an Update using the provided key
@ -139,9 +144,27 @@ public class Update { @@ -139,9 +144,27 @@ public class Update {
}
/**
* Update using the $pushAll update modifier
* Update using {@code $push} modifier. <br/>
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values.
*
* @param key
* @return {@link PushOperatorBuilder} for given key
*/
public PushOperatorBuilder push(String key) {
if (!pushCommandBuilders.containsKey(key)) {
pushCommandBuilders.put(key, new PushOperatorBuilder(key));
}
return pushCommandBuilders.get(key);
}
/**
* Update using the {@code $pushAll} update modifier. <br>
* <b>Note</b>: In mongodb 2.4 the usage of {@code $pushAll} has been deprecated in favor of {@code $push $each}.
* {@link #push(String)}) returns a builder that can be used to populate the {@code $each} object.
*
* @see http://docs.mongodb.org/manual/reference/operator/update/pushAll/
* @param key
* @param values
* @return
*/
@ -249,4 +272,124 @@ public class Update { @@ -249,4 +272,124 @@ public class Update {
keyValueMap.put(key, value);
}
/**
* Modifiers holds a distinct collection of {@link Modifier}
*
* @author Christoph Strobl
*/
public static class Modifiers {
private HashMap<String, Modifier> modifiers;
public Modifiers() {
this.modifiers = new LinkedHashMap<String, Modifier>(1);
}
public Collection<Modifier> getModifiers() {
return Collections.unmodifiableCollection(this.modifiers.values());
}
public void addModifier(Modifier modifier) {
this.modifiers.put(modifier.getKey(), modifier);
}
}
/**
* Marker interface of nested commands.
*
* @author Christoph Strobl
*/
public static interface Modifier {
/**
* @return the command to send eg. {@code $push}
*/
String getKey();
/**
* @return value to be sent with command
*/
Object getValue();
}
/**
* Implementation of {@link Modifier} representing {@code $each}.
*
* @author Christoph Strobl
*/
private static class Each implements Modifier {
private Object[] values;
public Each(Object... values) {
this.values = extractValues(values);
}
private Object[] extractValues(Object[] values) {
if (values == null || values.length == 0) {
return values;
}
if (values.length == 1 && values[0] instanceof Collection) {
return ((Collection<?>) values[0]).toArray();
}
Object[] convertedValues = new Object[values.length];
for (int i = 0; i < values.length; i++) {
convertedValues[i] = values[i];
}
return convertedValues;
}
@Override
public String getKey() {
return "$each";
}
@Override
public Object getValue() {
return this.values;
}
}
/**
* Builder for creating {@code $push} modifiers
*
* @author Christop Strobl
*/
public class PushOperatorBuilder {
private final String key;
private final Modifiers modifiers;
PushOperatorBuilder(String key) {
this.key = key;
this.modifiers = new Modifiers();
}
/**
* Propagates {@code $each} to {@code $push}
*
* @param values
* @return
*/
public Update each(Object... values) {
this.modifiers.addModifier(new Each(values));
return Update.this.push(key, this.modifiers);
}
/**
* Propagates {@link #value(Object)} to {@code $push}
*
* @param values
* @return
*/
public Update value(Object value) {
return Update.this.push(key, value);
}
}
}

2
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DBObjectTestUtils.java

@ -70,7 +70,7 @@ public abstract class DBObjectTestUtils { @@ -70,7 +70,7 @@ public abstract class DBObjectTestUtils {
}
@SuppressWarnings("unchecked")
private static <T> T getTypedValue(DBObject source, String key, Class<T> type) {
public static <T> T getTypedValue(DBObject source, String key, Class<T> type) {
Object value = source.get(key);
assertThat(value, is(notNullValue()));

55
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core; @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
@ -35,7 +36,6 @@ import org.bson.types.ObjectId; @@ -35,7 +36,6 @@ import org.bson.types.ObjectId;
import org.hamcrest.CoreMatchers;
import org.joda.time.DateTime;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -168,6 +168,7 @@ public class MongoTemplateTests { @@ -168,6 +168,7 @@ public class MongoTemplateTests {
template.dropCollection(BaseDoc.class);
template.dropCollection(ObjectWithEnumValue.class);
template.dropCollection(DocumentWithCollection.class);
template.dropCollection(DocumentWithCollectionOfSimpleType.class);
}
@Test
@ -887,7 +888,7 @@ public class MongoTemplateTests { @@ -887,7 +888,7 @@ public class MongoTemplateTests {
l2.add(31);
Query q3 = new Query(Criteria.where("age").in(l1, l2));
template.find(q3, PersonWithIdPropertyOfTypeObjectId.class);
Assert.fail("Should have trown an InvalidDocumentStoreApiUsageException");
fail("Should have trown an InvalidDocumentStoreApiUsageException");
} catch (InvalidMongoDbApiUsageException e) {}
}
@ -2202,8 +2203,8 @@ public class MongoTemplateTests { @@ -2202,8 +2203,8 @@ public class MongoTemplateTests {
template.findAndModify(query, update, Document.class);
Document retrieved = template.findOne(query, Document.class);
Assert.assertThat(retrieved.model, instanceOf(ModelA.class));
Assert.assertThat(retrieved.model.value(), equalTo("value2"));
assertThat(retrieved.model, instanceOf(ModelA.class));
assertThat(retrieved.model.value(), equalTo("value2"));
}
/**
@ -2234,10 +2235,56 @@ public class MongoTemplateTests { @@ -2234,10 +2235,56 @@ public class MongoTemplateTests {
assertThat(result.model.get(0).value(), is(newModelValue));
}
/**
* @see DATAMONGO-812
*/
@Test
public void updateMultiShouldAddValuesCorrectlyWhenUsingPushEachWithComplexTypes() {
DocumentWithCollection document = new DocumentWithCollection(new ModelA("model-a"));
template.save(document);
Query query = query(where("id").is(document.id));
assumeThat(template.findOne(query, DocumentWithCollection.class).model, hasSize(1));
Update update = new Update().push("model").each(new ModelA("model-b"), new ModelA("model-c"));
template.updateMulti(query, update, DocumentWithCollection.class);
assertThat(template.findOne(query, DocumentWithCollection.class).model, hasSize(3));
}
/**
* @see DATAMONGO-812
*/
@Test
public void updateMultiShouldAddValuesCorrectlyWhenUsingPushEachWithSimpleTypes() {
DocumentWithCollectionOfSimpleType document = new DocumentWithCollectionOfSimpleType();
document.values = Arrays.asList("spring");
template.save(document);
Query query = query(where("id").is(document.id));
assumeThat(template.findOne(query, DocumentWithCollectionOfSimpleType.class).values, hasSize(1));
Update update = new Update().push("values").each("data", "mongodb");
template.updateMulti(query, update, DocumentWithCollectionOfSimpleType.class);
assertThat(template.findOne(query, DocumentWithCollectionOfSimpleType.class).values, hasSize(3));
}
static class DocumentWithCollection {
@Id public String id;
public List<Model> model;
DocumentWithCollection(Model... models) {
this.model = Arrays.asList(models);
}
}
static class DocumentWithCollectionOfSimpleType {
@Id String id;
List<String> values;
}
static interface Model {

62
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert; @@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.DBObjectTestUtils.*;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -72,6 +73,7 @@ import com.mongodb.util.JSON; @@ -72,6 +73,7 @@ import com.mongodb.util.JSON;
*
* @author Oliver Gierke
* @author Patrik Wasik
* @author Christoph Strobl
*/
@RunWith(MockitoJUnitRunner.class)
public class MappingMongoConverterUnitTests {
@ -1026,7 +1028,7 @@ public class MappingMongoConverterUnitTests { @@ -1026,7 +1028,7 @@ public class MappingMongoConverterUnitTests {
Set<?> readResult = converter.read(Set.class, (BasicDBList) result);
assertThat(readResult.size(), is(1));
assertThat(readResult.iterator().next(), is(instanceOf(Map.class)));
assertThat(readResult.iterator().next(), is(instanceOf(Address.class)));
}
/**
@ -1381,6 +1383,62 @@ public class MappingMongoConverterUnitTests { @@ -1381,6 +1383,62 @@ public class MappingMongoConverterUnitTests {
assertThat(aValue.get("c"), is((Object) "C"));
}
@Test
public void convertsListToBasicDBListAndRetainsTypeInformationForComplexObjects() {
Address address = new Address();
address.city = "London";
address.street = "Foo";
Object result = converter.convertToMongoType(Collections.singletonList(address));
assertThat(result, is(instanceOf(BasicDBList.class)));
BasicDBList dbList = (BasicDBList) result;
assertThat(dbList, hasSize(1));
assertThat(getTypedValue(getAsDBObject(dbList, 0), ("_class"), String.class), equalTo(Address.class.getName()));
}
@Test
public void convertsListToBasicDBListWithoutTypeInformationForSimpleTypes() {
Object result = converter.convertToMongoType(Collections.singletonList("foo"));
assertThat(result, is(instanceOf(BasicDBList.class)));
BasicDBList dbList = (BasicDBList) result;
assertThat(dbList, hasSize(1));
assertThat(dbList.get(0), instanceOf(String.class));
}
@Test
public void convertsArrayToBasicDBListAndRetainsTypeInformationForComplexObjects() {
Address address = new Address();
address.city = "London";
address.street = "Foo";
Object result = converter.convertToMongoType(new Address[] { address });
assertThat(result, is(instanceOf(BasicDBList.class)));
BasicDBList dbList = (BasicDBList) result;
assertThat(dbList, hasSize(1));
assertThat(getTypedValue(getAsDBObject(dbList, 0), ("_class"), String.class), equalTo(Address.class.getName()));
}
@Test
public void convertsArrayToBasicDBListWithoutTypeInformationForSimpleTypes() {
Object result = converter.convertToMongoType(new String[] { "foo" });
assertThat(result, is(instanceOf(BasicDBList.class)));
BasicDBList dbList = (BasicDBList) result;
assertThat(dbList, hasSize(1));
assertThat(dbList.get(0), instanceOf(String.class));
}
static class GenericType<T> {
T content;
}

107
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java

@ -16,11 +16,14 @@ @@ -16,11 +16,14 @@
package org.springframework.data.mongodb.core.convert;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.collection.IsMapContaining.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.DBObjectTestUtils.*;
import java.util.Arrays;
import java.util.List;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -31,6 +34,7 @@ import org.springframework.data.mongodb.core.mapping.Field; @@ -31,6 +34,7 @@ import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.Update;
import com.mongodb.BasicDBList;
import com.mongodb.DBObject;
/**
@ -38,6 +42,7 @@ import com.mongodb.DBObject; @@ -38,6 +42,7 @@ import com.mongodb.DBObject;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Thomas Darimont
*/
@RunWith(MockitoJUnitRunner.class)
public class UpdateMapperUnitTests {
@ -45,12 +50,14 @@ public class UpdateMapperUnitTests { @@ -45,12 +50,14 @@ public class UpdateMapperUnitTests {
@Mock MongoDbFactory factory;
MappingMongoConverter converter;
MongoMappingContext context;
UpdateMapper mapper;
@Before
public void setUp() {
this.context = new MongoMappingContext();
this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context);
this.mapper = new UpdateMapper(converter);
}
/**
@ -60,7 +67,6 @@ public class UpdateMapperUnitTests { @@ -60,7 +67,6 @@ public class UpdateMapperUnitTests {
public void updateMapperRetainsTypeInformationForCollectionField() {
Update update = new Update().push("list", new ConcreteChildClass("2", "BAR"));
UpdateMapper mapper = new UpdateMapper(converter);
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(ParentClass.class));
@ -175,6 +181,91 @@ public class UpdateMapperUnitTests { @@ -175,6 +181,91 @@ public class UpdateMapperUnitTests {
assertThat(someObject.get("value"), is((Object) "bubu"));
}
/**
* @see DATAMONGO-812
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingSimpleTypes() {
Update update = new Update().push("values").each("spring", "data", "mongodb");
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Model.class));
DBObject push = getAsDBObject(mappedObject, "$push");
DBObject values = getAsDBObject(push, "values");
BasicDBList each = getAsDBList(values, "$each");
assertThat(push.get("_class"), nullValue());
assertThat(values.get("_class"), nullValue());
assertThat(each.toMap(), (Matcher) allOf(hasValue("spring"), hasValue("data"), hasValue("mongodb")));
}
/**
* @see DATAMONGO-812
*/
@Test
public void updateMapperShouldConvertPushWhithoutAddingClassInformationWhenUsedWithEvery() {
Update update = new Update().push("values").each("spring", "data", "mongodb");
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Model.class));
DBObject push = getAsDBObject(mappedObject, "$push");
DBObject values = getAsDBObject(push, "values");
assertThat(push.get("_class"), nullValue());
assertThat(values.get("_class"), nullValue());
}
/**
* @see DATAMONGO-812
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void updateMapperShouldConvertPushCorrectlyWhenCalledWithEachUsingCustomTypes() {
Update update = new Update().push("models").each(new ListModel("spring", "data", "mongodb"));
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(ModelWrapper.class));
DBObject push = getAsDBObject(mappedObject, "$push");
DBObject model = getAsDBObject(push, "models");
BasicDBList each = getAsDBList(model, "$each");
BasicDBList values = getAsDBList((DBObject) each.get(0), "values");
assertThat(values.toMap(), (Matcher) allOf(hasValue("spring"), hasValue("data"), hasValue("mongodb")));
}
/**
* @see DATAMONGO-812
*/
@Test
public void updateMapperShouldRetainClassInformationForPushCorrectlyWhenCalledWithEachUsingCustomTypes() {
Update update = new Update().push("models").each(new ListModel("spring", "data", "mongodb"));
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(),
context.getPersistentEntity(ModelWrapper.class));
DBObject push = getAsDBObject(mappedObject, "$push");
DBObject model = getAsDBObject(push, "models");
BasicDBList each = getAsDBList(model, "$each");
assertThat(((DBObject) each.get(0)).get("_class").toString(), equalTo(ListModel.class.getName()));
}
/**
* @see DATAMONGO-812
*/
@Test
public void testUpdateShouldAllowMultiplePushEachForDifferentFields() {
Update update = new Update().push("category").each("spring", "data").push("type").each("mongodb");
DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));
DBObject push = getAsDBObject(mappedObject, "$push");
assertThat(getAsDBObject(push, "category").containsField("$each"), is(true));
assertThat(getAsDBObject(push, "type").containsField("$each"), is(true));
}
static interface Model {}
static class ModelImpl implements Model {
@ -189,6 +280,20 @@ public class UpdateMapperUnitTests { @@ -189,6 +280,20 @@ public class UpdateMapperUnitTests {
Model model;
}
static class ListModelWrapper {
List<Model> models;
}
static class ListModel {
List<String> values;
public ListModel(String... values) {
this.values = Arrays.asList(values);
}
}
static class ParentClass {
String id;

Loading…
Cancel
Save