DATAMONGO-1176 - Polishing.
- Remove dropDups assertion as the MongoDB 3 driver does no longer provide dropDups even if running agains a MongoDB v2.6.7. - Remove mongo-next build profile as we're based on the Mongo 3 driver now. - Map update object and merge set operations.
This commit is contained in:
committed by
Oliver Gierke
parent
2461575c52
commit
2d3efdc0b4
@@ -9,7 +9,6 @@ before_script:
|
||||
env:
|
||||
matrix:
|
||||
- PROFILE=ci
|
||||
- PROFILE=mongo-next
|
||||
- PROFILE=mongo3
|
||||
- PROFILE=mongo3-next
|
||||
- PROFILE=mongo31
|
||||
|
||||
16
pom.xml
16
pom.xml
@@ -113,22 +113,6 @@
|
||||
</developers>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
|
||||
<id>mongo-next</id>
|
||||
<properties>
|
||||
<mongo>2.15.0-SNAPSHOT</mongo>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mongo-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
|
||||
<id>mongo3</id>
|
||||
|
||||
@@ -128,7 +128,7 @@ import com.mongodb.util.JSONParseException;
|
||||
|
||||
/**
|
||||
* Primary implementation of {@link MongoOperations}.
|
||||
*
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Graeme Rocher
|
||||
* @author Mark Pollack
|
||||
@@ -181,7 +181,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration
|
||||
*
|
||||
*
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
*/
|
||||
@@ -192,7 +192,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Constructor used for a template configuration with user credentials in the form of
|
||||
* {@link org.springframework.data.authentication.UserCredentials}
|
||||
*
|
||||
*
|
||||
* @param mongo must not be {@literal null}.
|
||||
* @param databaseName must not be {@literal null} or empty.
|
||||
* @param userCredentials
|
||||
@@ -203,7 +203,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
*
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
*/
|
||||
public MongoTemplate(MongoDbFactory mongoDbFactory) {
|
||||
@@ -212,7 +212,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Constructor used for a basic template configuration.
|
||||
*
|
||||
*
|
||||
* @param mongoDbFactory must not be {@literal null}.
|
||||
* @param mongoConverter
|
||||
*/
|
||||
@@ -241,7 +241,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Configures the {@link WriteResultChecking} to be used with the template. Setting {@literal null} will reset the
|
||||
* default of {@value #DEFAULT_WRITE_RESULT_CHECKING}.
|
||||
*
|
||||
*
|
||||
* @param resultChecking
|
||||
*/
|
||||
public void setWriteResultChecking(WriteResultChecking resultChecking) {
|
||||
@@ -252,7 +252,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern}
|
||||
* configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no
|
||||
* {@link WriteConcern} will be used.
|
||||
*
|
||||
*
|
||||
* @param writeConcern
|
||||
*/
|
||||
public void setWriteConcern(WriteConcern writeConcern) {
|
||||
@@ -261,7 +261,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Configures the {@link WriteConcernResolver} to be used with the template.
|
||||
*
|
||||
*
|
||||
* @param writeConcernResolver
|
||||
*/
|
||||
public void setWriteConcernResolver(WriteConcernResolver writeConcernResolver) {
|
||||
@@ -271,7 +271,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Used by @{link {@link #prepareCollection(DBCollection)} to set the {@link ReadPreference} before any operations are
|
||||
* performed.
|
||||
*
|
||||
*
|
||||
* @param readPreference
|
||||
*/
|
||||
public void setReadPreference(ReadPreference readPreference) {
|
||||
@@ -298,7 +298,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext}
|
||||
* can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get
|
||||
* created appropriately for entity types persisted through this {@link MongoTemplate} instance.
|
||||
*
|
||||
*
|
||||
* @param context must not be {@literal null}.
|
||||
*/
|
||||
private void prepareIndexCreator(ApplicationContext context) {
|
||||
@@ -319,14 +319,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Returns the default {@link org.springframework.data.mongodb.core.core.convert.MongoConverter}.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MongoConverter getConverter() {
|
||||
return this.mongoConverter;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.MongoOperations#executeAsStream(org.springframework.data.mongodb.core.query.Query, java.lang.Class)
|
||||
*/
|
||||
@@ -437,7 +437,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Execute a MongoDB query and iterate over the query results on a per-document basis with a
|
||||
* {@link DocumentCallbackHandler} using the provided CursorPreparer.
|
||||
*
|
||||
*
|
||||
* @param query the query class that specifies the criteria used to find a record and also an optional fields
|
||||
* specification, must not be {@literal null}.
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
@@ -709,7 +709,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/*
|
||||
* As MongoDB currently (2.4.4) doesn't support the skipping of elements in near queries
|
||||
* we skip the elements ourselves to avoid at least the document 2 object mapping overhead.
|
||||
*
|
||||
*
|
||||
* @see https://jira.mongodb.org/browse/SERVER-3925
|
||||
*/
|
||||
if (index >= elementsToSkip) {
|
||||
@@ -814,7 +814,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Prepare the collection before any processing is done using it. This allows a convenient way to apply settings like
|
||||
* slaveOk() etc. Can be overridden in sub-classes.
|
||||
*
|
||||
*
|
||||
* @param collection
|
||||
*/
|
||||
protected MongoCollection<Document> prepareCollection(MongoCollection<Document> collection) {
|
||||
@@ -830,7 +830,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* settings in sub-classes. <br />
|
||||
* In case of using MongoDB Java driver version 3 the returned {@link WriteConcern} will be defaulted to
|
||||
* {@link WriteConcern#ACKNOWLEDGED} when {@link WriteResultChecking} is set to {@link WriteResultChecking#EXCEPTION}.
|
||||
*
|
||||
*
|
||||
* @param writeConcern any WriteConcern already configured or null
|
||||
* @return The prepared WriteConcern or null
|
||||
*/
|
||||
@@ -1225,19 +1225,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
UpdateOptions opts = new UpdateOptions();
|
||||
opts.upsert(upsert);
|
||||
|
||||
// TODO hack - split up update and replaces
|
||||
boolean useUpdate = false;
|
||||
|
||||
for (String s : updateObj.keySet()) {
|
||||
if (s.startsWith("$")) {
|
||||
useUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection;
|
||||
|
||||
if (!useUpdate) {
|
||||
if (!UpdateMapper.isUpdateObject(updateObj)) {
|
||||
return collection.replaceOne(queryObj, updateObj, opts);
|
||||
} else {
|
||||
if (multi) {
|
||||
@@ -1292,7 +1282,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Returns {@link Entry} containing the field name of the id property as {@link Entry#getKey()} and the {@link Id}s
|
||||
* property value as its {@link Entry#getValue()}.
|
||||
*
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
@@ -1319,7 +1309,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Returns a {@link Query} for the given entity by its id.
|
||||
*
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -1331,7 +1321,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Returns a {@link Query} for the given entities by their ids.
|
||||
*
|
||||
*
|
||||
* @param objects must not be {@literal null} or {@literal empty}.
|
||||
* @return
|
||||
*/
|
||||
@@ -1623,7 +1613,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Retrieve and remove all documents matching the given {@code query} by calling {@link #find(Query, Class, String)}
|
||||
* and {@link #remove(Query, Class, String)}, whereas the {@link Query} for {@link #remove(Query, Class, String)} is
|
||||
* constructed out of the find result.
|
||||
*
|
||||
*
|
||||
* @param collectionName
|
||||
* @param query
|
||||
* @param entityClass
|
||||
@@ -1661,8 +1651,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the potentially mapped results of the given {@commandResult} contained some.
|
||||
*
|
||||
* Returns the potentially mapped results of the given {@code commandResult}.
|
||||
*
|
||||
* @param outputType
|
||||
* @param commandResult
|
||||
* @return
|
||||
@@ -1739,7 +1729,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Create the specified collection using the provided options
|
||||
*
|
||||
*
|
||||
* @param collectionName
|
||||
* @param collectionOptions
|
||||
* @return the collection that was created
|
||||
@@ -1776,7 +1766,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter.
|
||||
* The query document is specified as a standard {@link Document} and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from.
|
||||
* @param query the query document that specifies the criteria used to find a record.
|
||||
* @param fields the document that specifies the fields to be returned.
|
||||
@@ -1801,7 +1791,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List using the template's converter. The
|
||||
* query document is specified as a standard Document and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param fields the document that specifies the fields to be returned
|
||||
@@ -1817,7 +1807,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* Map the results of an ad-hoc query on the default MongoDB collection to a List of the specified type. The object is
|
||||
* converted from the MongoDB native representation using an instance of {@see MongoConverter}. The query document is
|
||||
* specified as a standard Document and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from.
|
||||
* @param query the query document that specifies the criteria used to find a record.
|
||||
* @param fields the document that specifies the fields to be returned.
|
||||
@@ -1870,7 +1860,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* The first document that matches the query is returned and also removed from the collection in the database.
|
||||
* <p/>
|
||||
* The query document is specified as a standard Document and so is the fields specification.
|
||||
*
|
||||
*
|
||||
* @param collectionName name of the collection to retrieve the objects from
|
||||
* @param query the query document that specifies the criteria used to find a record
|
||||
* @param entityClass the parameterized type of the returned list.
|
||||
@@ -1921,7 +1911,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Populates the id property of the saved object, if it's not set already.
|
||||
*
|
||||
*
|
||||
* @param savedObject
|
||||
* @param id
|
||||
*/
|
||||
@@ -1971,7 +1961,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* <li>Execute the given {@link ConnectionCallback} for a {@link Document}.</li>
|
||||
* <li>Apply the given {@link DbObjectCallback} to each of the {@link Document}s to obtain the result.</li>
|
||||
* <ol>
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
* @param collectionCallback the callback to retrieve the {@link Document} with
|
||||
* @param objectCallback the {@link DbObjectCallback} to transform {@link Document}s into the actual domain type
|
||||
@@ -2000,7 +1990,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* <li>Iterate over the {@link DBCursor} and applies the given {@link DbObjectCallback} to each of the
|
||||
* {@link Document}s collecting the actual result {@link List}.</li>
|
||||
* <ol>
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
* @param collectionCallback the callback to retrieve the {@link DBCursor} with
|
||||
* @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
|
||||
@@ -2113,7 +2103,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Handles {@link WriteResult} errors based on the configured {@link WriteResultChecking}.
|
||||
*
|
||||
*
|
||||
* @param writeResult
|
||||
* @param query
|
||||
* @param operation
|
||||
@@ -2157,7 +2147,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Inspects the given {@link CommandResult} for erros and potentially throws an
|
||||
* {@link InvalidDataAccessApiUsageException} for that error.
|
||||
*
|
||||
*
|
||||
* @param result must not be {@literal null}.
|
||||
* @param source must not be {@literal null}.
|
||||
*/
|
||||
@@ -2195,12 +2185,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
|
||||
* exception if the conversation failed. Thus allows safe re-throwing of the return value.
|
||||
*
|
||||
*
|
||||
* @param ex the exception to translate
|
||||
* @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation
|
||||
* @return
|
||||
*/
|
||||
private static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
|
||||
static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
|
||||
PersistenceExceptionTranslator exceptionTranslator) {
|
||||
RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
@@ -2234,7 +2224,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification
|
||||
* {@link Document} and executes that against the {@link DBCollection}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
@@ -2268,7 +2258,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification
|
||||
* {@link Document} and executes that against the {@link DBCollection}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
@@ -2300,7 +2290,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Simple {@link CollectionCallback} that takes a query {@link Document} plus an optional fields specification
|
||||
* {@link Document} and executes that against the {@link DBCollection}.
|
||||
*
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
private static class FindAndRemoveCallback implements CollectionCallback<Document> {
|
||||
@@ -2360,7 +2350,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Simple internal callback to allow operations on a {@link Document}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@@ -2373,7 +2363,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Simple {@link DbObjectCallback} that will transform {@link Document} into the given target type using the given
|
||||
* {@link MongoReader}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@@ -2513,7 +2503,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* {@link DbObjectCallback} that assumes a {@link GeoResult} to be created, delegates actual content unmarshalling to
|
||||
* a delegate and creates a {@link GeoResult} from the result.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static class GeoNearResultDbObjectCallback<T> implements DbObjectCallback<GeoResult<T>> {
|
||||
@@ -2524,7 +2514,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
/**
|
||||
* Creates a new {@link GeoNearResultDbObjectCallback} using the given {@link DbObjectCallback} delegate for
|
||||
* {@link GeoResult} content unmarshalling.
|
||||
*
|
||||
*
|
||||
* @param delegate must not be {@literal null}.
|
||||
*/
|
||||
public GeoNearResultDbObjectCallback(DbObjectCallback<T> delegate, Metric metric) {
|
||||
@@ -2546,7 +2536,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* A {@link CloseableIterator} that is backed by a MongoDB {@link Cursor}.
|
||||
*
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@@ -2565,7 +2555,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}.
|
||||
*
|
||||
*
|
||||
* @param cursor
|
||||
* @param exceptionTranslator
|
||||
* @param objectReadCallback
|
||||
|
||||
@@ -1114,7 +1114,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
if (obj instanceof Map) {
|
||||
|
||||
|
||||
Document result = new Document();
|
||||
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
|
||||
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue(), typeHint));
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class UpdateMapper extends QueryMapper {
|
||||
|
||||
@@ -51,6 +53,70 @@ public class UpdateMapper extends QueryMapper {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.convert.QueryMapper#getMappedObject(Bson, MongoPersistentEntity)
|
||||
*/
|
||||
@Override
|
||||
public Document getMappedObject(Bson query, MongoPersistentEntity<?> entity) {
|
||||
|
||||
Document document = super.getMappedObject(query, entity);
|
||||
|
||||
boolean hasOperators = false;
|
||||
boolean hasFields = false;
|
||||
|
||||
Document set = null;
|
||||
for (String s : document.keySet()) {
|
||||
if (s.startsWith("$")) {
|
||||
|
||||
if(s.equals("$set")){
|
||||
set = document.get(s, Document.class);
|
||||
}
|
||||
hasOperators = true;
|
||||
} else {
|
||||
hasFields = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOperators && hasFields) {
|
||||
|
||||
Document updateObject = new Document();
|
||||
Document fieldsToSet = set == null ? new Document() : set;
|
||||
|
||||
for (String s : document.keySet()) {
|
||||
if (s.startsWith("$")) {
|
||||
updateObject.put(s, document.get(s));
|
||||
} else {
|
||||
fieldsToSet.put(s, document.get(s));
|
||||
}
|
||||
}
|
||||
updateObject.put("$set", fieldsToSet);
|
||||
|
||||
return updateObject;
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@literal true} if the given {@link Document} is an update object that uses update operators.
|
||||
* @param updateObj
|
||||
* @return {@literal true} if the given {@link Document} is an update object.
|
||||
*/
|
||||
public static boolean isUpdateObject(Document updateObj) {
|
||||
|
||||
if (updateObj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String s : updateObj.keySet()) {
|
||||
if (s.startsWith("$")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given source object to a mongo type retaining the original type information of the source type on the
|
||||
* mongo type.
|
||||
|
||||
@@ -360,18 +360,12 @@ public class MongoTemplateTests {
|
||||
assertThat(indexInfo.size(), is(2));
|
||||
Object indexKey = null;
|
||||
boolean unique = false;
|
||||
boolean dropDupes = false;
|
||||
for (org.bson.Document ix : indexInfo) {
|
||||
|
||||
if ("age_-1".equals(ix.get("name"))) {
|
||||
indexKey = ix.get("key");
|
||||
unique = (Boolean) ix.get("unique");
|
||||
if (mongoVersion.isLessThan(TWO_DOT_EIGHT)) {
|
||||
dropDupes = (Boolean) ix.get("dropDups");
|
||||
assertThat(dropDupes, is(true));
|
||||
} else {
|
||||
assertThat(ix.get("dropDups"), is(nullValue()));
|
||||
}
|
||||
assertThat(ix.get("dropDups"), is(nullValue()));
|
||||
}
|
||||
}
|
||||
assertThat(((org.bson.Document) indexKey), IsMapContaining.<String, Object> hasEntry("age", -1));
|
||||
@@ -382,13 +376,7 @@ public class MongoTemplateTests {
|
||||
assertThat(indexInfoList.size(), is(2));
|
||||
IndexInfo ii = indexInfoList.get(1);
|
||||
assertThat(ii.isUnique(), is(true));
|
||||
|
||||
if (mongoVersion.isLessThan(TWO_DOT_EIGHT)) {
|
||||
assertThat(ii.isDropDuplicates(), is(true));
|
||||
} else {
|
||||
assertThat(ii.isDropDuplicates(), is(false));
|
||||
}
|
||||
|
||||
assertThat(ii.isDropDuplicates(), is(false));
|
||||
assertThat(ii.isSparse(), is(false));
|
||||
|
||||
List<IndexField> indexFields = ii.getIndexFields();
|
||||
|
||||
@@ -44,9 +44,6 @@ import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.DBObjectTestUtils;
|
||||
import org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests.ClassWithEnum.Allocation;
|
||||
import org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests.ClassWithEnum.AllocationToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.UpdateMapperUnitTests.ClassWithEnum.StringToAllocationConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
@@ -105,7 +102,7 @@ public class UpdateMapperUnitTests {
|
||||
Document push = getAsDocument(mappedObject, "$push");
|
||||
Document list = getAsDocument(push, "aliased");
|
||||
|
||||
assertThat(list.get("_class"), is((Object) ConcreteChildClass.class.getName()));
|
||||
assertThat(list.get("_class"), is(ConcreteChildClass.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +168,7 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
Document set = getAsDocument(mappedObject, "$set");
|
||||
Document modelDbObject = getAsDocument(set, "aliased.$");
|
||||
assertThat(modelDbObject.get("_class"), is((Object) ConcreteChildClass.class.getName()));
|
||||
assertThat(modelDbObject.get("_class"), is(ConcreteChildClass.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,8 +184,8 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(ParentClass.class));
|
||||
|
||||
Document set = getAsDocument(mappedObject, "$set");
|
||||
assertThat(set.get("aliased.$.value"), is((Object) "foo"));
|
||||
assertThat(set.get("aliased.$.otherValue"), is((Object) "bar"));
|
||||
assertThat(set.get("aliased.$.value"), is("foo"));
|
||||
assertThat(set.get("aliased.$.otherValue"), is("bar"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,12 +201,12 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(ParentClass.class));
|
||||
|
||||
Document dbo = getAsDocument(mappedObject, "$set");
|
||||
assertThat(dbo.get("aliased.$.value"), is((Object) "foo"));
|
||||
assertThat(dbo.get("aliased.$.value"), is("foo"));
|
||||
|
||||
Document someObject = getAsDocument(dbo, "aliased.$.someObject");
|
||||
assertThat(someObject, is(notNullValue()));
|
||||
assertThat(someObject.get("_class"), is((Object) ConcreteChildClass.class.getName()));
|
||||
assertThat(someObject.get("value"), is((Object) "bubu"));
|
||||
assertThat(someObject.get("_class"), is(ConcreteChildClass.class.getName()));
|
||||
assertThat(someObject.get("value"), is("bubu"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,7 +226,7 @@ public class UpdateMapperUnitTests {
|
||||
assertThat(push.get("_class"), nullValue());
|
||||
assertThat(values.get("_class"), nullValue());
|
||||
|
||||
assertThat(each, IsIterableContainingInOrder.<Object> contains("spring", "data", "mongodb"));
|
||||
assertThat(each, IsIterableContainingInOrder.contains("spring", "data", "mongodb"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +261,7 @@ public class UpdateMapperUnitTests {
|
||||
List<Object> each = getAsDBList(model, "$each");
|
||||
List<Object> values = getAsDBList((Document) each.get(0), "values");
|
||||
|
||||
assertThat(values, IsIterableContainingInOrder.<Object> contains("spring", "data", "mongodb"));
|
||||
assertThat(values, IsIterableContainingInOrder.contains("spring", "data", "mongodb"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +309,7 @@ public class UpdateMapperUnitTests {
|
||||
Document key = getAsDocument(push, "key");
|
||||
|
||||
assertThat(key.containsKey("$position"), is(true));
|
||||
assertThat((Integer) key.get("$position"), is(2));
|
||||
assertThat(key.get("$position"), is(2));
|
||||
assertThat(getAsDocument(push, "key").containsKey("$each"), is(true));
|
||||
}
|
||||
|
||||
@@ -330,7 +327,7 @@ public class UpdateMapperUnitTests {
|
||||
Document key = getAsDocument(push, "key");
|
||||
|
||||
assertThat(key.containsKey("$position"), is(true));
|
||||
assertThat((Integer) key.get("$position"), is(0));
|
||||
assertThat(key.get("$position"), is(0));
|
||||
assertThat(getAsDocument(push, "key").containsKey("$each"), is(true));
|
||||
}
|
||||
|
||||
@@ -382,7 +379,7 @@ public class UpdateMapperUnitTests {
|
||||
Document key = getAsDocument(push, "key");
|
||||
|
||||
assertThat(key.containsKey("$slice"), is(true));
|
||||
assertThat((Integer) key.get("$slice"), is(5));
|
||||
assertThat(key.get("$slice"), is(5));
|
||||
assertThat(key.containsKey("$each"), is(true));
|
||||
}
|
||||
|
||||
@@ -401,13 +398,13 @@ public class UpdateMapperUnitTests {
|
||||
Document key = getAsDocument(push, "key");
|
||||
|
||||
assertThat(key.containsKey("$slice"), is(true));
|
||||
assertThat((Integer) key.get("$slice"), is(5));
|
||||
assertThat(key.get("$slice"), is(5));
|
||||
assertThat(key.containsKey("$each"), is(true));
|
||||
|
||||
Document key2 = getAsDocument(push, "key-2");
|
||||
|
||||
assertThat(key2.containsKey("$slice"), is(true));
|
||||
assertThat((Integer) key2.get("$slice"), is(-2));
|
||||
assertThat(key2.get("$slice"), is(-2));
|
||||
assertThat(key2.containsKey("$each"), is(true));
|
||||
}
|
||||
|
||||
@@ -439,7 +436,7 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(DocumentWithDBRefCollection.class));
|
||||
|
||||
Document pullClause = getAsDocument(mappedObject, "$pull");
|
||||
assertThat(pullClause.get("dbRefAnnotatedList"), is((Object) new DBRef("entity", "2")));
|
||||
assertThat(pullClause.get("dbRefAnnotatedList"), is(new DBRef("entity", "2")));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,7 +453,7 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(DocumentWithDBRefCollection.class));
|
||||
|
||||
Document pullClause = getAsDocument(mappedObject, "$pull");
|
||||
assertThat(pullClause.get("dbRefAnnotatedList"), is((Object) new DBRef("entity", entity.id)));
|
||||
assertThat(pullClause.get("dbRefAnnotatedList"), is(new DBRef("entity", entity.id)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,7 +494,7 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(DocumentWithDBRefCollection.class));
|
||||
|
||||
Document setClause = getAsDocument(mappedObject, "$set");
|
||||
assertThat(setClause.get("dbRefProperty"), is((Object) new DBRef("entity", entity.id)));
|
||||
assertThat(setClause.get("dbRefProperty"), is(new DBRef("entity", entity.id)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -532,7 +529,7 @@ public class UpdateMapperUnitTests {
|
||||
Document idClause = getAsDocument(options, "_id");
|
||||
List<Object> inClause = getAsDBList(idClause, "$in");
|
||||
|
||||
assertThat(inClause, IsIterableContainingInOrder.<Object> contains(1L, 2L));
|
||||
assertThat(inClause, IsIterableContainingInOrder.contains(1L, 2L));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,7 +547,7 @@ public class UpdateMapperUnitTests {
|
||||
Document values = getAsDocument(addToSet, "values");
|
||||
List<Object> each = getAsDBList(values, "$each");
|
||||
|
||||
assertThat(each, IsIterableContainingInOrder.<Object> contains("spring", "data", "mongodb"));
|
||||
assertThat(each, IsIterableContainingInOrder.contains("spring", "data", "mongodb"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -588,7 +585,7 @@ public class UpdateMapperUnitTests {
|
||||
Object model = $set.get("referencedDocument");
|
||||
|
||||
DBRef expectedDBRef = new DBRef("interfaceDocumentDefinitionImpl", "1");
|
||||
assertThat(model, allOf(instanceOf(DBRef.class), IsEqual.<Object> equalTo(expectedDBRef)));
|
||||
assertThat(model, allOf(instanceOf(DBRef.class), IsEqual.equalTo(expectedDBRef)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,7 +603,7 @@ public class UpdateMapperUnitTests {
|
||||
Document value = DBObjectTestUtils.getAsDocument(list, "value");
|
||||
List<Object> $in = DBObjectTestUtils.getAsDBList(value, "$in");
|
||||
|
||||
assertThat($in, IsIterableContainingInOrder.<Object> contains("foo", "bar"));
|
||||
assertThat($in, IsIterableContainingInOrder.contains("foo", "bar"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -719,7 +716,7 @@ public class UpdateMapperUnitTests {
|
||||
public void mappingShouldRetainTypeInformationOfNestedListWhenUpdatingConcreteyParentType() {
|
||||
|
||||
ListModelWrapper lmw = new ListModelWrapper();
|
||||
lmw.models = Collections.<Model> singletonList(new ModelImpl(1));
|
||||
lmw.models = Collections.singletonList(new ModelImpl(1));
|
||||
|
||||
Update update = new Update().set("concreteTypeWithListAttributeOfInterfaceType", lmw);
|
||||
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
|
||||
@@ -778,7 +775,7 @@ public class UpdateMapperUnitTests {
|
||||
@Test
|
||||
public void mappingShouldRetrainTypeInformationWhenValueTypeOfMapDoesNotMatchItsDeclaration() {
|
||||
|
||||
Map<Object, Object> map = Collections.<Object, Object> singletonMap("szeth", new NestedDocument("son-son-vallano"));
|
||||
Map<Object, Object> map = Collections.singletonMap("szeth", new NestedDocument("son-son-vallano"));
|
||||
|
||||
Update update = new Update().set("map", map);
|
||||
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
|
||||
@@ -794,7 +791,7 @@ public class UpdateMapperUnitTests {
|
||||
@Test
|
||||
public void mappingShouldNotContainTypeInformationWhenValueTypeOfMapMatchesDeclaration() {
|
||||
|
||||
Map<Object, NestedDocument> map = Collections.<Object, NestedDocument> singletonMap("jasnah",
|
||||
Map<Object, NestedDocument> map = Collections.singletonMap("jasnah",
|
||||
new NestedDocument("kholin"));
|
||||
|
||||
Update update = new Update().set("concreteMap", map);
|
||||
@@ -813,7 +810,7 @@ public class UpdateMapperUnitTests {
|
||||
public void mapsUpdateWithBothReadingAndWritingConverterRegistered() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Arrays.asList(AllocationToStringConverter.INSTANCE, StringToAllocationConverter.INSTANCE));
|
||||
Arrays.asList(ClassWithEnum.AllocationToStringConverter.INSTANCE, ClassWithEnum.StringToAllocationConverter.INSTANCE));
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
@@ -825,11 +822,11 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
UpdateMapper mapper = new UpdateMapper(converter);
|
||||
|
||||
Update update = new Update().set("allocation", Allocation.AVAILABLE);
|
||||
Update update = new Update().set("allocation", ClassWithEnum.Allocation.AVAILABLE);
|
||||
Document result = mapper.getMappedObject(update.getUpdateObject(),
|
||||
mappingContext.getPersistentEntity(ClassWithEnum.class));
|
||||
|
||||
assertThat(result, isBsonObject().containing("$set.allocation", Allocation.AVAILABLE.code));
|
||||
assertThat(result, isBsonObject().containing("$set.allocation", ClassWithEnum.Allocation.AVAILABLE.code));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -907,7 +904,7 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
Document $set = DBObjectTestUtils.getAsDocument(mappedUpdate, "$set");
|
||||
assertThat($set.get("intValue"), Is.<Object> is(10));
|
||||
assertThat($set.get("intValue"), Is.is(10));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -921,7 +918,7 @@ public class UpdateMapperUnitTests {
|
||||
context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
Document $set = DBObjectTestUtils.getAsDocument(mappedUpdate, "$set");
|
||||
assertThat($set.get("primIntValue"), Is.<Object> is(10));
|
||||
assertThat($set.get("primIntValue"), Is.is(10));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -958,7 +955,7 @@ public class UpdateMapperUnitTests {
|
||||
public void mappingShouldConsiderCustomConvertersForEnumMapKeys() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(
|
||||
Arrays.asList(AllocationToStringConverter.INSTANCE, StringToAllocationConverter.INSTANCE));
|
||||
Arrays.asList(ClassWithEnum.AllocationToStringConverter.INSTANCE, ClassWithEnum.StringToAllocationConverter.INSTANCE));
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
|
||||
@@ -970,7 +967,7 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
UpdateMapper mapper = new UpdateMapper(converter);
|
||||
|
||||
Update update = new Update().set("enumAsMapKey", Collections.singletonMap(Allocation.AVAILABLE, 100));
|
||||
Update update = new Update().set("enumAsMapKey", Collections.singletonMap(ClassWithEnum.Allocation.AVAILABLE, 100));
|
||||
Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(),
|
||||
mappingContext.getPersistentEntity(ClassWithEnum.class));
|
||||
|
||||
@@ -981,6 +978,51 @@ public class UpdateMapperUnitTests {
|
||||
assertThat(enumAsMapKey.get("AVAILABLE"), is(100));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1176
|
||||
*/
|
||||
@Test
|
||||
public void mappingShouldPrepareUpdateObjectForMixedOperatorsAndFields() {
|
||||
|
||||
Document document = new Document("key", "value").append("$set", new Document("a", "b").append("x", "y"));
|
||||
|
||||
Document mappedObject = mapper.getMappedObject(document, context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
assertThat(mappedObject.get("$set"), is(equalTo(new Document("a", "b").append("x", "y").append("key", "value"))));
|
||||
assertThat(mappedObject.size(), is(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1176
|
||||
*/
|
||||
@Test
|
||||
public void mappingShouldReturnReplaceObject() {
|
||||
|
||||
Document document = new Document("key", "value").append("a", "b").append("x", "y");
|
||||
|
||||
Document mappedObject = mapper.getMappedObject(document, context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
assertThat(mappedObject.get("key"), is(equalTo("value")));
|
||||
assertThat(mappedObject.get("a"), is(equalTo("b")));
|
||||
assertThat(mappedObject.get("x"), is(equalTo("y")));
|
||||
assertThat(mappedObject.size(), is(3));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1176
|
||||
*/
|
||||
@Test
|
||||
public void mappingShouldReturnUpdateObject() {
|
||||
|
||||
Document document = new Document("$push", new Document("x", "y")).append("$set", new Document("a", "b"));
|
||||
|
||||
Document mappedObject = mapper.getMappedObject(document, context.getPersistentEntity(SimpleValueHolder.class));
|
||||
|
||||
assertThat(mappedObject.get("$push"), is(equalTo(new Document("x", "y"))));
|
||||
assertThat(mappedObject.get("$set"), is(equalTo(new Document("a", "b"))));
|
||||
assertThat(mappedObject.size(), is(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1486
|
||||
*/
|
||||
@@ -1011,7 +1053,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
|
||||
@org.springframework.data.mongodb.core.mapping.Document(collection = "DocumentWithReferenceToInterface")
|
||||
static interface DocumentWithReferenceToInterface {
|
||||
interface DocumentWithReferenceToInterface {
|
||||
|
||||
String getId();
|
||||
|
||||
@@ -1019,7 +1061,7 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
}
|
||||
|
||||
static interface InterfaceDocumentDefinitionWithoutId {
|
||||
interface InterfaceDocumentDefinitionWithoutId {
|
||||
|
||||
String getValue();
|
||||
}
|
||||
@@ -1068,7 +1110,7 @@ public class UpdateMapperUnitTests {
|
||||
|
||||
}
|
||||
|
||||
static interface Model {}
|
||||
interface Model {}
|
||||
|
||||
static class ModelImpl implements Model {
|
||||
public int value;
|
||||
@@ -1226,13 +1268,13 @@ public class UpdateMapperUnitTests {
|
||||
Allocation allocation;
|
||||
Map<Allocation, String> enumAsMapKey;
|
||||
|
||||
static enum Allocation {
|
||||
enum Allocation {
|
||||
|
||||
AVAILABLE("V"), ALLOCATED("A");
|
||||
|
||||
String code;
|
||||
|
||||
private Allocation(String code) {
|
||||
Allocation(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@@ -1248,7 +1290,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
static enum AllocationToStringConverter implements Converter<Allocation, String> {
|
||||
enum AllocationToStringConverter implements Converter<Allocation, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@@ -1258,7 +1300,7 @@ public class UpdateMapperUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
static enum StringToAllocationConverter implements Converter<String, Allocation> {
|
||||
enum StringToAllocationConverter implements Converter<String, Allocation> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user