Compare commits

...

24 Commits

Author SHA1 Message Date
Oliver Gierke
909fda2076 DATAMONGO-1527 - Release version 2.0 M1 (Kay). 2016-11-23 10:35:48 +01:00
Oliver Gierke
3b5d231529 DATAMONGO-1527 - Prepare 2.0 M1 (Kay). 2016-11-23 10:35:08 +01:00
Oliver Gierke
e90fe70ae1 DATAMONGO-1527 - Updated changelog. 2016-11-23 10:35:01 +01:00
Oliver Gierke
27d379ba71 DATAMONGO-1527 - Removed explicit reference to Spring Framework 5 snapshots. 2016-11-19 15:30:23 +01:00
Mark Paluch
e987a853ac DATAMONGO-1509 - Polishing.
Adopt type hint assertion for existing _class field checks. Simplify test code to use Collections.singletonList instead of Arrays.asList. Replace BasicDBList with List in JavaDoc. Use type inference for DocumentTestUtils.getAsDBList to avoid casts in test code. Extend documentation.

Original pull request: #411.
2016-11-17 15:54:10 +01:00
Christoph Strobl
3c16b4db7f DATAMONGO-1509 - Write type hint as last element of a Document.
Always add type hint as last property of a Document.
This is necessary to assure document equality within MongoDB in cases where the query contains full document comparisons. Unfortunately this also might break existing stuff since the order of properties within a Document is changed with this commit.

Original pull request: #411.
2016-11-17 15:12:36 +01:00
Mark Paluch
070d784be3 DATAMONGO-1176 - Exclude null id fields in bulk insert.
We no longer map _id fields into Document that are null to enforce MongoDB ObjectId generation on batch insert like insertAll.
2016-11-17 13:56:45 +01:00
Mark Paluch
af4f0e0913 DATAMONGO-1444 - Accept Collection and subtypes in ReactiveMongoOperations.insertAll(…). 2016-11-14 18:13:35 +01:00
Oliver Gierke
474af92075 DATAMONGO-1444 - Moved to new base class for reactive repository factories. 2016-11-14 18:13:34 +01:00
Oliver Gierke
99838c02fd DATAMONGO-1444 - Adapt to new changes in reactive repository configuration.
We now use the newly introduced ….useRepositoryConfiguration(…) in the module specific RepositoryConfigurationExtension implementations to distinguish between reactive and non-reactive repositories.

Removed RepositoryType class as it was only used by the previous repository typ detection.
2016-11-14 18:13:34 +01:00
Oliver Gierke
8060ebae6a DATAMONGO-1444 - Polishing.
Removed unused references to ConversionService from repository query implementations.
2016-11-14 18:13:34 +01:00
Mark Paluch
9e9495ee54 DATAMONGO-1444 - Make Project Reactor dependency no longer required for blocking repository usage.
Use ReactiveWrapperConverters for reactive wrapper type conversion to not require Project Reactor for blocking repository usage.
2016-11-14 18:13:34 +01:00
Christoph Strobl
098aae41b7 DATAMONGO-1444 - Update bulk insert operations.
Accept Mono<Collection<T>> instead of Publisher<T> to get rid of hidden buffer call inside of MongoTemplate.
2016-11-14 18:13:28 +01:00
Christoph Strobl
df859d0f3a DATAMONGO-1444 - Adopt changes in Spring Data Commons.
- Adopt RxJava to RxJava1 repository interface renaming.
- Remove ReactiveChunk, Slice and Page.
- Update documentation.
- Prevent sliced/paged query execution.
2016-11-14 18:13:25 +01:00
Christoph Strobl
e0f371f648 DATAMONGO-1444 - Polishing.
- Update Javadoc comments and reference documentation.
- Introduce Adapter for blocking IndexOperations.
- Remove transaction synchronization.
- Remove unused types.
- Remove dropDupos options from indexes.
- Prevent usage of Querydsl along with reactive repository.
- Use ReactiveQueryMethod in ReactiveMongoQuery.
2016-11-14 18:13:25 +01:00
Mark Paluch
2145e212ca DATAMONGO-1444 - Add support for RxJava wrapper types and slice queries.
Reactive MongoDB repository can now be composed from Project Reactor and RxJava types for method arguments and return types. Query methods and methods from the base/implementation classes can be invoked with a conversion of input/output types.
2016-11-14 18:13:25 +01:00
Mark Paluch
c814073441 DATAMONGO-1176 - Test code cleanup.
Replace DbObject in documentation with Document. Fix typos. Change dbObject variable names to document.
2016-11-14 18:13:24 +01:00
Mark Paluch
59573b10e6 DATAMONGO-1176 - Cleanup.
Replace DbObject in documentation with Document. Fix typos. Change dbObject variable names to document. Improve error messages. Remove unused code.
2016-11-14 18:13:24 +01:00
Christoph Strobl
054274392e DATAMONGO-1176 - Cleanup.
- Update licenses headers.
- Renname variables and methods from dbo -> document.
- Remove deprecations.
- Remove unused code blocks.
- Upgrade to MongoDB Java Driver 3.3
2016-11-14 18:13:24 +01:00
Mark Paluch
2d3efdc0b4 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.
2016-11-14 18:13:23 +01:00
Christoph Strobl
2461575c52 DATAMONGO-1176 - Switch to Document API.
We use the Document API when interacting with the MongoDB Java Driver. This allows us to make use of new features and enables us to use the Codec API and prepares the project for future enhancements concerning the drivers the reactive API.
2016-11-14 18:13:23 +01:00
Mark Paluch
4371760272 DATAMONGO-1461 - Upgrade Hibernate/Validator/JPA dependencies to match Spring 5 baseline.
Upgrade:
* Hibernate Validator to 5.2.4.Final
* JPA API to 2.1.1
* Hibernate Core to 5.2.1.Final
2016-11-14 17:49:48 +01:00
Mark Paluch
da5289fc18 DATAMONGO-1448 - Prepare 2.0 development.
Upgraded to Spring Data Build parent 2.0 snapshots and Spring Data Commons 2.0 snapshots. Removed obsolete distribution key property. Removed obsolete template.mf.
2016-11-14 17:49:48 +01:00
Oliver Gierke
ea9b402547 DATAMONGO-1525 - Improved creation of empty collections, esp. EnumSet.
We now use more type information to create a better empty collection in the first place. The previous algorithm always used an empty HashSet plus a subsequent conversion using the raw collection type. Especially the latter caused problems for EnumSets as the conversion into one requires the presence of component type information.

We now use Spring's collection factory and more available type information to create a proper collection in the first place and only rely on a subsequent conversion for arrays.
2016-11-13 18:33:45 +01:00
319 changed files with 19650 additions and 5716 deletions

View File

@@ -9,7 +9,6 @@ before_script:
env:
matrix:
- PROFILE=ci
- PROFILE=mongo-next
- PROFILE=mongo3
- PROFILE=mongo3-next
- PROFILE=mongo31

41
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
<packaging>pom</packaging>
<name>Spring Data MongoDB</name>
@@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>1.9.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
</parent>
<modules>
@@ -28,9 +28,9 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>1.13.0.BUILD-SNAPSHOT</springdata.commons>
<mongo>2.14.3</mongo>
<mongo.osgi>2.13.0</mongo.osgi>
<springdata.commons>2.0.0.M1</springdata.commons>
<mongo>3.2.2</mongo>
<mongo.reactivestreams>1.2.0</mongo.reactivestreams>
</properties>
<developers>
@@ -100,25 +100,20 @@
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>mpaluch</id>
<name>Mark Paluch</name>
<email>mpaluch at pivotal.io</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.pivotal.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
</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>
@@ -220,8 +215,8 @@
<repositories>
<repository>
<id>spring-libs-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
<id>spring-libs-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</repositories>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -14,8 +14,8 @@
<name>Spring Data MongoDB - Cross-Store Support</name>
<properties>
<jpa>2.0.0</jpa>
<hibernate>3.6.10.Final</hibernate>
<jpa>2.1.1</jpa>
<hibernate>5.2.1.Final</hibernate>
</properties>
<dependencies>
@@ -48,7 +48,15 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
</dependency>
<!-- reactive -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>${reactor}</version>
<optional>true</optional>
</dependency>
<dependency>
@@ -87,7 +95,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
<version>5.2.4.Final</version>
<scope>test</scope>
</dependency>

View File

@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.crossstore;
import javax.persistence.EntityManagerFactory;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
@@ -29,10 +30,10 @@ import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.DeleteResult;
/**
* @author Thomas Risberg
@@ -74,15 +75,15 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
String collName = getCollectionNameForEntity(entityClass);
final DBObject dbk = new BasicDBObject();
final Document dbk = new Document();
dbk.put(ENTITY_ID, id);
dbk.put(ENTITY_CLASS, entityClass.getName());
if (log.isDebugEnabled()) {
log.debug("Loading MongoDB data for {}", dbk);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
for (DBObject dbo : collection.find(dbk)) {
public Object doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
for (Document dbo : collection.find(dbk)) {
String key = (String) dbo.get(ENTITY_FIELD_NAME);
if (log.isDebugEnabled()) {
log.debug("Processing key: {}", key);
@@ -143,27 +144,31 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
for (String key : cs.getValues().keySet()) {
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
Object value = cs.getValues().get(key);
final DBObject dbQuery = new BasicDBObject();
final Document dbQuery = new Document();
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
dbQuery.put(ENTITY_FIELD_NAME, key);
DBObject dbId = mongoTemplate.execute(collName, new CollectionCallback<DBObject>() {
public DBObject doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.findOne(dbQuery);
final Document dbId = mongoTemplate.execute(collName, new CollectionCallback<Document>() {
public Document doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
Document id = collection.find(dbQuery).first();
return id;
}
});
if (value == null) {
if (log.isDebugEnabled()) {
log.debug("Flush: removing: {}", dbQuery);
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.remove(dbQuery);
public Object doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
DeleteResult dr = collection.deleteMany(dbQuery);
return null;
}
});
} else {
final DBObject dbDoc = new BasicDBObject();
final Document dbDoc = new Document();
dbDoc.putAll(dbQuery);
if (log.isDebugEnabled()) {
log.debug("Flush: saving: {}", dbQuery);
@@ -174,8 +179,18 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
dbDoc.put("_id", dbId.get("_id"));
}
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.save(dbDoc);
public Object doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
if (dbId != null) {
collection.replaceOne(Filters.eq("_id", dbId.get("_id")), dbDoc);
} else {
if (dbDoc.containsKey("_id") && dbDoc.get("_id") == null) {
dbDoc.remove("_id");
}
collection.insertOne(dbDoc);
}
return null;
}
});

View File

@@ -18,6 +18,7 @@ package org.springframework.data.mongodb.crossstore;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.bson.Document;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -36,8 +37,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.mongodb.DBObject;
/**
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
*
@@ -48,14 +47,11 @@ import com.mongodb.DBObject;
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
public class CrossStoreMongoTests {
@Autowired
MongoTemplate mongoTemplate;
@Autowired MongoTemplate mongoTemplate;
@PersistenceContext
EntityManager entityManager;
@PersistenceContext EntityManager entityManager;
@Autowired
PlatformTransactionManager transactionManager;
@Autowired PlatformTransactionManager transactionManager;
TransactionTemplate txTemplate;
@Before
@@ -187,7 +183,7 @@ public class CrossStoreMongoTests {
boolean weFound3 = false;
for (DBObject dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
for (Document dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
if (dbo.get("_entity_id").equals(3L)) {
weFound3 = true;

View File

@@ -20,7 +20,7 @@
<mongo:mapping-converter/>
<!-- Mongo config -->
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoClientFactoryBean">
<property name="host" value="localhost"/>
<property name="port" value="27017"/>
</bean>

View File

@@ -1,18 +0,0 @@
Bundle-SymbolicName: org.springframework.data.mongodb.crossstore
Bundle-Name: Spring Data MongoDB Cross Store Support
Bundle-Vendor: Pivotal Software, Inc.
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Export-Template:
org.springframework.data.mongodb.crossstore.*;version="${project.version}"
Import-Template:
com.mongodb.*;version="${mongo.osgi:[=.=.=,+1.0.0)}",
javax.persistence.*;version="${jpa:[=.=.=,+1.0.0)}",
org.aspectj.*;version="${aspectj:[1.0.0, 2.0.0)}",
org.bson.*;version="0",
org.slf4j.*;version="${slf4j:[=.=.=,+1.0.0)}",
org.springframework.*;version="${spring:[=.=.=.=,+1.0.0)}",
org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",
org.springframework.data.mongodb.*;version="${project.version:[=.=.=.=,+1.0.0)}",
org.w3c.dom.*;version="0"

View File

@@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -1,9 +0,0 @@
Bundle-SymbolicName: org.springframework.data.mongodb.log4j
Bundle-Name: Spring Data Mongo DB Log4J Appender
Bundle-Vendor: Pivotal Software, Inc.
Bundle-ManifestVersion: 2
Import-Package:
sun.reflect;version="0";resolution:=optional
Import-Template:
com.mongodb.*;version="${mongo.osgi:[=.=.=,+1.0.0)}",
org.apache.log4j.*;version="${log4j:[=.=.=,+1.0.0)}"

View File

@@ -11,13 +11,14 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>1.10.0.BUILD-SNAPSHOT</version>
<version>2.0.0.M1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<objenesis>1.3</objenesis>
<equalsverifier>1.5</equalsverifier>
<mongo>3.3.0</mongo>
</properties>
<dependencies>
@@ -78,6 +79,52 @@
<optional>true</optional>
</dependency>
<!-- reactive -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>${mongo.reactivestreams}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>${mongo}</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>${reactor}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>${rxjava}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava-reactive-streams</artifactId>
<version>${rxjava-reactive-streams}</version>
<optional>true</optional>
</dependency>
<!-- CDI -->
<dependency>
<groupId>javax.enterprise</groupId>
@@ -126,7 +173,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
<version>5.2.4.Final</version>
<scope>test</scope>
</dependency>
@@ -212,9 +259,11 @@
</includes>
<excludes>
<exclude>**/PerformanceTests.java</exclude>
<exclude>**/ReactivePerformanceTests.java</exclude>
</excludes>
<systemPropertyVariables>
<java.util.logging.config.file>src/test/resources/logging.properties</java.util.logging.config.file>
<reactor.trace.cancel>true</reactor.trace.cancel>
</systemPropertyVariables>
<properties>
<property>

View File

@@ -20,6 +20,7 @@ import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
import com.mongodb.DB;
import com.mongodb.client.MongoDatabase;
/**
* Interface for factories creating {@link DB} instances.
@@ -35,7 +36,7 @@ public interface MongoDbFactory {
* @return
* @throws DataAccessException
*/
DB getDb() throws DataAccessException;
MongoDatabase getDb() throws DataAccessException;
/**
* Creates a {@link DB} instance to access the database with the given name.
@@ -44,7 +45,7 @@ public interface MongoDbFactory {
* @return
* @throws DataAccessException
*/
DB getDb(String dbName) throws DataAccessException;
MongoDatabase getDb(String dbName) throws DataAccessException;
/**
* Exposes a shared {@link MongoExceptionTranslator}.
@@ -52,4 +53,6 @@ public interface MongoDbFactory {
* @return will never be {@literal null}.
*/
PersistenceExceptionTranslator getExceptionTranslator();
DB getLegacyDb();
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.MongoExceptionTranslator;
import com.mongodb.reactivestreams.client.MongoDatabase;
/**
* Interface for factories creating reactive {@link MongoDatabase} instances.
*
* @author Mark Paluch
* @since 2.0
*/
public interface ReactiveMongoDatabaseFactory {
/**
* Creates a default {@link MongoDatabase} instance.
*
* @return
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase() throws DataAccessException;
/**
* Creates a {@link MongoDatabase} instance to access the database with the given name.
*
* @param dbName must not be {@literal null} or empty.
* @return
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase(String dbName) throws DataAccessException;
/**
* Exposes a shared {@link MongoExceptionTranslator}.
*
* @return will never be {@literal null}.
*/
PersistenceExceptionTranslator getExceptionTranslator();
}

View File

@@ -15,36 +15,16 @@
*/
package org.springframework.data.mongodb.config;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
@@ -57,16 +37,11 @@ import com.mongodb.MongoClient;
* @author Thomas Darimont
* @author Ryan Tenney
* @author Christoph Strobl
* @author Mark Paluch
* @see MongoConfigurationSupport
*/
@Configuration
public abstract class AbstractMongoConfiguration {
/**
* Return the name of the database to connect to.
*
* @return must not be {@literal null}.
*/
protected abstract String getDatabaseName();
public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport {
/**
* Return the name of the authentication database to use. Defaults to {@literal null} and will turn into the value
@@ -120,7 +95,7 @@ public abstract class AbstractMongoConfiguration {
* class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
* {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is
* overridden to implement alternate behavior.
*
*
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
* entities.
* @deprecated use {@link #getMappingBasePackages()} instead.
@@ -132,20 +107,6 @@ public abstract class AbstractMongoConfiguration {
return mappingBasePackage == null ? null : mappingBasePackage.getName();
}
/**
* Returns the base packages to scan for MongoDB mapped entities at startup. Will return the package name of the
* configuration class' (the concrete class, not this one here) by default. So if you have a
* {@code com.acme.AppConfig} extending {@link AbstractMongoConfiguration} the base package will be considered
* {@code com.acme} unless the method is overridden to implement alternate behavior.
*
* @return the base packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning
* for entities.
* @since 1.10
*/
protected Collection<String> getMappingBasePackages() {
return Collections.singleton(getMappingBasePackage());
}
/**
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
* be used.
@@ -159,47 +120,6 @@ public abstract class AbstractMongoConfiguration {
return null;
}
/**
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
*
* @see #getMappingBasePackage()
* @return
* @throws ClassNotFoundException
*/
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
/**
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
*
* @return
* @throws ClassNotFoundException
*/
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(mongoMappingContext()));
}
/**
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/
@Bean
public CustomConversions customConversions() {
return new CustomConversions(Collections.emptyList());
}
/**
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
@@ -219,79 +139,4 @@ public abstract class AbstractMongoConfiguration {
return converter;
}
/**
* Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in
* all packages returned by {@link #getMappingBasePackages()}.
*
* @see #getMappingBasePackages()
* @return
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (String basePackage : getMappingBasePackages()) {
initialEntitySet.addAll(scanForEntities(basePackage));
}
return initialEntitySet;
}
/**
* Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and
* {@link Persistent}.
*
* @param basePackage must not be {@literal null}.
* @return
* @throws ClassNotFoundException
* @since 1.10
*/
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
if (!StringUtils.hasText(basePackage)) {
return Collections.emptySet();
}
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet
.add(ClassUtils.forName(candidate.getBeanClassName(), AbstractMongoConfiguration.class.getClassLoader()));
}
}
return initialEntitySet;
}
/**
* Configures whether to abbreviate field names for domain objects by configuring a
* {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. For advanced
* customization needs, consider overriding {@link #mappingMongoConverter()}.
*
* @return
*/
protected boolean abbreviateFieldNames() {
return false;
}
/**
* Configures a {@link FieldNamingStrategy} on the {@link MongoMappingContext} instance created.
*
* @return
* @since 1.5
*/
protected FieldNamingStrategy fieldNamingStrategy() {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import com.mongodb.reactivestreams.client.MongoClient;
/**
* Base class for reactive Spring Data MongoDB configuration using JavaConfig.
*
* @author Mark Paluch
* @since 2.0
* @see MongoConfigurationSupport
*/
@Configuration
public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurationSupport {
/**
* Return the {@link MongoClient} instance to connect to. Annotate with {@link Bean} in case you want to expose a
* {@link MongoClient} instance to the {@link org.springframework.context.ApplicationContext}.
*
* @return
*/
public abstract MongoClient mongoClient();
/**
* Creates a {@link ReactiveMongoTemplate}.
*
* @return
*/
@Bean
public ReactiveMongoOperations reactiveMongoTemplate() throws Exception {
return new ReactiveMongoTemplate(mongoDbFactory(), mappingMongoConverter());
}
/**
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link Mongo} instance
* configured in {@link #mongoClient()}.
*
* @see #mongoClient()
* @see #reactiveMongoTemplate()
* @return
* @throws Exception
*/
@Bean
public ReactiveMongoDatabaseFactory mongoDbFactory() {
return new SimpleReactiveMongoDatabaseFactory(mongoClient(), getDatabaseName());
}
/**
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
*
* @see #customConversions()
* @see #mongoMappingContext()
* @see #mongoDbFactory()
* @return
* @throws Exception
*/
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(ReactiveMongoTemplate.NO_OP_REF_RESOLVER,
mongoMappingContext());
converter.setCustomConversions(customConversions());
return converter;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2016 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.
@@ -67,12 +67,13 @@ import org.w3c.dom.Element;
/**
* Bean definition parser for the {@code mapping-converter} element.
*
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Maciej Walkowiak
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
public class MappingMongoConverterParser implements BeanDefinitionParser {
@@ -120,16 +121,21 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
converterBuilder.addPropertyValue("customConversions", conversionsDefinition);
}
if(!registry.containsBeanDefinition("indexOperationsProvider")){
BeanDefinitionBuilder indexOperationsProviderBuilder = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.data.mongodb.core.DefaultIndexOperationsProvider");
indexOperationsProviderBuilder.addConstructorArgReference(dbFactoryRef);
parserContext.registerBeanComponent(new BeanComponentDefinition(indexOperationsProviderBuilder.getBeanDefinition(), "indexOperationsProvider"));
}
try {
registry.getBeanDefinition(INDEX_HELPER_BEAN_NAME);
} catch (NoSuchBeanDefinitionException ignored) {
if (!StringUtils.hasText(dbFactoryRef)) {
dbFactoryRef = DB_FACTORY_BEAN_NAME;
}
BeanDefinitionBuilder indexHelperBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MongoPersistentEntityIndexCreator.class);
indexHelperBuilder.addConstructorArgReference(ctxRef);
indexHelperBuilder.addConstructorArgReference(dbFactoryRef);
indexHelperBuilder.addConstructorArgReference("indexOperationsProvider");
indexHelperBuilder.addDependsOn(ctxRef);
parserContext.registerBeanComponent(new BeanComponentDefinition(indexHelperBuilder.getBeanDefinition(),
@@ -348,7 +354,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
/**
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
*
*
* @author Oliver Gierke
*/
private static class NegatingFilter implements TypeFilter {
@@ -357,7 +363,7 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
/**
* Creates a new {@link NegatingFilter} with the given delegates.
*
*
* @param filters
*/
public NegatingFilter(TypeFilter... filters) {

View File

@@ -0,0 +1,203 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
import org.springframework.data.mapping.model.FieldNamingStrategy;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.support.CachingIsNewStrategyFactory;
import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
/**
* Base class for Spring Data MongoDB to be extended for JavaConfiguration usage.
*
* @author Mark Paluch
* @since 2.0
*/
public abstract class MongoConfigurationSupport {
/**
* Return the name of the database to connect to.
*
* @return must not be {@literal null}.
*/
protected abstract String getDatabaseName();
/**
* Returns the base packages to scan for MongoDB mapped entities at startup. Will return the package name of the
* configuration class' (the concrete class, not this one here) by default. So if you have a
* {@code com.acme.AppConfig} extending {@link MongoConfigurationSupport} the base package will be considered
* {@code com.acme} unless the method is overridden to implement alternate behavior.
*
* @return the base packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning
* for entities.
* @since 1.10
*/
protected Collection<String> getMappingBasePackages() {
Package mappingBasePackage = getClass().getPackage();
return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName());
}
/**
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
*
* @see #getMappingBasePackage()
* @return
* @throws ClassNotFoundException
*/
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
/**
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
*
* @return
* @throws ClassNotFoundException
*/
@Bean
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(
new PersistentEntities(Arrays.<MappingContext<?, ?>> asList(new MappingContext[] { mongoMappingContext() }))));
}
/**
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/
@Bean
public CustomConversions customConversions() {
return new CustomConversions(Collections.emptyList());
}
/**
* Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in
* all packages returned by {@link #getMappingBasePackages()}.
*
* @see #getMappingBasePackages()
* @return
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
for (String basePackage : getMappingBasePackages()) {
initialEntitySet.addAll(scanForEntities(basePackage));
}
return initialEntitySet;
}
/**
* Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and
* {@link Persistent}.
*
* @param basePackage must not be {@literal null}.
* @return
* @throws ClassNotFoundException
* @since 1.10
*/
protected Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
if (!StringUtils.hasText(basePackage)) {
return Collections.emptySet();
}
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet
.add(ClassUtils.forName(candidate.getBeanClassName(), MongoConfigurationSupport.class.getClassLoader()));
}
}
return initialEntitySet;
}
/**
* Configures whether to abbreviate field names for domain objects by configuring a
* {@link CamelCaseAbbreviatingFieldNamingStrategy} on the {@link MongoMappingContext} instance created. For advanced
* customization needs, consider overriding {@link #mappingMongoConverter()}.
*
* @return
*/
protected boolean abbreviateFieldNames() {
return false;
}
/**
* Configures a {@link FieldNamingStrategy} on the {@link MongoMappingContext} instance created.
*
* @return
* @since 1.5
*/
protected FieldNamingStrategy fieldNamingStrategy() {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
}

View File

@@ -32,7 +32,7 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.config.BeanComponentDefinitionBuilder;
import org.springframework.data.mongodb.core.MongoFactoryBean;
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -131,7 +131,7 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
*/
private BeanDefinition registerMongoBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoFactoryBean.class);
BeanDefinitionBuilder mongoBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoClientFactoryBean.class);
setPropertyValue(mongoBuilder, element, "host");
setPropertyValue(mongoBuilder, element, "port");

View File

@@ -21,7 +21,7 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;
import com.mongodb.BulkWriteResult;
import com.mongodb.bulk.BulkWriteResult;
/**
* Bulk operations for insert/update/remove actions on a collection. These bulks operation are available since MongoDB
@@ -38,7 +38,7 @@ public interface BulkOperations {
/**
* Mode for bulk operation.
**/
public enum BulkMode {
enum BulkMode {
/** Perform bulk operations in sequence. The first error will cancel processing. */
ORDERED,

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,12 +15,30 @@
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DBCollection;
import com.mongodb.MongoException;
import org.bson.Document;
import org.springframework.dao.DataAccessException;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
/**
* Callback interface for executing actions against a {@link MongoCollection}
*
* @author Mark Pollak
* @author Grame Rocher
* @author Oliver Gierke
* @author John Brisbin
* @auhtor Christoph Strobl
* @since 1.0
*/
public interface CollectionCallback<T> {
T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
/**
* @param collection never {@literal null}.
* @return
* @throws MongoException
* @throws DataAccessException
*/
T doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2016 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.
@@ -15,12 +15,15 @@
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DBCursor;
import org.bson.Document;
import com.mongodb.client.FindIterable;
/**
* Simple callback interface to allow customization of a {@link DBCursor}.
* Simple callback interface to allow customization of a {@link FindIterable}.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
interface CursorPreparer {
@@ -29,5 +32,5 @@ interface CursorPreparer {
*
* @param cursor
*/
DBCursor prepare(DBCursor cursor);
FindIterable<Document> prepare(FindIterable<Document> cursor);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,11 +15,16 @@
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DB;
import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
import com.mongodb.MongoException;
import com.mongodb.client.MongoDatabase;
/**
*
* @param <T>
*/
public interface DbCallback<T> {
T doInDB(DB db) throws MongoException, DataAccessException;
T doInDB(MongoDatabase db) throws MongoException, DataAccessException;
}

View File

@@ -15,9 +15,11 @@
*/
package org.springframework.data.mongodb.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bson.Document;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.query.Query;
@@ -26,18 +28,22 @@ import org.springframework.data.util.Pair;
import org.springframework.util.Assert;
import com.mongodb.BulkWriteException;
import com.mongodb.BulkWriteOperation;
import com.mongodb.BulkWriteRequestBuilder;
import com.mongodb.BulkWriteResult;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.BulkWriteOptions;
import com.mongodb.client.model.DeleteManyModel;
import com.mongodb.client.model.InsertOneModel;
import com.mongodb.client.model.UpdateManyModel;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.WriteModel;
/**
* Default implementation for {@link BulkOperations}.
*
* @author Tobias Trelle
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.9
*/
class DefaultBulkOperations implements BulkOperations {
@@ -45,13 +51,14 @@ class DefaultBulkOperations implements BulkOperations {
private final MongoOperations mongoOperations;
private final BulkMode bulkMode;
private final String collectionName;
private final Class<?> entityType;
private PersistenceExceptionTranslator exceptionTranslator;
private WriteConcernResolver writeConcernResolver;
private WriteConcern defaultWriteConcern;
private BulkWriteOperation bulk;
private BulkWriteOptions bulkOptions;
List<WriteModel<Document>> models = new ArrayList<WriteModel<Document>>();
/**
* Creates a new {@link DefaultBulkOperations} for the given {@link MongoOperations}, {@link BulkMode}, collection
@@ -72,12 +79,11 @@ class DefaultBulkOperations implements BulkOperations {
this.mongoOperations = mongoOperations;
this.bulkMode = bulkMode;
this.collectionName = collectionName;
this.entityType = entityType;
this.exceptionTranslator = new MongoExceptionTranslator();
this.writeConcernResolver = DefaultWriteConcernResolver.INSTANCE;
this.bulk = initBulkOperation();
this.bulkOptions = initBulkOperation();
}
/**
@@ -117,7 +123,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(document, "Document must not be null!");
bulk.insert((DBObject) mongoOperations.getConverter().convertToMongoType(document));
models.add(new InsertOneModel<Document>((Document) mongoOperations.getConverter().convertToMongoType(document)));
return this;
}
@@ -229,8 +235,7 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
bulk.find(query.getQueryObject()).remove();
models.add(new DeleteManyModel<Document>(query.getQueryObject()));
return this;
}
@@ -255,15 +260,16 @@ class DefaultBulkOperations implements BulkOperations {
* @see org.springframework.data.mongodb.core.BulkOperations#executeBulk()
*/
@Override
public BulkWriteResult execute() {
MongoAction action = new MongoAction(defaultWriteConcern, MongoActionOperation.BULK, collectionName, entityType,
null, null);
WriteConcern writeConcern = writeConcernResolver.resolve(action);
public com.mongodb.bulk.BulkWriteResult execute() {
try {
return writeConcern == null ? bulk.execute() : bulk.execute(writeConcern);
MongoCollection<Document> collection = mongoOperations.getCollection(collectionName);
if (defaultWriteConcern != null) {
collection = collection.withWriteConcern(defaultWriteConcern);
}
return collection.bulkWrite(models, bulkOptions);
} catch (BulkWriteException o_O) {
@@ -271,7 +277,7 @@ class DefaultBulkOperations implements BulkOperations {
throw toThrow == null ? o_O : toThrow;
} finally {
this.bulk = initBulkOperation();
this.bulkOptions = initBulkOperation();
}
}
@@ -289,39 +295,26 @@ class DefaultBulkOperations implements BulkOperations {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!");
BulkWriteRequestBuilder builder = bulk.find(query.getQueryObject());
if (upsert) {
if (multi) {
builder.upsert().update(update.getUpdateObject());
} else {
builder.upsert().updateOne(update.getUpdateObject());
}
UpdateOptions options = new UpdateOptions();
options.upsert(upsert);
if (multi) {
models.add(new UpdateManyModel<Document>(query.getQueryObject(), update.getUpdateObject(), options));
} else {
if (multi) {
builder.update(update.getUpdateObject());
} else {
builder.updateOne(update.getUpdateObject());
}
models.add(new UpdateOneModel<Document>(query.getQueryObject(), update.getUpdateObject(), options));
}
return this;
}
private final BulkWriteOperation initBulkOperation() {
DBCollection collection = mongoOperations.getCollection(collectionName);
private final BulkWriteOptions initBulkOperation() {
BulkWriteOptions options = new BulkWriteOptions();
switch (bulkMode) {
case ORDERED:
return collection.initializeOrderedBulkOperation();
return options.ordered(true);
case UNORDERED:
return collection.initializeUnorderedBulkOperation();
return options.ordered(false);
}
throw new IllegalStateException("BulkMode was null!");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@@ -15,22 +15,22 @@
*/
package org.springframework.data.mongodb.core;
import static org.springframework.data.domain.Sort.Direction.*;
import static org.springframework.data.mongodb.core.MongoTemplate.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.bson.Document;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.util.Assert;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.IndexOptions;
/**
* Default implementation of {@link IndexOperations}.
@@ -39,28 +39,25 @@ import com.mongodb.MongoException;
* @author Oliver Gierke
* @author Komi Innocent
* @author Christoph Strobl
* @author Mark Paluch
*/
public class DefaultIndexOperations implements IndexOperations {
private static final Double ONE = Double.valueOf(1);
private static final Double MINUS_ONE = Double.valueOf(-1);
private static final Collection<String> TWO_D_IDENTIFIERS = Arrays.asList("2d", "2dsphere");
private final MongoOperations mongoOperations;
private final MongoDbFactory mongoDbFactory;
private final String collectionName;
/**
* Creates a new {@link DefaultIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param mongoDbFactory must not be {@literal null}.
* @param collectionName must not be {@literal null}.
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName) {
public DefaultIndexOperations(MongoDbFactory mongoDbFactory, String collectionName) {
Assert.notNull(mongoOperations, "MongoOperations must not be null!");
Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!");
Assert.notNull(collectionName, "Collection name can not be null!");
this.mongoOperations = mongoOperations;
this.mongoDbFactory = mongoDbFactory;
this.collectionName = collectionName;
}
@@ -68,17 +65,18 @@ public class DefaultIndexOperations implements IndexOperations {
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.IndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)
*/
public void ensureIndex(final IndexDefinition indexDefinition) {
mongoOperations.execute(collectionName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
DBObject indexOptions = indexDefinition.getIndexOptions();
if (indexOptions != null) {
collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
} else {
collection.createIndex(indexDefinition.getIndexKeys());
}
return null;
public String ensureIndex(final IndexDefinition indexDefinition) {
return execute(collection -> {
Document indexOptions = indexDefinition.getIndexOptions();
if (indexOptions != null) {
IndexOptions ops = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
return collection.createIndex(indexDefinition.getIndexKeys(), ops);
}
return collection.createIndex(indexDefinition.getIndexKeys());
});
}
@@ -87,11 +85,10 @@ public class DefaultIndexOperations implements IndexOperations {
* @see org.springframework.data.mongodb.core.IndexOperations#dropIndex(java.lang.String)
*/
public void dropIndex(final String name) {
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
collection.dropIndex(name);
return null;
}
execute(collection -> {
collection.dropIndex(name);
return null;
});
}
@@ -104,80 +101,46 @@ public class DefaultIndexOperations implements IndexOperations {
dropIndex("*");
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.IndexOperations#resetIndexCache()
*/
@Deprecated
public void resetIndexCache() {
mongoOperations.execute(collectionName, new CollectionCallback<Void>() {
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
ReflectiveDBCollectionInvoker.resetIndexCache(collection);
return null;
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.IndexOperations#getIndexInfo()
*/
public List<IndexInfo> getIndexInfo() {
return mongoOperations.execute(collectionName, new CollectionCallback<List<IndexInfo>>() {
public List<IndexInfo> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
List<DBObject> dbObjectList = collection.getIndexInfo();
return getIndexData(dbObjectList);
return execute(new CollectionCallback<List<IndexInfo>>() {
public List<IndexInfo> doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {
MongoCursor<Document> cursor = collection.listIndexes(Document.class).iterator();
return getIndexData(cursor);
}
private List<IndexInfo> getIndexData(List<DBObject> dbObjectList) {
private List<IndexInfo> getIndexData(MongoCursor<Document> cursor) {
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
for (DBObject ix : dbObjectList) {
while (cursor.hasNext()) {
DBObject keyDbObject = (DBObject) ix.get("key");
int numberOfElements = keyDbObject.keySet().size();
List<IndexField> indexFields = new ArrayList<IndexField>(numberOfElements);
for (String key : keyDbObject.keySet()) {
Object value = keyDbObject.get(key);
if (TWO_D_IDENTIFIERS.contains(value)) {
indexFields.add(IndexField.geo(key));
} else if ("text".equals(value)) {
DBObject weights = (DBObject) ix.get("weights");
for (String fieldName : weights.keySet()) {
indexFields.add(IndexField.text(fieldName, Float.valueOf(weights.get(fieldName).toString())));
}
} else {
Double keyValue = new Double(value.toString());
if (ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, ASC));
} else if (MINUS_ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, DESC));
}
}
}
String name = ix.get("name").toString();
boolean unique = ix.containsField("unique") ? (Boolean) ix.get("unique") : false;
boolean dropDuplicates = ix.containsField("dropDups") ? (Boolean) ix.get("dropDups") : false;
boolean sparse = ix.containsField("sparse") ? (Boolean) ix.get("sparse") : false;
String language = ix.containsField("default_language") ? (String) ix.get("default_language") : "";
indexInfoList.add(new IndexInfo(indexFields, name, unique, dropDuplicates, sparse, language));
Document ix = cursor.next();
IndexInfo indexInfo = IndexConverters.documentToIndexInfoConverter().convert(ix);
indexInfoList.add(indexInfo);
}
return indexInfoList;
}
});
}
public <T> T execute(CollectionCallback<T> callback) {
Assert.notNull(callback);
try {
MongoCollection<Document> collection = mongoDbFactory.getDb().getCollection(collectionName);
return callback.doInCollection(collection);
} catch (RuntimeException e) {
throw potentiallyConvertRuntimeException(e, mongoDbFactory.getExceptionTranslator());
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.data.mongodb.MongoDbFactory;
/**
* {@link IndexOperationsProvider} to obtain {@link IndexOperations} from a given {@link MongoDbFactory}. TODO: Review
* me
*
* @author Mark Paluch
* @since 2.0
*/
class DefaultIndexOperationsProvider implements IndexOperationsProvider {
private final MongoDbFactory mongoDbFactory;
/**
* @param mongoDbFactory must not be {@literal null}.
*/
DefaultIndexOperationsProvider(MongoDbFactory mongoDbFactory) {
this.mongoDbFactory = mongoDbFactory;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.IndexOperationsProvider#reactiveIndexOps(java.lang.String)
*/
@Override
public IndexOperations indexOps(String collectionName) {
return new DefaultIndexOperations(mongoDbFactory, collectionName);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.bson.Document;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.util.Assert;
import com.mongodb.reactivestreams.client.ListIndexesPublisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Default implementation of {@link IndexOperations}.
*
* @author Mark Paluch
* @since 1.11
*/
public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
private final ReactiveMongoOperations mongoOperations;
private final String collectionName;
/**
* Creates a new {@link DefaultReactiveIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null}.
*/
public DefaultReactiveIndexOperations(ReactiveMongoOperations mongoOperations, String collectionName) {
Assert.notNull(mongoOperations, "ReactiveMongoOperations must not be null!");
Assert.notNull(collectionName, "Collection must not be null!");
this.mongoOperations = mongoOperations;
this.collectionName = collectionName;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveIndexOperations#ensureIndex(org.springframework.data.mongodb.core.index.IndexDefinition)
*/
public Mono<String> ensureIndex(final IndexDefinition indexDefinition) {
return mongoOperations.execute(collectionName, (ReactiveCollectionCallback<String>) collection -> {
Document indexOptions = indexDefinition.getIndexOptions();
if (indexOptions != null) {
return collection.createIndex(indexDefinition.getIndexKeys(),
IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition));
}
return collection.createIndex(indexDefinition.getIndexKeys());
}).next();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveIndexOperations#dropIndex(java.lang.String)
*/
public Mono<Void> dropIndex(final String name) {
return mongoOperations.execute(collectionName, collection -> {
return Mono.from(collection.dropIndex(name));
}).flatMap(success -> Mono.<Void>empty()).next();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveIndexOperations#dropAllIndexes()
*/
public Mono<Void> dropAllIndexes() {
return dropIndex("*");
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveIndexOperations#getIndexInfo()
*/
public Flux<IndexInfo> getIndexInfo() {
return mongoOperations.execute(collectionName, collection -> {
ListIndexesPublisher<Document> indexesPublisher = collection.listIndexes(Document.class);
return Flux.from(indexesPublisher).map(IndexConverters.documentToIndexInfoConverter()::convert);
});
}
}

View File

@@ -20,11 +20,13 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.dao.DataAccessException;
import org.springframework.data.mongodb.core.script.ExecutableMongoScript;
@@ -34,8 +36,9 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.mongodb.DB;
import com.mongodb.BasicDBList;
import com.mongodb.MongoException;
import com.mongodb.client.MongoDatabase;
/**
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
@@ -97,8 +100,13 @@ class DefaultScriptOperations implements ScriptOperations {
return mongoOperations.execute(new DbCallback<Object>() {
@Override
public Object doInDB(DB db) throws MongoException, DataAccessException {
return db.eval(script.getCode(), convertScriptArgs(false, args));
public Object doInDB(MongoDatabase db) throws MongoException, DataAccessException {
Document command = new Document("$eval", script.getCode());
BasicDBList commandArgs = new BasicDBList();
commandArgs.addAll(Arrays.asList(convertScriptArgs(false, args)));
command.append("args", commandArgs);
return db.runCommand(command).get("retval");
}
});
}
@@ -115,8 +123,10 @@ class DefaultScriptOperations implements ScriptOperations {
return mongoOperations.execute(new DbCallback<Object>() {
@Override
public Object doInDB(DB db) throws MongoException, DataAccessException {
return db.eval(String.format("%s(%s)", scriptName, convertAndJoinScriptArgs(args)));
public Object doInDB(MongoDatabase db) throws MongoException, DataAccessException {
return db.runCommand(new Document("eval", String.format("%s(%s)", scriptName, convertAndJoinScriptArgs(args))))
.get("retval");
}
});
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2011 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,24 +15,26 @@
*/
package org.springframework.data.mongodb.core;
import org.bson.Document;
import org.springframework.dao.DataAccessException;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
/**
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
* about exception handling. {@MongoException}s will be caught and translated by the calling
* MongoTemplate
*
* An DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later
* for later inspection.
* about exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate An
* DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for
* later inspection.
*
* @author Mark Pollack
*
* @author Grame Rocher
* @author Oliver Gierke
* @author John Brisbin
* @author Christoph Strobl
* @since 1.0
*/
public interface DocumentCallbackHandler {
void processDocument(DBObject dbObject) throws MongoException, DataAccessException;
void processDocument(Document document) throws MongoException, DataAccessException;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import com.mongodb.DBCursor;
import com.mongodb.reactivestreams.client.FindPublisher;
/**
* Simple callback interface to allow customization of a {@link FindPublisher}.
*
* @author Mark Paluch
*/
interface FindPublisherPreparer {
/**
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
*
* @param cursor
*/
<T> FindPublisher<T> prepare(FindPublisher<T> findPublisher);
}

View File

@@ -15,29 +15,29 @@
*/
package org.springframework.data.mongodb.core;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Value object to mitigate different representations of geo command execution results in MongoDB.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @soundtrack Fruitcake - Jeff Coffin (The Inside of the Outside)
* @since 1.9
*/
class GeoCommandStatistics {
private static final GeoCommandStatistics NONE = new GeoCommandStatistics(new BasicDBObject());
private static final GeoCommandStatistics NONE = new GeoCommandStatistics(new Document());
private final DBObject source;
private final Document source;
/**
* Creates a new {@link GeoCommandStatistics} instance with the given source document.
*
* @param source must not be {@literal null}.
*/
private GeoCommandStatistics(DBObject source) {
private GeoCommandStatistics(Document source) {
Assert.notNull(source, "Source document must not be null!");
this.source = source;
@@ -49,12 +49,12 @@ class GeoCommandStatistics {
* @param commandResult must not be {@literal null}.
* @return
*/
public static GeoCommandStatistics from(DBObject commandResult) {
public static GeoCommandStatistics from(Document commandResult) {
Assert.notNull(commandResult, "Command result must not be null!");
Object stats = commandResult.get("stats");
return stats == null ? NONE : new GeoCommandStatistics((DBObject) stats);
return stats == null ? NONE : new GeoCommandStatistics((Document) stats);
}
/**

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import static org.springframework.data.domain.Sort.Direction.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.util.ObjectUtils;
import com.mongodb.client.model.IndexOptions;
/**
* {@link Converter Converters} for index-related MongoDB documents/types.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
abstract class IndexConverters {
private static final Converter<IndexDefinition, IndexOptions> DEFINITION_TO_MONGO_INDEX_OPTIONS;
private static final Converter<Document, IndexInfo> DOCUMENT_INDEX_INFO;
private static final Double ONE = Double.valueOf(1);
private static final Double MINUS_ONE = Double.valueOf(-1);
private static final Collection<String> TWO_D_IDENTIFIERS = Arrays.asList("2d", "2dsphere");
static {
DEFINITION_TO_MONGO_INDEX_OPTIONS = getIndexDefinitionIndexOptionsConverter();
DOCUMENT_INDEX_INFO = getDocumentIndexInfoConverter();
}
private IndexConverters() {
}
static Converter<IndexDefinition, IndexOptions> indexDefinitionToIndexOptionsConverter() {
return DEFINITION_TO_MONGO_INDEX_OPTIONS;
}
static Converter<Document, IndexInfo> documentToIndexInfoConverter() {
return DOCUMENT_INDEX_INFO;
}
private static Converter<IndexDefinition, IndexOptions> getIndexDefinitionIndexOptionsConverter() {
return indexDefinition -> {
Document indexOptions = indexDefinition.getIndexOptions();
IndexOptions ops = new IndexOptions();
if (indexOptions.containsKey("name")) {
ops = ops.name(indexOptions.get("name").toString());
}
if (indexOptions.containsKey("unique")) {
ops = ops.unique((Boolean) indexOptions.get("unique"));
}
if (indexOptions.containsKey("sparse")) {
ops = ops.sparse((Boolean) indexOptions.get("sparse"));
}
if (indexOptions.containsKey("background")) {
ops = ops.background((Boolean) indexOptions.get("background"));
}
if (indexOptions.containsKey("expireAfterSeconds")) {
ops = ops.expireAfter((Long) indexOptions.get("expireAfterSeconds"), TimeUnit.SECONDS);
}
if (indexOptions.containsKey("min")) {
ops = ops.min(((Number) indexOptions.get("min")).doubleValue());
}
if (indexOptions.containsKey("max")) {
ops = ops.max(((Number) indexOptions.get("max")).doubleValue());
}
if (indexOptions.containsKey("bits")) {
ops = ops.bits((Integer) indexOptions.get("bits"));
}
if (indexOptions.containsKey("bucketSize")) {
ops = ops.bucketSize(((Number) indexOptions.get("bucketSize")).doubleValue());
}
if (indexOptions.containsKey("default_language")) {
ops = ops.defaultLanguage(indexOptions.get("default_language").toString());
}
if (indexOptions.containsKey("language_override")) {
ops = ops.languageOverride(indexOptions.get("language_override").toString());
}
if (indexOptions.containsKey("weights")) {
ops = ops.weights((org.bson.Document) indexOptions.get("weights"));
}
for (String key : indexOptions.keySet()) {
if (ObjectUtils.nullSafeEquals("2dsphere", indexOptions.get(key))) {
ops = ops.sphereVersion(2);
}
}
return ops;
};
}
private static Converter<Document, IndexInfo> getDocumentIndexInfoConverter() {
return ix -> {
Document keyDocument = (Document) ix.get("key");
int numberOfElements = keyDocument.keySet().size();
List<IndexField> indexFields = new ArrayList<IndexField>(numberOfElements);
for (String key : keyDocument.keySet()) {
Object value = keyDocument.get(key);
if (TWO_D_IDENTIFIERS.contains(value)) {
indexFields.add(IndexField.geo(key));
} else if ("text".equals(value)) {
Document weights = (Document) ix.get("weights");
for (String fieldName : weights.keySet()) {
indexFields.add(IndexField.text(fieldName, Float.valueOf(weights.get(fieldName).toString())));
}
} else {
Double keyValue = new Double(value.toString());
if (ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, ASC));
} else if (MINUS_ONE.equals(keyValue)) {
indexFields.add(IndexField.create(key, DESC));
}
}
}
String name = ix.get("name").toString();
boolean unique = ix.containsKey("unique") ? (Boolean) ix.get("unique") : false;
boolean sparse = ix.containsKey("sparse") ? (Boolean) ix.get("sparse") : false;
String language = ix.containsKey("default_language") ? (String) ix.get("default_language") : "";
return new IndexInfo(indexFields, name, unique, sparse, language);
};
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@@ -35,7 +35,7 @@ public interface IndexOperations {
*
* @param indexDefinition must not be {@literal null}.
*/
void ensureIndex(IndexDefinition indexDefinition);
String ensureIndex(IndexDefinition indexDefinition);
/**
* Drops an index from this collection.
@@ -49,15 +49,6 @@ public interface IndexOperations {
*/
void dropAllIndexes();
/**
* Clears all indices that have not yet been applied to this collection.
*
* @deprecated since 1.7. The MongoDB Java driver version 3.0 does no longer support reseting the index cache.
* @throws {@link UnsupportedOperationException} when used with MongoDB Java driver version 3.0.
*/
@Deprecated
void resetIndexCache();
/**
* Returns the index information on the collection.
*

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2016. 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import java.util.List;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.util.Assert;
/**
* Adapter for creating synchronous {@link IndexOperations}.
*
* @author Christoph Strobl
* @since 2.0
*/
public interface IndexOperationsAdapter extends IndexOperations {
/**
* Obtain a blocking variant of {@link IndexOperations} wrapping {@link ReactiveIndexOperations}.
*
* @param reactiveIndexOperations must not be {@literal null}.
* @return never {@literal null}
*/
static IndexOperationsAdapter blocking(ReactiveIndexOperations reactiveIndexOperations) {
Assert.notNull(reactiveIndexOperations, "ReactiveIndexOperations must not be null!");
return new IndexOperationsAdapter() {
@Override
public String ensureIndex(IndexDefinition indexDefinition) {
return reactiveIndexOperations.ensureIndex(indexDefinition).block();
}
@Override
public void dropIndex(String name) {
reactiveIndexOperations.dropIndex(name).block();
}
@Override
public void dropAllIndexes() {
reactiveIndexOperations.dropAllIndexes().block();
}
@Override
public List<IndexInfo> getIndexInfo() {
return reactiveIndexOperations.getIndexInfo().collectList().block();
}
};
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
/**
* TODO: Revisit for a better pattern.
* @author Mark Paluch
* @since 2.0
*/
public interface IndexOperationsProvider {
/**
* Returns the operations that can be performed on indexes
*
* @return index operations on the named collection
*/
IndexOperations indexOps(String collectionName);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2012 the original author or authors.
* Copyright 2011-2016 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.
@@ -15,9 +15,9 @@
*/
package org.springframework.data.mongodb.core;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
/**
@@ -31,6 +31,7 @@ import com.mongodb.WriteConcern;
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class MongoAction {
@@ -38,8 +39,8 @@ public class MongoAction {
private final WriteConcern defaultWriteConcern;
private final Class<?> entityType;
private final MongoActionOperation mongoActionOperation;
private final DBObject query;
private final DBObject document;
private final Document query;
private final Document document;
/**
* Create an instance of a {@link MongoAction}.
@@ -48,11 +49,11 @@ public class MongoAction {
* @param mongoActionOperation action being taken against the collection
* @param collectionName the collection name, must not be {@literal null} or empty.
* @param entityType the POJO that is being operated against
* @param document the converted DBObject from the POJO or Spring Update object
* @param query the converted DBObject from the Spring Query object
* @param document the converted Document from the POJO or Spring Update object
* @param query the converted Document from the Spring Query object
*/
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation,
String collectionName, Class<?> entityType, DBObject document, DBObject query) {
public MongoAction(WriteConcern defaultWriteConcern, MongoActionOperation mongoActionOperation, String collectionName,
Class<?> entityType, Document document, Document query) {
Assert.hasText(collectionName, "Collection name must not be null or empty!");
@@ -72,14 +73,6 @@ public class MongoAction {
return defaultWriteConcern;
}
/**
* @deprecated use {@link #getEntityType()} instead.
*/
@Deprecated
public Class<?> getEntityClass() {
return entityType;
}
public Class<?> getEntityType() {
return entityType;
}
@@ -88,11 +81,11 @@ public class MongoAction {
return mongoActionOperation;
}
public DBObject getQuery() {
public Document getQuery() {
return query;
}
public DBObject getDocument() {
public Document getDocument() {
return document;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-2016 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.
@@ -19,6 +19,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.bson.BsonInvalidOperationException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
@@ -33,7 +34,10 @@ import org.springframework.data.mongodb.util.MongoDbErrorCodes;
import org.springframework.util.ClassUtils;
import com.mongodb.BulkWriteException;
import com.mongodb.MongoBulkWriteException;
import com.mongodb.MongoException;
import com.mongodb.MongoServerException;
import com.mongodb.bulk.BulkWriteError;
/**
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
@@ -57,7 +61,7 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
Arrays.asList("MongoInternalException"));
private static final Set<String> DATA_INTEGRETY_EXCEPTIONS = new HashSet<String>(
Arrays.asList("WriteConcernException"));
Arrays.asList("WriteConcernException", "MongoWriteException", "MongoBulkWriteException"));
/*
* (non-Javadoc)
@@ -67,6 +71,10 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
// Check for well-known MongoException subclasses.
if (ex instanceof BsonInvalidOperationException) {
throw new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
}
String exception = ClassUtils.getShortName(ClassUtils.getUserClass(ex.getClass()));
if (DULICATE_KEY_EXCEPTIONS.contains(exception)) {
@@ -82,6 +90,20 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
}
if (DATA_INTEGRETY_EXCEPTIONS.contains(exception)) {
if (ex instanceof MongoServerException) {
if (((MongoServerException) ex).getCode() == 11000) {
return new DuplicateKeyException(ex.getMessage(), ex);
}
if (ex instanceof MongoBulkWriteException) {
for (BulkWriteError x : ((MongoBulkWriteException) ex).getWriteErrors()) {
if (x.getCode() == 11000) {
return new DuplicateKeyException(ex.getMessage(), ex);
}
}
}
}
return new DataIntegrityViolationException(ex.getMessage(), ex);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@@ -19,6 +19,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.bson.Document;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
@@ -36,13 +37,12 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.CloseableIterator;
import com.mongodb.CommandResult;
import com.mongodb.Cursor;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.ReadPreference;
import com.mongodb.WriteResult;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
/**
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
@@ -69,12 +69,12 @@ public interface MongoOperations {
/**
* Execute the a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
* MongoDB driver to convert the JSON string to a DBObject. Any errors that result from executing this command will be
* MongoDB driver to convert the JSON string to a Document. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
* @param jsonCommand a MongoDB command expressed as a JSON string.
*/
CommandResult executeCommand(String jsonCommand);
Document executeCommand(String jsonCommand);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
@@ -82,19 +82,7 @@ public interface MongoOperations {
*
* @param command a MongoDB command
*/
CommandResult executeCommand(DBObject command);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
* @param command a MongoDB command
* @param options query options to use
* @deprecated since 1.7. Please use {@link #executeCommand(DBObject, ReadPreference)}, as the MongoDB Java driver
* version 3 no longer supports this operation.
*/
@Deprecated
CommandResult executeCommand(DBObject command, int options);
Document executeCommand(Document command);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's data
@@ -105,7 +93,7 @@ public interface MongoOperations {
* @return
* @since 1.7
*/
CommandResult executeCommand(DBObject command, ReadPreference readPreference);
Document executeCommand(Document command, ReadPreference readPreference);
/**
* Execute a MongoDB query and iterate over the query results on a per-document basis with a DocumentCallbackHandler.
@@ -152,22 +140,6 @@ public interface MongoOperations {
*/
<T> T execute(String collectionName, CollectionCallback<T> action);
/**
* Executes the given {@link DbCallback} within the same connection to the database so as to ensure consistency in a
* write heavy environment where you may read the data that you wrote. See the comments on {@see <a
* href=http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency>Java Driver Concurrency</a>}
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param action callback that specified the MongoDB actions to perform on the DB instance
* @return a result object returned by the action or <tt>null</tt>
* @deprecated since 1.7 as the MongoDB Java driver version 3 does not longer support request boundaries via
* {@link DB#requestStart()} and {@link DB#requestDone()}.
*/
@Deprecated
<T> T executeInSession(DbCallback<T> action);
/**
* Executes the given {@link Query} on the entity collection of the specified {@code entityType} backed by a Mongo DB
* {@link Cursor}.
@@ -203,7 +175,7 @@ public interface MongoOperations {
* @param entityClass class that determines the collection to create
* @return the created collection
*/
<T> DBCollection createCollection(Class<T> entityClass);
<T> MongoCollection<Document> createCollection(Class<T> entityClass);
/**
* Create a collection with a name based on the provided entity class using the options.
@@ -212,7 +184,7 @@ public interface MongoOperations {
* @param collectionOptions options to use when creating the collection.
* @return the created collection
*/
<T> DBCollection createCollection(Class<T> entityClass, CollectionOptions collectionOptions);
<T> MongoCollection<Document> createCollection(Class<T> entityClass, CollectionOptions collectionOptions);
/**
* Create an uncapped collection with the provided name.
@@ -220,7 +192,7 @@ public interface MongoOperations {
* @param collectionName name of the collection
* @return the created collection
*/
DBCollection createCollection(String collectionName);
MongoCollection<Document> createCollection(String collectionName);
/**
* Create a collection with the provided name and options.
@@ -229,7 +201,7 @@ public interface MongoOperations {
* @param collectionOptions options to use when creating the collection.
* @return the created collection
*/
DBCollection createCollection(String collectionName, CollectionOptions collectionOptions);
MongoCollection<Document> createCollection(String collectionName, CollectionOptions collectionOptions);
/**
* A set of collection names.
@@ -246,7 +218,7 @@ public interface MongoOperations {
* @param collectionName name of the collection
* @return an existing collection or a newly created one.
*/
DBCollection getCollection(String collectionName);
MongoCollection<Document> getCollection(String collectionName);
/**
* Check to see if a collection with a name indicated by the entity class exists.
@@ -864,7 +836,7 @@ public interface MongoOperations {
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult upsert(Query query, Update update, Class<?> entityClass);
UpdateResult upsert(Query query, Update update, Class<?> entityClass);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
@@ -876,7 +848,7 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult upsert(Query query, Update update, String collectionName);
UpdateResult upsert(Query query, Update update, String collectionName);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
@@ -888,7 +860,7 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult upsert(Query query, Update update, Class<?> entityClass, String collectionName);
UpdateResult upsert(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates the first object that is found in the collection of the entity class that matches the query document with
@@ -900,7 +872,7 @@ public interface MongoOperations {
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateFirst(Query query, Update update, Class<?> entityClass);
UpdateResult updateFirst(Query query, Update update, Class<?> entityClass);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
@@ -912,7 +884,7 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateFirst(Query query, Update update, String collectionName);
UpdateResult updateFirst(Query query, Update update, String collectionName);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
@@ -925,7 +897,7 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
UpdateResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -937,7 +909,7 @@ public interface MongoOperations {
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateMulti(Query query, Update update, Class<?> entityClass);
UpdateResult updateMulti(Query query, Update update, Class<?> entityClass);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
@@ -949,7 +921,7 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateMulti(Query query, Update update, String collectionName);
UpdateResult updateMulti(Query query, Update update, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -962,14 +934,14 @@ public interface MongoOperations {
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
WriteResult updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName);
UpdateResult updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName);
/**
* Remove the given object from the collection by id.
*
* @param object
*/
WriteResult remove(Object object);
DeleteResult remove(Object object);
/**
* Removes the given object from the given collection.
@@ -977,7 +949,7 @@ public interface MongoOperations {
* @param object
* @param collection must not be {@literal null} or empty.
*/
WriteResult remove(Object object, String collection);
DeleteResult remove(Object object, String collection);
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
@@ -986,7 +958,7 @@ public interface MongoOperations {
* @param query
* @param entityClass
*/
WriteResult remove(Query query, Class<?> entityClass);
DeleteResult remove(Query query, Class<?> entityClass);
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
@@ -996,7 +968,7 @@ public interface MongoOperations {
* @param entityClass
* @param collectionName
*/
WriteResult remove(Query query, Class<?> entityClass, String collectionName);
DeleteResult remove(Query query, Class<?> entityClass, String collectionName);
/**
* Remove all documents from the specified collection that match the provided query document criteria. There is no
@@ -1005,7 +977,7 @@ public interface MongoOperations {
* @param query the query document that specifies the criteria used to remove a record
* @param collectionName name of the collection where the objects will removed
*/
WriteResult remove(Query query, String collectionName);
DeleteResult remove(Query query, String collectionName);
/**
* Returns and removes all documents form the specified collection that match the provided query.

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.dao.DataAccessException;
import com.mongodb.MongoException;
import com.mongodb.reactivestreams.client.MongoCollection;
import org.bson.Document;
import org.reactivestreams.Publisher;
/**
* @author Mark Paluch
* @param <T>
* @since 2.0
*/
public interface ReactiveCollectionCallback<T> {
Publisher<T> doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.dao.DataAccessException;
import com.mongodb.MongoException;
import com.mongodb.reactivestreams.client.MongoDatabase;
import org.reactivestreams.Publisher;
/**
* @author Mark Paluch
* @param <T>
* @since 2.0
*/
public interface ReactiveDatabaseCallback<T> {
Publisher<T> doInDB(MongoDatabase db) throws MongoException, DataAccessException;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import java.util.List;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexInfo;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Index operations on a collection.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public interface ReactiveIndexOperations {
/**
* Ensure that an index for the provided {@link IndexDefinition} exists for the collection indicated by the entity
* class. If not it will be created.
*
* @param indexDefinition must not be {@literal null}.
*/
Mono<String> ensureIndex(IndexDefinition indexDefinition);
/**
* Drops an index from this collection.
*
* @param name name of index to drop
*/
Mono<Void> dropIndex(String name);
/**
* Drops all indices from this collection.
*/
Mono<Void> dropAllIndexes();
/**
* Returns the index information on the collection.
*
* @return index information on the collection
*/
Flux<IndexInfo> getIndexInfo();
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.util.StringUtils;
import com.mongodb.async.client.MongoClientSettings;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
/**
* Convenient factory for configuring a reactive streams {@link MongoClient}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public class ReactiveMongoClientFactoryBean extends AbstractFactoryBean<MongoClient>
implements PersistenceExceptionTranslator {
private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator();
private String connectionString;
private String host;
private Integer port;
private MongoClientSettings mongoClientSettings;
private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_EXCEPTION_TRANSLATOR;
/**
* Configures the host to connect to.
*
* @param host
*/
public void setHost(String host) {
this.host = host;
}
/**
* Configures the port to connect to.
*
* @param port
*/
public void setPort(int port) {
this.port = port;
}
/**
* Configures the connection string.
*
* @param connectionString
*/
public void setConnectionString(String connectionString) {
this.connectionString = connectionString;
}
/**
* Configures the mongo client settings.
*
* @param mongoClientSettings
*/
public void setMongoClientSettings(MongoClientSettings mongoClientSettings) {
this.mongoClientSettings = mongoClientSettings;
}
/**
* Configures the {@link PersistenceExceptionTranslator} to use.
*
* @param exceptionTranslator
*/
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator == null ? DEFAULT_EXCEPTION_TRANSLATOR : exceptionTranslator;
}
@Override
public Class<?> getObjectType() {
return MongoClient.class;
}
@Override
protected MongoClient createInstance() throws Exception {
if (mongoClientSettings != null) {
return MongoClients.create(mongoClientSettings);
}
if (StringUtils.hasText(connectionString)) {
return MongoClients.create(connectionString);
}
if (StringUtils.hasText(host)) {
if (port != null) {
return MongoClients.create(String.format("mongodb://%s:%d", host, port));
}
return MongoClients.create(String.format("mongodb://%s", host));
}
throw new IllegalStateException(
"Cannot create MongoClients. One of the following is required: mongoClientSettings, connectionString or host/port");
}
@Override
protected void destroyInstance(MongoClient instance) throws Exception {
instance.close();
}
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import java.util.ArrayList;
import java.util.List;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.util.Assert;
import com.mongodb.MongoCredential;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
import com.mongodb.async.client.MongoClientSettings;
import com.mongodb.connection.ClusterSettings;
import com.mongodb.connection.ConnectionPoolSettings;
import com.mongodb.connection.ServerSettings;
import com.mongodb.connection.SocketSettings;
import com.mongodb.connection.SslSettings;
import com.mongodb.connection.StreamFactoryFactory;
/**
* A factory bean for construction of a {@link MongoClientSettings} instance to be used with the async MongoDB driver.
*
* @author Mark Paluch
* @since 2.0
*/
public class ReactiveMongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoClientSettings> {
private static final MongoClientSettings DEFAULT_MONGO_SETTINGS = MongoClientSettings.builder().build();
private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference();
private WriteConcern writeConcern = DEFAULT_MONGO_SETTINGS.getWriteConcern();
private ReadConcern readConcern = DEFAULT_MONGO_SETTINGS.getReadConcern();
private List<MongoCredential> credentialList = new ArrayList<>();
private StreamFactoryFactory streamFactoryFactory = DEFAULT_MONGO_SETTINGS.getStreamFactoryFactory();
private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry();
private ClusterSettings clusterSettings = DEFAULT_MONGO_SETTINGS.getClusterSettings();
private SocketSettings socketSettings = DEFAULT_MONGO_SETTINGS.getSocketSettings();
private SocketSettings heartbeatSocketSettings = DEFAULT_MONGO_SETTINGS.getHeartbeatSocketSettings();
private ConnectionPoolSettings connectionPoolSettings = DEFAULT_MONGO_SETTINGS.getConnectionPoolSettings();
private ServerSettings serverSettings = DEFAULT_MONGO_SETTINGS.getServerSettings();
private SslSettings sslSettings = DEFAULT_MONGO_SETTINGS.getSslSettings();
/**
* Set the {@link ReadPreference}.
*
* @param readPreference
*/
public void setReadPreference(ReadPreference readPreference) {
this.readPreference = readPreference;
}
/**
* Set the {@link WriteConcern}.
*
* @param writeConcern
*/
public void setWriteConcern(WriteConcern writeConcern) {
this.writeConcern = writeConcern;
}
/**
* Set the {@link ReadConcern}.
*
* @param readConcern
*/
public void setReadConcern(ReadConcern readConcern) {
this.readConcern = readConcern;
}
/**
* Set the List of {@link MongoCredential}s.
*
* @param credentialList must not be {@literal null}.
*/
public void setCredentialList(List<MongoCredential> credentialList) {
Assert.notNull(credentialList, "CredendialList must not be null!");
this.credentialList.addAll(credentialList);
}
/**
* Adds the {@link MongoCredential} to the list of credentials.
*
* @param mongoCredential must not be {@literal null}.
*/
public void addMongoCredential(MongoCredential mongoCredential) {
Assert.notNull(mongoCredential, "MongoCredential must not be null!");
this.credentialList.add(mongoCredential);
}
/**
* Set the {@link StreamFactoryFactory}.
*
* @param streamFactoryFactory
*/
public void setStreamFactoryFactory(StreamFactoryFactory streamFactoryFactory) {
this.streamFactoryFactory = streamFactoryFactory;
}
/**
* Set the {@link CodecRegistry}.
*
* @param codecRegistry
*/
public void setCodecRegistry(CodecRegistry codecRegistry) {
this.codecRegistry = codecRegistry;
}
/**
* Set the {@link ClusterSettings}.
*
* @param clusterSettings
*/
public void setClusterSettings(ClusterSettings clusterSettings) {
this.clusterSettings = clusterSettings;
}
/**
* Set the {@link SocketSettings}.
*
* @param socketSettings
*/
public void setSocketSettings(SocketSettings socketSettings) {
this.socketSettings = socketSettings;
}
/**
* Set the heartbeat {@link SocketSettings}.
*
* @param heartbeatSocketSettings
*/
public void setHeartbeatSocketSettings(SocketSettings heartbeatSocketSettings) {
this.heartbeatSocketSettings = heartbeatSocketSettings;
}
/**
* Set the {@link ConnectionPoolSettings}.
*
* @param connectionPoolSettings
*/
public void setConnectionPoolSettings(ConnectionPoolSettings connectionPoolSettings) {
this.connectionPoolSettings = connectionPoolSettings;
}
/**
* Set the {@link ServerSettings}.
*
* @param serverSettings
*/
public void setServerSettings(ServerSettings serverSettings) {
this.serverSettings = serverSettings;
}
/**
* Set the {@link SslSettings}.
*
* @param sslSettings
*/
public void setSslSettings(SslSettings sslSettings) {
this.sslSettings = sslSettings;
}
@Override
public Class<?> getObjectType() {
return MongoClientSettings.class;
}
@Override
protected MongoClientSettings createInstance() throws Exception {
return MongoClientSettings.builder() //
.readPreference(readPreference) //
.writeConcern(writeConcern) //
.readConcern(readConcern) //
.credentialList(credentialList) //
.streamFactoryFactory(streamFactoryFactory) //
.codecRegistry(codecRegistry) //
.clusterSettings(clusterSettings) //
.socketSettings(socketSettings) //
.heartbeatSocketSettings(heartbeatSocketSettings) //
.connectionPoolSettings(connectionPoolSettings) //
.serverSettings(serverSettings) //
.sslSettings(sslSettings) //
.build();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoDatabase;
/**
* Helper class featuring helper methods for internal MongoDb classes. Mainly intended for internal use within the
* framework.
*
* @author Mark Paluch
* @author Christoph Strobl
* @since 2.0
*/
public abstract class ReactiveMongoDbUtils {
/**
* Private constructor to prevent instantiation.
*/
private ReactiveMongoDbUtils() {}
/**
* Obtains a {@link MongoDatabase} connection for the given {@link MongoClient} instance and database name
*
* @param mongo the {@link MongoClient} instance, must not be {@literal null}.
* @param databaseName the database name, must not be {@literal null} or empty.
* @return the {@link MongoDatabase} connection
*/
public static MongoDatabase getMongoDatabase(MongoClient mongo, String databaseName) {
return doGetMongoDatabase(mongo, databaseName, true);
}
private static MongoDatabase doGetMongoDatabase(MongoClient mongo, String databaseName, boolean allowCreate) {
return mongo.getDatabase(databaseName);
}
}

View File

@@ -0,0 +1,945 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import java.util.Collection;
import org.bson.Document;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscription;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import com.mongodb.ReadPreference;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.reactivestreams.client.MongoCollection;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Interface that specifies a basic set of MongoDB operations executed in a reactive way.
* <p>
* Implemented by {@link ReactiveMongoTemplate}. Not often used but a useful option for extensibility and testability
* (as it can be easily mocked, stubbed, or be the target of a JDK proxy). Command execution using
* {@link ReactiveMongoOperations} is deferred until subscriber subscribes to the {@link Publisher}.
*
* @author Mark Paluch
* @author Christoph Strobl
* @see Flux
* @see Mono
* @see http://projectreactor.io/docs/
* @since 2.0
*/
public interface ReactiveMongoOperations {
/**
* Returns the reactive operations that can be performed on indexes
*
* @return index operations on the named collection
*/
ReactiveIndexOperations indexOps(String collectionName);
/**
* Returns the reactive operations that can be performed on indexes
*
* @return index operations on the named collection associated with the given entity class
*/
ReactiveIndexOperations indexOps(Class<?> entityClass);
/**
* Execute the a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
* MongoDB driver to convert the JSON string to a DBObject. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
* @param jsonCommand a MongoDB command expressed as a JSON string.
* @return a result object returned by the action
*/
Mono<Document> executeCommand(String jsonCommand);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's DAO
* exception hierarchy.
*
* @param command a MongoDB command
* @return a result object returned by the action
*/
Mono<Document> executeCommand(Document command);
/**
* Execute a MongoDB command. Any errors that result from executing this command will be converted into Spring's data
* access exception hierarchy.
*
* @param command a MongoDB command, must not be {@literal null}.
* @param readPreference read preferences to use, can be {@literal null}.
* @return a result object returned by the action
*/
Mono<Document> executeCommand(Document command, ReadPreference readPreference);
/**
* Executes a {@link ReactiveDatabaseCallback} translating any exceptions as necessary.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance.
* @return a result object returned by the action
*/
<T> Flux<T> execute(ReactiveDatabaseCallback<T> action);
/**
* Executes the given {@link ReactiveCollectionCallback} on the entity collection of the specified class.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param entityClass class that determines the collection to use
* @param <T> return type
* @param action callback object that specifies the MongoDB action
* @return a result object returned by the action or <tt>null</tt>
*/
<T> Flux<T> execute(Class<?> entityClass, ReactiveCollectionCallback<T> action);
/**
* Executes the given {@link ReactiveCollectionCallback} on the collection of the given name.
* <p/>
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param <T> return type
* @param collectionName the name of the collection that specifies which DBCollection instance will be passed into
* @param action callback object that specifies the MongoDB action the callback action.
* @return a result object returned by the action or <tt>null</tt>
*/
<T> Flux<T> execute(String collectionName, ReactiveCollectionCallback<T> action);
/**
* Create an uncapped collection with a name based on the provided entity class.
*
* @param entityClass class that determines the collection to create
* @return the created collection
*/
<T> Mono<MongoCollection<Document>> createCollection(Class<T> entityClass);
/**
* Create a collection with a name based on the provided entity class using the options.
*
* @param entityClass class that determines the collection to create
* @param collectionOptions options to use when creating the collection.
* @return the created collection
*/
<T> Mono<MongoCollection<Document>> createCollection(Class<T> entityClass, CollectionOptions collectionOptions);
/**
* Create an uncapped collection with the provided name.
*
* @param collectionName name of the collection
* @return the created collection
*/
Mono<MongoCollection<Document>> createCollection(String collectionName);
/**
* Create a collection with the provided name and options.
*
* @param collectionName name of the collection
* @param collectionOptions options to use when creating the collection.
* @return the created collection
*/
Mono<MongoCollection<Document>> createCollection(String collectionName, CollectionOptions collectionOptions);
/**
* A set of collection names.
*
* @return Flux of collection names
*/
Flux<String> getCollectionNames();
/**
* Get a collection by name, creating it if it doesn't exist.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection
* @return an existing collection or a newly created one.
*/
MongoCollection<Document> getCollection(String collectionName);
/**
* Check to see if a collection with a name indicated by the entity class exists.
* <p/>
* Translate any exceptions as necessary.
*
* @param entityClass class that determines the name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
<T> Mono<Boolean> collectionExists(Class<T> entityClass);
/**
* Check to see if a collection with a given name exists.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection
* @return true if a collection with the given name is found, false otherwise.
*/
Mono<Boolean> collectionExists(String collectionName);
/**
* Drop the collection with the name indicated by the entity class.
* <p/>
* Translate any exceptions as necessary.
*
* @param entityClass class that determines the collection to drop/delete.
*/
<T> Mono<Void> dropCollection(Class<T> entityClass);
/**
* Drop the collection with the given name.
* <p/>
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection to drop/delete.
*/
Mono<Void> dropCollection(String collectionName);
/**
* Query for a {@link Flux} of objects of type T from the collection used by the entity class.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
* @param entityClass the parametrized type of the returned {@link Flux}.
*
* @return the converted collection
*/
<T> Flux<T> findAll(Class<T> entityClass);
/**
* Query for a {@link Flux} of objects of type T from the specified collection.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
*
* @param entityClass the parametrized type of the returned {@link Flux}.
* @param collectionName name of the collection to retrieve the objects from
* @return the converted collection
*/
<T> Flux<T> findAll(Class<T> entityClass, String collectionName);
/**
* Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the
* specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Mono}.
* @return the converted object
*/
<T> Mono<T> findOne(Query query, Class<T> entityClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified
* type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Mono}.
* @param collectionName name of the collection to retrieve the objects from
* @return the converted object
*/
<T> Mono<T> findOne(Query query, Class<T> entityClass, String collectionName);
/**
* Determine result of given {@link Query} contains at least one element.
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param collectionName name of the collection to check for objects.
* @return
*/
Mono<Boolean> exists(Query query, String collectionName);
/**
* Determine result of given {@link Query} contains at least one element.
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param entityClass the parametrized type.
* @return
*/
Mono<Boolean> exists(Query query, Class<?> entityClass);
/**
* Determine result of given {@link Query} contains at least one element.
*
* @param query the {@link Query} class that specifies the criteria used to find a record.
* @param entityClass the parametrized type.
* @param collectionName name of the collection to check for objects.
* @return
*/
Mono<Boolean> exists(Query query, Class<?> entityClass, String collectionName);
/**
* Map the results of an ad-hoc query on the collection for the entity class to a {@link Flux} of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Flux}.
* @return the {@link Flux} of converted objects
*/
<T> Flux<T> find(Query query, Class<T> entityClass);
/**
* Map the results of an ad-hoc query on the specified collection to a {@link Flux} of the specified type.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Flux}.
* @param collectionName name of the collection to retrieve the objects from
* @return the {@link Flux} of converted objects
*/
<T> Flux<T> find(Query query, Class<T> entityClass, String collectionName);
/**
* Returns a document with the given id mapped onto the given class. The collection the query is ran against will be
* derived from the given target class as well.
*
* @param <T>
* @param id the id of the document to return.
* @param entityClass the type the document shall be converted into.
* @return the document with the given id mapped onto the given target class.
*/
<T> Mono<T> findById(Object id, Class<T> entityClass);
/**
* Returns the document with the given id from the given collection mapped onto the given target class.
*
* @param id the id of the document to return
* @param entityClass the type to convert the document to
* @param collectionName the collection to query for the document
* @param <T>
* @return
*/
<T> Mono<T> findById(Object id, Class<T> entityClass, String collectionName);
/**
* Returns {@link Flux} of {@link GeoResult} for all entities matching the given {@link NearQuery}. Will consider entity mapping
* information to determine the collection the query is ran against. Note, that MongoDB limits the number of results
* by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a particular number of
* results.
*
* @param near must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @return
*/
<T> Flux<GeoResult<T>> geoNear(NearQuery near, Class<T> entityClass);
/**
* Returns {@link Flux} of {@link GeoResult} for all entities matching the given {@link NearQuery}. Note, that MongoDB limits the
* number of results by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a
* particular number of results.
*
* @param near must not be {@literal null}.
* @param entityClass must not be {@literal null}.
* @param collectionName the collection to trigger the query against. If no collection name is given the entity class
* will be inspected.
* @return
*/
<T> Flux<GeoResult<T>> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
* @param entityClass the parametrized type.
* @return
*/
<T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
* @param entityClass the parametrized type.
* @param collectionName the collection to query.
* @return
*/
<T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
* @param options the {@link FindAndModifyOptions} holding additional information.
* @param entityClass the parametrized type.
* @return
*/
<T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
* {@link FindAndModifyOptions} into account.
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link Update} to apply on matching documents.
* @param options the {@link FindAndModifyOptions} holding additional information.
* @param entityClass the parametrized type.
* @param collectionName the collection to query.
* @return
*/
<T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName);
/**
* Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the
* specified type. The first document that matches the query is returned and also removed from the collection in the
* database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Mono}.
* @return the converted object
*/
<T> Mono<T> findAndRemove(Query query, Class<T> entityClass);
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified
* type. The first document that matches the query is returned and also removed from the collection in the database.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Mono}.
* @param collectionName name of the collection to retrieve the objects from.
* @return the converted object
*/
<T> Mono<T> findAndRemove(Query query, Class<T> entityClass, String collectionName);
/**
* Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
*
* @param query
* @param entityClass must not be {@literal null}.
* @return
*/
Mono<Long> count(Query query, Class<?> entityClass);
/**
* Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
* must solely consist of document field references as we lack type information to map potential property references
* onto document fields. TO make sure the query gets mapped, use {@link #count(Query, Class, String)}.
*
* @param query
* @param collectionName must not be {@literal null} or empty.
* @return
* @see #count(Query, Class, String)
*/
Mono<Long> count(Query query, String collectionName);
/**
* Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
* class to map the given {@link Query}.
*
* @param query
* @param entityClass must not be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
* @return
*/
Mono<Long> count(Query query, Class<?> entityClass, String collectionName);
/**
* Insert the object into the collection for the entity type of the object to save.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
* Spring's Type Conversion"</a> for more details.
* <p/>
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* @param objectToSave the object to store in the collection.
* @return
*/
<T> Mono<T> insert(T objectToSave);
/**
* Insert the object into the specified collection.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* @param objectToSave the object to store in the collection
* @param collectionName name of the collection to store the object in
* @return
*/
<T> Mono<T> insert(T objectToSave, String collectionName);
/**
* Insert a Collection of objects into a collection in a single batch write to the database.
*
* @param batchToSave the batch of objects to save.
* @param entityClass class that determines the collection to use
* @return
*/
<T> Flux<T> insert(Collection<? extends T> batchToSave, Class<?> entityClass);
/**
* Insert a batch of objects into the specified collection in a single batch write to the database.
*
* @param batchToSave the list of objects to save.
* @param collectionName name of the collection to store the object in
* @return
*/
<T> Flux<T> insert(Collection<? extends T> batchToSave, String collectionName);
/**
* Insert a mixed Collection of objects into a database collection determining the collection name to use based on the
* class.
*
* @param objectsToSave the list of objects to save.
* @return
*/
<T> Flux<T> insertAll(Collection<? extends T> objectsToSave);
/**
* Insert the object into the collection for the entity type of the object to save.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
* Spring's Type Conversion"</a> for more details.
* <p/>
* <p/>
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* @param objectToSave the object to store in the collection.
* @return
*/
<T> Mono<T> insert(Mono<? extends T> objectToSave);
/**
* Insert a Collection of objects into a collection in a single batch write to the database.
*
* @param batchToSave the publisher which provides objects to save.
* @param entityClass class that determines the collection to use
* @return
*/
<T> Flux<T> insertAll(Mono<? extends Collection<? extends T>> batchToSave, Class<?> entityClass);
/**
* Insert objects into the specified collection in a single batch write to the database.
*
* @param batchToSave the publisher which provides objects to save.
* @param collectionName name of the collection to store the object in
* @return
*/
<T> Flux<T> insertAll(Mono<? extends Collection<? extends T>> batchToSave, String collectionName);
/**
* Insert a mixed Collection of objects into a database collection determining the collection name to use based on the
* class.
*
* @param objectsToSave the publisher which provides objects to save.
* @return
*/
<T> Flux<T> insertAll(Mono<? extends Collection<? extends T>> objectsToSave);
/**
* Save the object to the collection for the entity type of the object to save. This will perform an insert if the
* object is not already present, that is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
* Spring's Type Conversion"</a> for more details.
*
* @param objectToSave the object to store in the collection
* @return
*/
<T> Mono<T> save(T objectToSave);
/**
* Save the object to the specified collection. This will perform an insert if the object is not already present, that
* is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
* http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">Spring's
* Type Conversion"</a> for more details.
*
* @param objectToSave the object to store in the collection
* @param collectionName name of the collection to store the object in
* @return
*/
<T> Mono<T> save(T objectToSave, String collectionName);
/**
* Save the object to the collection for the entity type of the object to save. This will perform an insert if the
* object is not already present, that is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert" >
* Spring's Type Conversion"</a> for more details.
*
* @param objectToSave the object to store in the collection
* @return
*/
<T> Mono<T> save(Mono<? extends T> objectToSave);
/**
* Save the object to the specified collection. This will perform an insert if the object is not already present, that
* is an 'upsert'.
* <p/>
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* If you object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See <a
* http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">Spring's
* Type Conversion"</a> for more details.
*
* @param objectToSave the object to store in the collection
* @param collectionName name of the collection to store the object in
* @return
*/
<T> Mono<T> save(Mono<? extends T> objectToSave, String collectionName);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
* @param query the query document that specifies the criteria used to select a record to be upserted
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> upsert(Query query, Update update, String collectionName);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
* @param query the query document that specifies the criteria used to select a record to be upserted
* @param update the update document that contains the updated object or $ operators to manipulate the existing object
* @param entityClass class of the pojo to be operated on
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates the first object that is found in the collection of the entity class that matches the query document with
* the provided update document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateFirst(Query query, Update update, String collectionName);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param entityClass class of the pojo to be operated on
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
* with the provided updated document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param entityClass class that determines the collection to use
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateMulti(Query query, Update update, Class<?> entityClass);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
* provided updated document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateMulti(Query query, Update update, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
* with the provided updated document.
*
* @param query the query document that specifies the criteria used to select a record to be updated
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object.
* @param entityClass class of the pojo to be operated on
* @param collectionName name of the collection to update the object in
* @return the WriteResult which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName);
/**
* Remove the given object from the collection by id.
*
* @param object
* @return
*/
Mono<DeleteResult> remove(Object object);
/**
* Removes the given object from the given collection.
*
* @param object
* @param collection must not be {@literal null} or empty.
*/
Mono<DeleteResult> remove(Object object, String collection);
/**
* Remove the given object from the collection by id.
*
* @param objectToRemove
* @return
*/
Mono<DeleteResult> remove(Mono<? extends Object> objectToRemove);
/**
* Removes the given object from the given collection.
*
* @param objectToRemove
* @param collection must not be {@literal null} or empty.
* @return
*/
Mono<DeleteResult> remove(Mono<? extends Object> objectToRemove, String collection);
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
*
* @param query
* @param entityClass
* @return
*/
Mono<DeleteResult> remove(Query query, Class<?> entityClass);
/**
* Remove all documents that match the provided query document criteria from the the collection used to store the
* entityClass. The Class parameter is also used to help convert the Id of the object if it is present in the query.
*
* @param query
* @param entityClass
* @param collectionName
* @return
*/
Mono<DeleteResult> remove(Query query, Class<?> entityClass, String collectionName);
/**
* Remove all documents from the specified collection that match the provided query document criteria. There is no
* conversion/mapping done for any criteria using the id field.
*
* @param query the query document that specifies the criteria used to remove a record
* @param collectionName name of the collection where the objects will removed
*/
Mono<DeleteResult> remove(Query query, String collectionName);
/**
* Returns and removes all documents form the specified collection that match the provided query.
*
* @param query
* @param collectionName
* @return
*/
<T> Flux<T> findAllAndRemove(Query query, String collectionName);
/**
* Returns and removes all documents matching the given query form the collection used to store the entityClass.
*
* @param query
* @param entityClass
* @return
*/
<T> Flux<T> findAllAndRemove(Query query, Class<T> entityClass);
/**
* Returns and removes all documents that match the provided query document criteria from the the collection used to
* store the entityClass. The Class parameter is also used to help convert the Id of the object if it is present in
* the query.
*
* @param query
* @param entityClass
* @param collectionName
* @return
*/
<T> Flux<T> findAllAndRemove(Query query, Class<T> entityClass, String collectionName);
/**
* Map the results of an ad-hoc query on the collection for the entity class to a stream of objects of the specified
* type. The stream uses a {@link com.mongodb.CursorType#TailableAwait tailable} cursor that may be an infinite
* stream. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is
* {@link Subscription#cancel() canceled}.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Flux}.
* @return the {@link Flux} of converted objects
*/
<T> Flux<T> tail(Query query, Class<T> entityClass);
/**
* Map the results of an ad-hoc query on the collection for the entity class to a stream of objects of the specified
* type. The stream uses a {@link com.mongodb.CursorType#TailableAwait tailable} cursor that may be an infinite
* stream. The stream will not be completed unless the {@link org.reactivestreams.Subscription} is
* {@link Subscription#cancel() canceled}.
* <p/>
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
* configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* <p/>
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
* @param query the query class that specifies the criteria used to find a record and also an optional fields
* specification
* @param entityClass the parametrized type of the returned {@link Flux}.
* @param collectionName name of the collection to retrieve the objects from
* @return the {@link Flux} of converted objects
*/
<T> Flux<T> tail(Query query, Class<T> entityClass, String collectionName);
/**
* Returns the underlying {@link MongoConverter}.
*
* @return
*/
MongoConverter getConverter();
}

View File

@@ -20,10 +20,10 @@ import static org.springframework.util.ReflectionUtils.*;
import java.lang.reflect.Method;
import org.bson.Document;
import org.springframework.data.mongodb.util.MongoClientVersion;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
/**
* {@link ReflectiveDBCollectionInvoker} provides reflective access to {@link DBCollection} API that is not consistently
@@ -40,7 +40,7 @@ class ReflectiveDBCollectionInvoker {
static {
GEN_INDEX_NAME_METHOD = findMethod(DBCollection.class, "genIndexName", DBObject.class);
GEN_INDEX_NAME_METHOD = findMethod(DBCollection.class, "genIndexName", Document.class);
RESET_INDEX_CHACHE_METHOD = findMethod(DBCollection.class, "resetIndexCache");
}
@@ -53,7 +53,7 @@ class ReflectiveDBCollectionInvoker {
* @param keys the names of the fields used in this index
* @return
*/
public static String generateIndexName(DBObject keys) {
public static String generateIndexName(Document keys) {
if (isMongo3Driver()) {
return genIndexName(keys);
@@ -79,14 +79,14 @@ class ReflectiveDBCollectionInvoker {
}
/**
* Borrowed from MongoDB Java driver version 2. See <a
* href="http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754"
* >http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754</a>
* Borrowed from MongoDB Java driver version 2. See
* <a href="http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754" >
* http://github.com/mongodb/mongo-java-driver/blob/r2.13.0/src/main/com/mongodb/DBCollection.java#L754</a>
*
* @param keys
* @return
*/
private static String genIndexName(DBObject keys) {
private static String genIndexName(Document keys) {
StringBuilder name = new StringBuilder();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.

View File

@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import com.mongodb.MongoException;
import com.mongodb.WriteResult;
import com.mongodb.client.result.UpdateResult;
/**
* {@link ReflectiveWriteResultInvoker} provides reflective access to {@link WriteResult} API that is not consistently
@@ -35,6 +36,7 @@ final class ReflectiveWriteResultInvoker {
private static final Method GET_ERROR_METHOD;
private static final Method WAS_ACKNOWLEDGED_METHOD;
private static final Method WAS_ACKNOWLEDGED_METHOD_UR;
private ReflectiveWriteResultInvoker() {}
@@ -42,6 +44,7 @@ final class ReflectiveWriteResultInvoker {
GET_ERROR_METHOD = findMethod(WriteResult.class, "getError");
WAS_ACKNOWLEDGED_METHOD = findMethod(WriteResult.class, "wasAcknowledged");
WAS_ACKNOWLEDGED_METHOD_UR = findMethod(UpdateResult.class, "wasAcknowledged");
}
/**
@@ -64,4 +67,12 @@ final class ReflectiveWriteResultInvoker {
public static boolean wasAcknowledged(WriteResult writeResult) {
return isMongo3Driver() ? ((Boolean) invokeMethod(WAS_ACKNOWLEDGED_METHOD, writeResult)).booleanValue() : true;
}
/**
* @param writeResult
* @return return in case of MongoDB Java driver version 2.
*/
public static boolean wasAcknowledged(UpdateResult writeResult) {
return isMongo3Driver() ? ((Boolean) invokeMethod(WAS_ACKNOWLEDGED_METHOD_UR, writeResult)).booleanValue() : true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@@ -33,6 +33,7 @@ import com.mongodb.MongoClientURI;
import com.mongodb.MongoException;
import com.mongodb.MongoURI;
import com.mongodb.WriteConcern;
import com.mongodb.client.MongoDatabase;
/**
* Factory to create {@link DB} instances from a {@link Mongo} instance.
@@ -187,7 +188,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
* (non-Javadoc)
* @see org.springframework.data.mongodb.MongoDbFactory#getDb()
*/
public DB getDb() throws DataAccessException {
public MongoDatabase getDb() throws DataAccessException {
return getDb(databaseName);
}
@@ -195,18 +196,17 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
* (non-Javadoc)
* @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String)
*/
@SuppressWarnings("deprecation")
public DB getDb(String dbName) throws DataAccessException {
public MongoDatabase getDb(String dbName) throws DataAccessException {
Assert.hasText(dbName, "Database name must not be empty.");
DB db = MongoDbUtils.getDB(mongo, dbName, credentials, authenticationDatabaseName);
MongoDatabase db = ((MongoClient) mongo).getDatabase(dbName);
if (writeConcern != null) {
db.setWriteConcern(writeConcern);
if (writeConcern == null) {
return db;
}
return db;
return db.withWriteConcern(writeConcern);
}
/**
@@ -232,4 +232,10 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
public PersistenceExceptionTranslator getExceptionTranslator() {
return this.exceptionTranslator;
}
@SuppressWarnings("deprecation")
@Override
public DB getLegacyDb() {
return mongo.getDB(databaseName);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core;
import java.net.UnknownHostException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.util.Assert;
import com.mongodb.ConnectionString;
import com.mongodb.WriteConcern;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import com.mongodb.reactivestreams.client.MongoDatabase;
/**
* Factory to create {@link MongoDatabase} instances from a {@link MongoClient} instance.
*
* @author Mark Paluch
* @since 2.0
*/
public class SimpleReactiveMongoDatabaseFactory implements DisposableBean, ReactiveMongoDatabaseFactory {
private final MongoClient mongo;
private final String databaseName;
private final boolean mongoInstanceCreated;
private final PersistenceExceptionTranslator exceptionTranslator;
private WriteConcern writeConcern;
/**
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link ConnectionString}.
*
* @param connectionString must not be {@literal null}.
* @throws UnknownHostException
*/
public SimpleReactiveMongoDatabaseFactory(ConnectionString connectionString) throws UnknownHostException {
this(MongoClients.create(connectionString), connectionString.getDatabase(), true);
}
/**
* Creates a new {@link SimpleReactiveMongoDatabaseFactory} instance from the given {@link MongoClient}.
*
* @param mongoClient must not be {@literal null}.
* @param databaseName must not be {@literal null}.
* @since 1.7
*/
public SimpleReactiveMongoDatabaseFactory(MongoClient mongoClient, String databaseName) {
this(mongoClient, databaseName, false);
}
private SimpleReactiveMongoDatabaseFactory(MongoClient client, String databaseName, boolean mongoInstanceCreated) {
Assert.notNull(client, "MongoClient must not be null!");
Assert.hasText(databaseName, "Database name must not be empty!");
Assert.isTrue(databaseName.matches("[\\w-]+"),
"Database name must only contain letters, numbers, underscores and dashes!");
this.mongo = client;
this.databaseName = databaseName;
this.mongoInstanceCreated = mongoInstanceCreated;
this.exceptionTranslator = new MongoExceptionTranslator();
}
/**
* Configures the {@link WriteConcern} to be used on the {@link MongoDatabase} instance being created.
*
* @param writeConcern the writeConcern to set
*/
public void setWriteConcern(WriteConcern writeConcern) {
this.writeConcern = writeConcern;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getMongoDatabase()
*/
public MongoDatabase getMongoDatabase() throws DataAccessException {
return getMongoDatabase(databaseName);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getMongoDatabase(java.lang.String)
*/
public MongoDatabase getMongoDatabase(String dbName) throws DataAccessException {
Assert.hasText(dbName, "Database name must not be empty.");
MongoDatabase db = ReactiveMongoDbUtils.getMongoDatabase(mongo, dbName);
if (writeConcern != null) {
db = db.withWriteConcern(writeConcern);
}
return db;
}
/**
* Clean up the Mongo instance if it was created by the factory itself.
*
* @see DisposableBean#destroy()
*/
public void destroy() throws Exception {
if (mongoInstanceCreated) {
mongo.close();
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.ReactiveMongoDbFactory#getExceptionTranslator()
*/
public PersistenceExceptionTranslator getExceptionTranslator() {
return this.exceptionTranslator;
}
}

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
@@ -32,9 +33,6 @@ import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.SerializationUtils;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* An {@code Aggregation} is a representation of a list of aggregation steps to be performed by the MongoDB Aggregation
* Framework.
@@ -491,19 +489,19 @@ public class Aggregation {
}
/**
* Converts this {@link Aggregation} specification to a {@link DBObject}.
* Converts this {@link Aggregation} specification to a {@link Document}.
*
* @param inputCollectionName the name of the input collection
* @return the {@code DBObject} representing this aggregation
* @return the {@code Document} representing this aggregation
*/
public DBObject toDbObject(String inputCollectionName, AggregationOperationContext rootContext) {
public Document toDocument(String inputCollectionName, AggregationOperationContext rootContext) {
AggregationOperationContext context = rootContext;
List<DBObject> operationDocuments = new ArrayList<DBObject>(operations.size());
List<Document> operationDocuments = new ArrayList<Document>(operations.size());
for (AggregationOperation operation : operations) {
operationDocuments.add(operation.toDBObject(context));
operationDocuments.add(operation.toDocument(context));
if (operation instanceof FieldsExposingAggregationOperation) {
@@ -517,7 +515,7 @@ public class Aggregation {
}
}
DBObject command = new BasicDBObject("aggregate", inputCollectionName);
Document command = new Document("aggregate", inputCollectionName);
command.put("pipeline", operationDocuments);
command = options.applyAndReturnPotentiallyChangedCommand(command);
@@ -532,7 +530,7 @@ public class Aggregation {
@Override
public String toString() {
return SerializationUtils
.serializeToJsonSafely(toDbObject("__collection__", new NoOpAggregationOperationContext()));
.serializeToJsonSafely(toDocument("__collection__", new NoOpAggregationOperationContext()));
}
/**
@@ -544,11 +542,11 @@ public class Aggregation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.Document)
*/
@Override
public DBObject getMappedObject(DBObject dbObject) {
return dbObject;
public Document getMappedObject(Document document) {
return document;
}
/*

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import com.mongodb.DBObject;
import org.bson.Document;
/**
* An {@link AggregationExpression} can be used with field expressions in aggregation pipeline stages like
@@ -28,11 +28,11 @@ import com.mongodb.DBObject;
public interface AggregationExpression {
/**
* Turns the {@link AggregationExpression} into a {@link DBObject} within the given
* Turns the {@link AggregationExpression} into a {@link Document} within the given
* {@link AggregationOperationContext}.
*
* @param context
* @return
*/
DBObject toDbObject(AggregationOperationContext context);
Document toDocument(AggregationOperationContext context);
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.AggregationExpressionTransformer.AggregationExpressionTransformationContext;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.data.mongodb.core.spel.ExpressionNode;
@@ -22,16 +23,16 @@ import org.springframework.data.mongodb.core.spel.ExpressionTransformationContex
import org.springframework.data.mongodb.core.spel.ExpressionTransformer;
import org.springframework.util.Assert;
import com.mongodb.DBObject;
/**
* Interface to type an {@link ExpressionTransformer} to the contained
* {@link AggregationExpressionTransformationContext}.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.4
*/
interface AggregationExpressionTransformer extends
ExpressionTransformer<AggregationExpressionTransformationContext<ExpressionNode>> {
interface AggregationExpressionTransformer
extends ExpressionTransformer<AggregationExpressionTransformationContext<ExpressionNode>> {
/**
* A special {@link ExpressionTransformationContextSupport} to be aware of the {@link AggregationOperationContext}.
@@ -39,8 +40,8 @@ interface AggregationExpressionTransformer extends
* @author Oliver Gierke
* @author Thomas Darimont
*/
public static class AggregationExpressionTransformationContext<T extends ExpressionNode> extends
ExpressionTransformationContextSupport<T> {
class AggregationExpressionTransformationContext<T extends ExpressionNode>
extends ExpressionTransformationContextSupport<T> {
private final AggregationOperationContext aggregationContext;
@@ -53,7 +54,7 @@ interface AggregationExpressionTransformer extends
* @param aggregationContext must not be {@literal null}.
*/
public AggregationExpressionTransformationContext(T currentNode, ExpressionNode parentNode,
DBObject previousOperationObject, AggregationOperationContext context) {
Document previousOperationObject, AggregationOperationContext context) {
super(currentNode, parentNode, previousOperationObject);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.
@@ -19,17 +19,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* An enum of supported {@link AggregationExpression}s in aggregation pipeline stages.
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.10
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.7
*/
public enum AggregationFunctionExpressions {
@@ -76,10 +76,10 @@ public enum AggregationFunctionExpressions {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.Expression#toDbObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.Expression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDbObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
List<Object> args = new ArrayList<Object>(values.size());
@@ -87,13 +87,13 @@ public enum AggregationFunctionExpressions {
args.add(unpack(value, context));
}
return new BasicDBObject("$" + name, args);
return new Document("$" + name, args);
}
private static Object unpack(Object value, AggregationOperationContext context) {
if (value instanceof AggregationExpression) {
return ((AggregationExpression) value).toDbObject(context);
return ((AggregationExpression) value).toDocument(context);
}
if (value instanceof Field) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,7 +15,7 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import com.mongodb.DBObject;
import org.bson.Document;
/**
* Represents one single operation in an aggregation pipeline.
@@ -23,15 +23,16 @@ import com.mongodb.DBObject;
* @author Sebastian Herold
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public interface AggregationOperation {
/**
* Turns the {@link AggregationOperation} into a {@link DBObject} by using the given
* Turns the {@link AggregationOperation} into a {@link Document} by using the given
* {@link AggregationOperationContext}.
*
* @return the DBObject
* @return the Document
*/
DBObject toDBObject(AggregationOperationContext context);
Document toDocument(AggregationOperationContext context);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,25 +15,25 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import com.mongodb.DBObject;
/**
* The context for an {@link AggregationOperation}.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public interface AggregationOperationContext {
/**
* Returns the mapped {@link DBObject}, potentially converting the source considering mapping metadata etc.
* Returns the mapped {@link Document}, potentially converting the source considering mapping metadata etc.
*
* @param dbObject will never be {@literal null}.
* @param document will never be {@literal null}.
* @return must not be {@literal null}.
*/
DBObject getMappedObject(DBObject dbObject);
Document getMappedObject(Document document);
/**
* Returns a {@link FieldReference} for the given field or {@literal null} if the context does not expose the given

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,8 +15,7 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.bson.Document;
/**
* Holds a set of configurable aggregation options that can be used within an aggregation pipeline. A list of support
@@ -25,6 +24,7 @@ import com.mongodb.DBObject;
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @see Aggregation#withOptions(AggregationOptions)
* @see TypedAggregation#withOptions(AggregationOptions)
* @since 1.6
@@ -37,7 +37,7 @@ public class AggregationOptions {
private final boolean allowDiskUse;
private final boolean explain;
private final DBObject cursor;
private final Document cursor;
/**
* Creates a new {@link AggregationOptions}.
@@ -46,7 +46,7 @@ public class AggregationOptions {
* @param explain whether to get the execution plan for the aggregation instead of the actual results.
* @param cursor can be {@literal null}, used to pass additional options to the aggregation.
*/
public AggregationOptions(boolean allowDiskUse, boolean explain, DBObject cursor) {
public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor) {
this.allowDiskUse = allowDiskUse;
this.explain = explain;
@@ -77,7 +77,7 @@ public class AggregationOptions {
*
* @return
*/
public DBObject getCursor() {
public Document getCursor() {
return cursor;
}
@@ -88,19 +88,19 @@ public class AggregationOptions {
* @param command the aggregation command.
* @return
*/
DBObject applyAndReturnPotentiallyChangedCommand(DBObject command) {
Document applyAndReturnPotentiallyChangedCommand(Document command) {
DBObject result = new BasicDBObject(command.toMap());
Document result = new Document(command);
if (allowDiskUse && !result.containsField(ALLOW_DISK_USE)) {
if (allowDiskUse && !result.containsKey(ALLOW_DISK_USE)) {
result.put(ALLOW_DISK_USE, allowDiskUse);
}
if (explain && !result.containsField(EXPLAIN)) {
if (explain && !result.containsKey(EXPLAIN)) {
result.put(EXPLAIN, explain);
}
if (cursor != null && !result.containsField(CURSOR)) {
if (cursor != null && !result.containsKey(CURSOR)) {
result.put("cursor", cursor);
}
@@ -108,18 +108,18 @@ public class AggregationOptions {
}
/**
* Returns a {@link DBObject} representation of this {@link AggregationOptions}.
* Returns a {@link Document} representation of this {@link AggregationOptions}.
*
* @return
*/
public DBObject toDbObject() {
public Document toDocument() {
DBObject dbo = new BasicDBObject();
dbo.put(ALLOW_DISK_USE, allowDiskUse);
dbo.put(EXPLAIN, explain);
dbo.put(CURSOR, cursor);
Document document = new Document();
document.put(ALLOW_DISK_USE, allowDiskUse);
document.put(EXPLAIN, explain);
document.put(CURSOR, cursor);
return dbo;
return document;
}
/* (non-Javadoc)
@@ -127,7 +127,7 @@ public class AggregationOptions {
*/
@Override
public String toString() {
return toDbObject().toString();
return toDocument().toJson();
}
/**
@@ -139,7 +139,7 @@ public class AggregationOptions {
private boolean allowDiskUse;
private boolean explain;
private DBObject cursor;
private Document cursor;
/**
* Defines whether to off-load intensive sort-operations to disk.
@@ -171,7 +171,7 @@ public class AggregationOptions {
* @param cursor
* @return
*/
public Builder cursor(DBObject cursor) {
public Builder cursor(Document cursor) {
this.cursor = cursor;
return this;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -19,23 +19,23 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.DBObject;
/**
* Collects the results of executing an aggregation operation.
*
* @author Tobias Trelle
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @param <T> The class in which the results are mapped onto.
* @since 1.3
*/
public class AggregationResults<T> implements Iterable<T> {
private final List<T> mappedResults;
private final DBObject rawResults;
private final Document rawResults;
private final String serverUsed;
/**
@@ -44,7 +44,7 @@ public class AggregationResults<T> implements Iterable<T> {
* @param mappedResults must not be {@literal null}.
* @param rawResults must not be {@literal null}.
*/
public AggregationResults(List<T> mappedResults, DBObject rawResults) {
public AggregationResults(List<T> mappedResults, Document rawResults) {
Assert.notNull(mappedResults);
Assert.notNull(rawResults);
@@ -97,7 +97,7 @@ public class AggregationResults<T> implements Iterable<T> {
* @return
* @since 1.6
*/
public DBObject getRawResults() {
public Document getRawResults() {
return rawResults;
}

View File

@@ -18,17 +18,15 @@ package org.springframework.data.mongodb.core.aggregation;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $cond} operator. A {@link ConditionalOperator} allows nested conditions
* {@code if-then[if-then-else]-else} using {@link Field}, {@link CriteriaDefinition} or a {@link DBObject custom}
* {@code if-then[if-then-else]-else} using {@link Field}, {@link CriteriaDefinition} or a {@link Document custom}
* condition. Replacement values can be either {@link Field field references}, values of simple MongoDB types or values
* that can be converted to a simple MongoDB type.
*
@@ -67,14 +65,14 @@ public class ConditionalOperator implements AggregationExpression {
}
/**
* Creates a new {@link ConditionalOperator} for a given {@link DBObject criteria} and {@code then}/{@code otherwise}
* Creates a new {@link ConditionalOperator} for a given {@link Document criteria} and {@code then}/{@code otherwise}
* values.
*
* @param condition must not be {@literal null}.
* @param thenValue must not be {@literal null}.
* @param otherwiseValue must not be {@literal null}.
*/
public ConditionalOperator(DBObject condition, Object thenValue, Object otherwiseValue) {
public ConditionalOperator(Document condition, Object thenValue, Object otherwiseValue) {
this((Object) condition, thenValue, otherwiseValue);
}
@@ -95,42 +93,42 @@ public class ConditionalOperator implements AggregationExpression {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDbObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDbObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject condObject = new BasicDBObject();
Document condObject = new Document();
condObject.append("if", resolveCriteria(context, condition));
condObject.append("then", resolveValue(context, thenValue));
condObject.append("else", resolveValue(context, otherwiseValue));
return new BasicDBObject("$cond", condObject);
return new Document("$cond", condObject);
}
private Object resolveValue(AggregationOperationContext context, Object value) {
if (value instanceof DBObject || value instanceof Field) {
if (value instanceof Document || value instanceof Field) {
return resolve(context, value);
}
if (value instanceof ConditionalOperator) {
return ((ConditionalOperator) value).toDbObject(context);
return ((ConditionalOperator) value).toDocument(context);
}
return context.getMappedObject(new BasicDBObject("$set", value)).get("$set");
return context.getMappedObject(new Document("$set", value)).get("$set");
}
private Object resolveCriteria(AggregationOperationContext context, Object value) {
if (value instanceof DBObject || value instanceof Field) {
if (value instanceof Document || value instanceof Field) {
return resolve(context, value);
}
if (value instanceof CriteriaDefinition) {
DBObject mappedObject = context.getMappedObject(((CriteriaDefinition) value).getCriteriaObject());
Document mappedObject = context.getMappedObject(((CriteriaDefinition) value).getCriteriaObject());
List<Object> clauses = new ArrayList<Object>();
clauses.addAll(getClauses(context, mappedObject));
@@ -143,10 +141,10 @@ public class ConditionalOperator implements AggregationExpression {
}
throw new InvalidDataAccessApiUsageException(
String.format("Invalid value in condition. Supported: DBObject, Field references, Criteria, got: %s", value));
String.format("Invalid value in condition. Supported: Document, Field references, Criteria, got: %s", value));
}
private List<Object> getClauses(AggregationOperationContext context, DBObject mappedObject) {
private List<Object> getClauses(AggregationOperationContext context, Document mappedObject) {
List<Object> clauses = new ArrayList<Object>();
@@ -167,16 +165,16 @@ public class ConditionalOperator implements AggregationExpression {
List<Object> args = new ArrayList<Object>();
for (Object clause : (List<?>) predicate) {
if (clause instanceof DBObject) {
args.addAll(getClauses(context, (DBObject) clause));
if (clause instanceof Document) {
args.addAll(getClauses(context, (Document) clause));
}
}
clauses.add(new BasicDBObject(key, args));
clauses.add(new Document(key, args));
} else if (predicate instanceof DBObject) {
} else if (predicate instanceof Document) {
DBObject nested = (DBObject) predicate;
Document nested = (Document) predicate;
for (String s : nested.keySet()) {
@@ -187,7 +185,7 @@ public class ConditionalOperator implements AggregationExpression {
List<Object> args = new ArrayList<Object>();
args.add("$" + key);
args.add(nested.get(s));
clauses.add(new BasicDBObject(s, args));
clauses.add(new Document(s, args));
}
} else if (!isKeyword(key)) {
@@ -195,7 +193,7 @@ public class ConditionalOperator implements AggregationExpression {
List<Object> args = new ArrayList<Object>();
args.add("$" + key);
args.add(predicate);
clauses.add(new BasicDBObject("$eq", args));
clauses.add(new Document("$eq", args));
}
return clauses;
@@ -213,8 +211,8 @@ public class ConditionalOperator implements AggregationExpression {
private Object resolve(AggregationOperationContext context, Object value) {
if (value instanceof DBObject) {
return context.getMappedObject((DBObject) value);
if (value instanceof Document) {
return context.getMappedObject((Document) value);
}
return context.getReference((Field) value).toString();
@@ -243,7 +241,7 @@ public class ConditionalOperator implements AggregationExpression {
* @param booleanExpression expression that yields in a boolean result, must not be {@literal null}.
* @return the {@link ThenBuilder}
*/
ThenBuilder when(DBObject booleanExpression);
ThenBuilder when(Document booleanExpression);
/**
* @param booleanField reference to a field holding a boolean value, must not be {@literal null}.
@@ -270,7 +268,7 @@ public class ConditionalOperator implements AggregationExpression {
public static interface ThenBuilder {
/**
* @param value the value to be used if the condition evaluates {@literal true}. Can be a {@link DBObject}, a value
* @param value the value to be used if the condition evaluates {@literal true}. Can be a {@link Document}, a value
* that is supported by MongoDB or a value that can be converted to a MongoDB representation but must not
* be {@literal null}.
* @return the {@link OtherwiseBuilder}
@@ -284,7 +282,7 @@ public class ConditionalOperator implements AggregationExpression {
public static interface OtherwiseBuilder {
/**
* @param value the value to be used if the condition evaluates {@literal false}. Can be a {@link DBObject}, a value
* @param value the value to be used if the condition evaluates {@literal false}. Can be a {@link Document}, a value
* that is supported by MongoDB or a value that can be converted to a MongoDB representation but must not
* be {@literal null}.
* @return the {@link ConditionalOperator}
@@ -316,10 +314,10 @@ public class ConditionalOperator implements AggregationExpression {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ConditionalOperator.WhenBuilder#when(com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.aggregation.ConditionalOperator.WhenBuilder#when(org.bson.Document)
*/
@Override
public ConditionalExpressionBuilder when(DBObject booleanExpression) {
public ConditionalExpressionBuilder when(Document booleanExpression) {
Assert.notNull(booleanExpression, "'Boolean expression' must not be null!");

View File

@@ -15,12 +15,11 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.util.Assert;
import com.mongodb.DBObject;
/**
* {@link AggregationOperationContext} that combines the available field references from a given
* {@code AggregationOperationContext} and an {@link FieldsExposingAggregationOperation}.
@@ -28,6 +27,7 @@ import com.mongodb.DBObject;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Mark Paluch
* @author Christoph Strobl
* @since 1.4
*/
class ExposedFieldsAggregationOperationContext implements AggregationOperationContext {
@@ -54,11 +54,11 @@ class ExposedFieldsAggregationOperationContext implements AggregationOperationCo
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.Document)
*/
@Override
public DBObject getMappedObject(DBObject dbObject) {
return rootContext.getMappedObject(dbObject);
public Document getMappedObject(Document document) {
return rootContext.getMappedObject(document);
}
/*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,12 +15,10 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Represents a {@code geoNear} aggregation operation.
* <p>
@@ -28,6 +26,7 @@ import com.mongodb.DBObject;
* instances of this class directly.
*
* @author Thomas Darimont
* @author Christoph Strobl
* @since 1.3
*/
public class GeoNearOperation implements AggregationOperation {
@@ -53,14 +52,14 @@ public class GeoNearOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject command = (BasicDBObject) context.getMappedObject(nearQuery.toDBObject());
Document command = context.getMappedObject(nearQuery.toDocument());
command.put("distanceField", distanceField);
return new BasicDBObject("$geoNear", command);
return new Document("$geoNear", command);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -21,14 +21,12 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $group}-operation.
* <p>
@@ -39,6 +37,7 @@ import com.mongodb.DBObject;
* @author Sebastian Herold
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public class GroupOperation implements FieldsExposingAggregationOperation {
@@ -194,7 +193,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
/**
* Generates an {@link GroupOperationBuilder} for an {@code $last}-expression for the given {@link AggregationExpression}.
* Generates an {@link GroupOperationBuilder} for an {@code $last}-expression for the given
* {@link AggregationExpression}.
*
* @param expr
* @return
@@ -214,7 +214,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
/**
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given {@link AggregationExpression}.
* Generates an {@link GroupOperationBuilder} for a {@code $first}-expression for the given
* {@link AggregationExpression}.
*
* @param expr
* @return
@@ -234,7 +235,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
/**
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given {@link AggregationExpression}.
* Generates an {@link GroupOperationBuilder} for an {@code $avg}-expression for the given
* {@link AggregationExpression}.
*
* @param expr
* @return
@@ -278,7 +280,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
/**
* Generates an {@link GroupOperationBuilder} for an {@code $min}-expression that for the given {@link AggregationExpression}.
* Generates an {@link GroupOperationBuilder} for an {@code $min}-expression that for the given
* {@link AggregationExpression}.
*
* @param expr
* @return
@@ -298,7 +301,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
/**
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given {@link AggregationExpression}.
* Generates an {@link GroupOperationBuilder} for an {@code $max}-expression that for the given
* {@link AggregationExpression}.
*
* @param expr
* @return
@@ -329,12 +333,12 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public com.mongodb.DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject operationObject = new BasicDBObject();
Document operationObject = new Document();
if (idFields.exposesNoNonSyntheticFields()) {
@@ -347,7 +351,7 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
} else {
BasicDBObject inner = new BasicDBObject();
Document inner = new Document();
for (ExposedField field : idFields) {
FieldReference reference = context.getReference(field);
@@ -358,10 +362,10 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
}
for (Operation operation : operations) {
operationObject.putAll(operation.toDBObject(context));
operationObject.putAll(operation.toDocument(context));
}
return new BasicDBObject("$group", operationObject);
return new Document("$group", operationObject);
}
interface Keyword {
@@ -412,8 +416,8 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
return new ExposedField(key, true);
}
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject(key, new BasicDBObject(op.toString(), getValue(context)));
public Document toDocument(AggregationOperationContext context) {
return new Document(key, new Document(op.toString(), getValue(context)));
}
public Object getValue(AggregationOperationContext context) {
@@ -421,7 +425,7 @@ public class GroupOperation implements FieldsExposingAggregationOperation {
if (reference == null) {
if (value instanceof AggregationExpression) {
return ((AggregationExpression) value).toDbObject(context);
return ((AggregationExpression) value).toDocument(context);
}
return value;

View File

@@ -13,23 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.aggregation;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $ifNull} operator. Replacement values can be either {@link Field field
* references}, values of simple MongoDB types or values that can be converted to a simple MongoDB type.
*
* @see http://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/
* @author Mark Paluch
* @author Christoph Strobl
* @since 1.10
*/
public class IfNullOperator implements AggregationExpression {
@@ -54,28 +52,28 @@ public class IfNullOperator implements AggregationExpression {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDbObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDbObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
List<Object> list = new ArrayList<Object>();
list.add(context.getReference(field).toString());
list.add(resolve(value, context));
return new BasicDBObject("$ifNull", list);
return new Document("$ifNull", list);
}
private Object resolve(Object value, AggregationOperationContext context) {
if (value instanceof Field) {
return context.getReference((Field) value).toString();
} else if (value instanceof DBObject) {
} else if (value instanceof Document) {
return value;
}
return context.getMappedObject(new BasicDBObject("$set", value)).get("$set");
return context.getMappedObject(new Document("$set", value)).get("$set");
}
/**
@@ -118,7 +116,7 @@ public class IfNullOperator implements AggregationExpression {
/**
* @param value the value to be used if the {@code $ifNull }condition evaluates {@literal true}. Can be a
* {@link DBObject}, a value that is supported by MongoDB or a value that can be converted to a MongoDB
* {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB
* representation but must not be {@literal null}.
* @return the {@link IfNullOperator}
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,11 +15,9 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the {@code $limit}-operation.
* <p>
@@ -29,6 +27,7 @@ import com.mongodb.DBObject;
* @see http://docs.mongodb.org/manual/reference/aggregation/limit/
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public class LimitOperation implements AggregationOperation {
@@ -46,10 +45,10 @@ public class LimitOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$limit", maxElements);
public Document toDocument(AggregationOperationContext context) {
return new Document("$limit", Long.valueOf(maxElements));
}
}

View File

@@ -15,13 +15,11 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $lookup}-operation. We recommend to use the static factory method
* {@link Aggregation#lookup(String, String, String, String)} instead of creating instances of this class directly.
@@ -75,19 +73,19 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject lookupObject = new BasicDBObject();
Document lookupObject = new Document();
lookupObject.append("from", from.getTarget());
lookupObject.append("localField", localField.getTarget());
lookupObject.append("foreignField", foreignField.getTarget());
lookupObject.append("as", as.getTarget());
return new BasicDBObject("$lookup", lookupObject);
return new Document("$lookup", lookupObject);
}
/**

View File

@@ -15,12 +15,10 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the {@code $match}-operation.
* <p>
@@ -51,10 +49,10 @@ public class MatchOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$match", context.getMappedObject(criteriaDefinition.getCriteriaObject()));
public Document toDocument(AggregationOperationContext context) {
return new Document("$match", context.getMappedObject(criteriaDefinition.getCriteriaObject()));
}
}

View File

@@ -15,8 +15,7 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.bson.Document;
import org.springframework.util.Assert;
/**
@@ -27,6 +26,7 @@ import org.springframework.util.Assert;
*
* @see http://docs.mongodb.org/manual/reference/aggregation/out/
* @author Nikolay Bogdanov
* @author Christoph Strobl
*/
public class OutOperation implements AggregationOperation {
@@ -42,10 +42,10 @@ public class OutOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$out", collectionName);
public Document toDocument(AggregationOperationContext context) {
return new Document("$out", collectionName);
}
}

View File

@@ -20,14 +20,12 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder.FieldProjection;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $project}-operation.
* <p>
@@ -186,18 +184,18 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject fieldObject = new BasicDBObject();
Document fieldObject = new Document();
for (Projection projection : projections) {
fieldObject.putAll(projection.toDBObject(context));
fieldObject.putAll(projection.toDocument(context));
}
return new BasicDBObject("$project", fieldObject);
return new Document("$project", fieldObject);
}
/**
@@ -227,11 +225,11 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return this.operation.toDBObject(context);
public Document toDocument(AggregationOperationContext context) {
return this.operation.toDocument(context);
}
/**
@@ -353,11 +351,11 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject(getExposedField().getName(), toMongoExpression(context, expression, params));
public Document toDocument(AggregationOperationContext context) {
return new Document(getExposedField().getName(), toMongoExpression(context, expression, params));
}
protected static Object toMongoExpression(AggregationOperationContext context, String expression,
@@ -643,11 +641,11 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return this.operation.toDBObject(context);
public Document toDocument(AggregationOperationContext context) {
return this.operation.toDocument(context);
}
/**
@@ -684,11 +682,11 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject(name, Fields.UNDERSCORE_ID_REF);
public Document toDocument(AggregationOperationContext context) {
return new Document(name, Fields.UNDERSCORE_ID_REF);
}
}
@@ -753,11 +751,11 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject(field.getName(), renderFieldValue(context));
public Document toDocument(AggregationOperationContext context) {
return new Document(field.getName(), renderFieldValue(context));
}
private Object renderFieldValue(AggregationOperationContext context) {
@@ -809,14 +807,14 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
DBObject inner = new BasicDBObject("$" + operation, getOperationArguments(context));
Document inner = new Document("$" + operation, getOperationArguments(context));
return new BasicDBObject(getField().getName(), inner);
return new Document(getField().getName(), inner);
}
protected List<Object> getOperationArguments(AggregationOperationContext context) {
@@ -899,18 +897,18 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.ProjectionOperation.Projection#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
DBObject nestedObject = new BasicDBObject();
Document nestedObject = new Document();
for (Field field : fields) {
nestedObject.put(field.getName(), context.getReference(field.getTarget()).toString());
}
return new BasicDBObject(name, nestedObject);
return new Document(name, nestedObject);
}
}
@@ -1035,13 +1033,13 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
}
/**
* Renders the current {@link Projection} into a {@link DBObject} based on the given
* Renders the current {@link Projection} into a {@link Document} based on the given
* {@link AggregationOperationContext}.
*
* @param context will never be {@literal null}.
* @return
*/
public abstract DBObject toDBObject(AggregationOperationContext context);
public abstract Document toDocument(AggregationOperationContext context);
}
/**
@@ -1066,8 +1064,8 @@ public class ProjectionOperation implements FieldsExposingAggregationOperation {
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject(field.getName(), expression.toDbObject(context));
public Document toDocument(AggregationOperationContext context) {
return new Document(field.getName(), expression.toDocument(context));
}
}
}

View File

@@ -15,11 +15,9 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $skip}-operation.
* <p>
@@ -29,6 +27,7 @@ import com.mongodb.DBObject;
* @see http://docs.mongodb.org/manual/reference/aggregation/skip/
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public class SkipOperation implements AggregationOperation {
@@ -48,10 +47,10 @@ public class SkipOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$skip", skipCount);
public Document toDocument(AggregationOperationContext context) {
return new Document("$skip", skipCount);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,15 +15,13 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $sort}-operation.
* <p>
@@ -33,6 +31,7 @@ import com.mongodb.DBObject;
* @see http://docs.mongodb.org/manual/reference/aggregation/sort/#pipe._S_sort
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public class SortOperation implements AggregationOperation {
@@ -60,12 +59,12 @@ public class SortOperation implements AggregationOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
BasicDBObject object = new BasicDBObject();
Document object = new Document();
for (Order order : sort) {
@@ -74,6 +73,6 @@ public class SortOperation implements AggregationOperation {
object.put(reference.getRaw(), order.isAscending() ? 1 : -1);
}
return new BasicDBObject("$sort", object);
return new Document("$sort", object);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,12 +15,12 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import static org.springframework.data.mongodb.util.DBObjectUtils.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.bson.Document;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.mongodb.core.spel.ExpressionNode;
import org.springframework.data.mongodb.core.spel.ExpressionTransformationContextSupport;
@@ -40,10 +40,6 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Renders the AST of a SpEL expression as a MongoDB Aggregation Framework projection expression.
*
@@ -131,8 +127,8 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
* @author Thomas Darimont
* @author Oliver Gierke
*/
private static abstract class ExpressionNodeConversion<T extends ExpressionNode> implements
AggregationExpressionTransformer {
private static abstract class ExpressionNodeConversion<T extends ExpressionNode>
implements AggregationExpressionTransformer {
private final AggregationExpressionTransformer transformer;
private final Class<? extends ExpressionNode> nodeType;
@@ -188,7 +184,7 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
* @param context must not be {@literal null}.
* @return
*/
protected Object transform(ExpressionNode node, ExpressionNode parent, DBObject operation,
protected Object transform(ExpressionNode node, ExpressionNode parent, Document operation,
AggregationExpressionTransformationContext<?> context) {
Assert.notNull(node, "ExpressionNode must not be null!");
@@ -236,7 +232,7 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
OperatorNode currentNode = context.getCurrentNode();
DBObject operationObject = createOperationObjectAndAddToPreviousArgumentsIfNecessary(context, currentNode);
Document operationObject = createOperationObjectAndAddToPreviousArgumentsIfNecessary(context, currentNode);
Object leftResult = transform(currentNode.getLeft(), currentNode, operationObject, context);
if (currentNode.isUnaryMinus()) {
@@ -249,32 +245,33 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
return operationObject;
}
private DBObject createOperationObjectAndAddToPreviousArgumentsIfNecessary(
private Document createOperationObjectAndAddToPreviousArgumentsIfNecessary(
AggregationExpressionTransformationContext<OperatorNode> context, OperatorNode currentNode) {
DBObject nextDbObject = new BasicDBObject(currentNode.getMongoOperator(), new BasicDBList());
Document nextDocument = new Document(currentNode.getMongoOperator(), new ArrayList<Object>());
if (!context.hasPreviousOperation()) {
return nextDbObject;
return nextDocument;
}
if (context.parentIsSameOperation()) {
// same operator applied in a row e.g. 1 + 2 + 3 carry on with the operation and render as $add: [1, 2 ,3]
nextDbObject = context.getPreviousOperationObject();
nextDocument = context.getPreviousOperationObject();
} else if (!currentNode.isUnaryOperator()) {
// different operator -> add context object for next level to list if arguments of previous expression
context.addToPreviousOperation(nextDbObject);
context.addToPreviousOperation(nextDocument);
}
return nextDbObject;
return nextDocument;
}
private Object convertUnaryMinusOp(ExpressionTransformationContextSupport<OperatorNode> context, Object leftResult) {
private Object convertUnaryMinusOp(ExpressionTransformationContextSupport<OperatorNode> context,
Object leftResult) {
Object result = leftResult instanceof Number ? leftResult
: new BasicDBObject("$multiply", dbList(-1, leftResult));
: new Document("$multiply", Arrays.<Object> asList(Integer.valueOf(-1), leftResult));
if (leftResult != null && context.hasPreviousOperation()) {
context.addToPreviousOperation(result);
@@ -468,7 +465,7 @@ class SpelExpressionTransformer implements AggregationExpressionTransformer {
args.add(transform(childNode, context));
}
return context.addToPreviousOrReturn(new BasicDBObject(node.getMethodName(), dbList(args.toArray())));
return context.addToPreviousOrReturn(new Document(node.getMethodName(), args));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2016 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.
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.aggregation;
import static org.springframework.data.mongodb.core.aggregation.Fields.*;
import org.bson.Document;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
@@ -27,13 +28,12 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.util.Assert;
import com.mongodb.DBObject;
/**
* {@link AggregationOperationContext} aware of a particular type and a {@link MappingContext} to potentially translate
* property references into document field names.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.3
*/
public class TypeBasedAggregationOperationContext implements AggregationOperationContext {
@@ -64,11 +64,11 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(com.mongodb.Document)
*/
@Override
public DBObject getMappedObject(DBObject dbObject) {
return mapper.getMappedObject(dbObject, mappingContext.getPersistentEntity(type));
public Document getMappedObject(Document document) {
return mapper.getMappedObject(document, mappingContext.getPersistentEntity(type));
}
/*
@@ -93,8 +93,8 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
private FieldReference getReferenceFor(Field field) {
PersistentPropertyPath<MongoPersistentProperty> propertyPath = mappingContext.getPersistentPropertyPath(
field.getTarget(), type);
PersistentPropertyPath<MongoPersistentProperty> propertyPath = mappingContext
.getPersistentPropertyPath(field.getTarget(), type);
Field mappedField = field(propertyPath.getLeafProperty().getName(),
propertyPath.toDotPath(MongoPersistentProperty.PropertyToFieldNameConverter.INSTANCE));

View File

@@ -15,12 +15,10 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Encapsulates the aggregation framework {@code $unwind}-operation.
* <p>
@@ -87,25 +85,25 @@ public class UnwindOperation
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDBObject(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
public Document toDocument(AggregationOperationContext context) {
String path = context.getReference(field).toString();
if (!preserveNullAndEmptyArrays && arrayIndex == null) {
return new BasicDBObject("$unwind", path);
return new Document("$unwind", path);
}
DBObject unwindArgs = new BasicDBObject();
Document unwindArgs = new Document();
unwindArgs.put("path", path);
if (arrayIndex != null) {
unwindArgs.put("includeArrayIndex", arrayIndex.getName());
}
unwindArgs.put("preserveNullAndEmptyArrays", preserveNullAndEmptyArrays);
return new BasicDBObject("$unwind", unwindArgs);
return new Document("$unwind", unwindArgs);
}
/*

View File

@@ -31,7 +31,7 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObj
/**
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
* converters. Allows registering {@link CustomConversions}.
*
*
* @author Jon Brisbin
* @author Oliver Gierke
*/
@@ -43,7 +43,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
/**
* Creates a new {@link AbstractMongoConverter} using the given {@link GenericConversionService}.
*
*
* @param conversionService
*/
public AbstractMongoConverter(GenericConversionService conversionService) {
@@ -52,7 +52,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
/**
* Registers the given custom conversions with the converter.
*
*
* @param conversions
*/
public void setCustomConversions(CustomConversions conversions) {
@@ -61,7 +61,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
/**
* Registers {@link EntityInstantiators} to customize entity instantiation.
*
*
* @param instantiators
*/
public void setInstantiators(EntityInstantiators instantiators) {
@@ -89,7 +89,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
conversions.registerConvertersIn(conversionService);
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object)
*/

View File

@@ -15,13 +15,13 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import java.util.List;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
/**
@@ -30,6 +30,7 @@ import com.mongodb.DBRef;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.4
*/
public interface DbRefResolver {
@@ -66,11 +67,11 @@ public interface DbRefResolver {
* @return
* @since 1.7
*/
DBObject fetch(DBRef dbRef);
Document fetch(DBRef dbRef);
/**
* Loads a given {@link List} of {@link DBRef}s from the datasource in one batch. The resulting {@link List} of
* {@link DBObject} will reflect the ordering of the {@link DBRef} passed in.<br />
* {@link Document} will reflect the ordering of the {@link DBRef} passed in.<br />
* The {@link DBRef} elements in the list must not reference different collections.
*
* @param dbRefs must not be {@literal null}.
@@ -78,5 +79,5 @@ public interface DbRefResolver {
* @throws InvalidDataAccessApiUsageException in case not all {@link DBRef} target the same collection.
* @since 1.10
*/
List<DBObject> bulkFetch(List<DBRef> dbRefs);
List<Document> bulkFetch(List<DBRef> dbRefs);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,6 +15,7 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
@@ -23,12 +24,11 @@ import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
/**
* @author Oliver Gierke
* @author Christoph Strobl
*/
class DefaultDbRefProxyHandler implements DbRefProxyHandler {
@@ -38,11 +38,12 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
/**
* @param spELContext must not be {@literal null}.
* @param conversionService must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
* @param resolver must not be {@literal null}.
*/
public DefaultDbRefProxyHandler(SpELContext spELContext,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext, ValueResolver resolver) {
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext,
ValueResolver resolver) {
this.spELContext = spELContext;
this.mappingContext = mappingContext;
@@ -70,7 +71,7 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(proxy, spELContext);
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(proxy);
DBObject object = new BasicDBObject(idProperty.getFieldName(), source.getId());
Document object = new Document(idProperty.getFieldName(), source.getId());
ObjectPath objectPath = ObjectPath.ROOT.push(proxy, entity, null);
accessor.setProperty(idProperty, resolver.getValueInternal(idProperty, object, evaluator, objectPath));

View File

@@ -29,6 +29,7 @@ import java.util.List;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.bson.Document;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
@@ -45,11 +46,8 @@ import org.springframework.objenesis.ObjenesisStd;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.client.MongoDatabase;
/**
* A {@link DbRefResolver} that resolves {@link org.springframework.data.mongodb.core.mapping.DBRef}s by delegating to a
@@ -58,6 +56,7 @@ import com.mongodb.DBRef;
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @since 1.4
*/
public class DefaultDbRefResolver implements DbRefResolver {
@@ -113,7 +112,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#fetch(com.mongodb.DBRef)
*/
@Override
public DBObject fetch(DBRef dbRef) {
public Document fetch(DBRef dbRef) {
return ReflectiveDBRefResolver.fetch(mongoDbFactory, dbRef);
}
@@ -122,7 +121,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* @see org.springframework.data.mongodb.core.convert.DbRefResolver#bulkFetch(java.util.List)
*/
@Override
public List<DBObject> bulkFetch(List<DBRef> refs) {
public List<Document> bulkFetch(List<DBRef> refs) {
Assert.notNull(mongoDbFactory, "Factory must not be null!");
Assert.notNull(refs, "DBRef to fetch must not be null!");
@@ -144,9 +143,9 @@ public class DefaultDbRefResolver implements DbRefResolver {
ids.add(ref.getId());
}
DB db = mongoDbFactory.getDb();
List<DBObject> result = db.getCollection(collection)
.find(new BasicDBObjectBuilder().add("_id", new BasicDBObject("$in", ids)).get()).toArray();
MongoDatabase db = mongoDbFactory.getDb();
List<Document> result = new ArrayList<>();
db.getCollection(collection).find(new Document("_id", new Document("$in", ids))).into(result);
Collections.sort(result, new DbRefByReferencePositionComparator(ids));
return result;
}
@@ -439,20 +438,20 @@ public class DefaultDbRefResolver implements DbRefResolver {
}
/**
* {@link Comparator} for sorting {@link DBObject} that have been loaded in random order by a predefined list of
* {@link Comparator} for sorting {@link Document} that have been loaded in random order by a predefined list of
* reference identifiers.
*
* @author Christoph Strobl
* @author Oliver Gierke
* @since 1.10
*/
private static class DbRefByReferencePositionComparator implements Comparator<DBObject> {
private static class DbRefByReferencePositionComparator implements Comparator<Document> {
private final List<Object> reference;
/**
* Creates a new {@link DbRefByReferencePositionComparator} for the given list of reference identifiers.
*
*
* @param referenceIds must not be {@literal null}.
*/
public DbRefByReferencePositionComparator(List<Object> referenceIds) {
@@ -466,7 +465,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
public int compare(DBObject o1, DBObject o2) {
public int compare(Document o1, Document o2) {
return Integer.compare(reference.indexOf(o1.get("_id")), reference.indexOf(o2.get("_id")));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,25 +15,26 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.DBObject;
/**
* Default implementation of {@link DbRefResolverCallback}.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
class DefaultDbRefResolverCallback implements DbRefResolverCallback {
private final DBObject surroundingObject;
private final Bson surroundingObject;
private final ObjectPath path;
private final ValueResolver resolver;
private final SpELExpressionEvaluator evaluator;
/**
* Creates a new {@link DefaultDbRefResolverCallback} using the given {@link DBObject}, {@link ObjectPath},
* Creates a new {@link DefaultDbRefResolverCallback} using the given {@link Document}, {@link ObjectPath},
* {@link ValueResolver} and {@link SpELExpressionEvaluator}.
*
* @param surroundingObject must not be {@literal null}.
@@ -41,7 +42,7 @@ class DefaultDbRefResolverCallback implements DbRefResolverCallback {
* @param evaluator must not be {@literal null}.
* @param resolver must not be {@literal null}.
*/
public DefaultDbRefResolverCallback(DBObject surroundingObject, ObjectPath path, SpELExpressionEvaluator evaluator,
public DefaultDbRefResolverCallback(Bson surroundingObject, ObjectPath path, SpELExpressionEvaluator evaluator,
ValueResolver resolver) {
this.surroundingObject = surroundingObject;

View File

@@ -20,6 +20,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.SimpleTypeInformationMapper;
import org.springframework.data.convert.TypeAliasAccessor;
@@ -30,19 +32,20 @@ import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
* information in {@link DBObject}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
* respectively.
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implements MongoTypeMapper {
public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements MongoTypeMapper {
public static final String DEFAULT_TYPE_KEY = "_class";
@SuppressWarnings("rawtypes") //
@@ -50,7 +53,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
@SuppressWarnings("rawtypes") //
private static final TypeInformation<Map> MAP_TYPE_INFO = ClassTypeInformation.from(Map.class);
private final TypeAliasAccessor<DBObject> accessor;
private final TypeAliasAccessor<Bson> accessor;
private final String typeKey;
public DefaultMongoTypeMapper() {
@@ -62,15 +65,15 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
}
public DefaultMongoTypeMapper(String typeKey, MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext) {
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), mappingContext,
this(typeKey, new DocumentTypeAliasAccessor(typeKey), mappingContext,
Arrays.asList(new SimpleTypeInformationMapper()));
}
public DefaultMongoTypeMapper(String typeKey, List<? extends TypeInformationMapper> mappers) {
this(typeKey, new DBObjectTypeAliasAccessor(typeKey), null, mappers);
this(typeKey, new DocumentTypeAliasAccessor(typeKey), null, mappers);
}
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<DBObject> accessor,
private DefaultMongoTypeMapper(String typeKey, TypeAliasAccessor<Bson> accessor,
MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
List<? extends TypeInformationMapper> mappers) {
@@ -93,7 +96,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
* @see org.springframework.data.mongodb.core.convert.MongoTypeMapper#writeTypeRestrictions(java.util.Set)
*/
@Override
public void writeTypeRestrictions(DBObject result, Set<Class<?>> restrictedTypes) {
public void writeTypeRestrictions(Document result, Set<Class<?>> restrictedTypes) {
if (restrictedTypes == null || restrictedTypes.isEmpty()) {
return;
@@ -110,27 +113,28 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
}
}
accessor.writeTypeTo(result, new BasicDBObject("$in", restrictedMappedTypes));
accessor.writeTypeTo(result, new Document("$in", restrictedMappedTypes));
}
/* (non-Javadoc)
* @see org.springframework.data.convert.DefaultTypeMapper#getFallbackTypeFor(java.lang.Object)
*/
@Override
protected TypeInformation<?> getFallbackTypeFor(DBObject source) {
protected TypeInformation<?> getFallbackTypeFor(Bson source) {
return source instanceof BasicDBList ? LIST_TYPE_INFO : MAP_TYPE_INFO;
}
/**
* {@link TypeAliasAccessor} to store aliases in a {@link DBObject}.
* {@link TypeAliasAccessor} to store aliases in a {@link Document}.
*
* @author Oliver Gierke
*/
public static final class DBObjectTypeAliasAccessor implements TypeAliasAccessor<DBObject> {
public static final class DocumentTypeAliasAccessor implements TypeAliasAccessor<Bson> {
private final String typeKey;
public DBObjectTypeAliasAccessor(String typeKey) {
public DocumentTypeAliasAccessor(String typeKey) {
this.typeKey = typeKey;
}
@@ -138,22 +142,34 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<DBObject> implemen
* (non-Javadoc)
* @see org.springframework.data.convert.TypeAliasAccessor#readAliasFrom(java.lang.Object)
*/
public Object readAliasFrom(DBObject source) {
public Object readAliasFrom(Bson source) {
if (source instanceof BasicDBList) {
if (source instanceof List) {
return null;
}
return source.get(typeKey);
if (source instanceof Document) {
return ((Document) source).get(typeKey);
} else if (source instanceof DBObject) {
return ((DBObject) source).get(typeKey);
}
throw new IllegalArgumentException("Cannot read alias from " + source.getClass());
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.TypeAliasAccessor#writeTypeTo(java.lang.Object, java.lang.Object)
*/
public void writeTypeTo(DBObject sink, Object alias) {
public void writeTypeTo(Bson sink, Object alias) {
if (typeKey != null) {
sink.put(typeKey, alias);
if (sink instanceof Document) {
((Document) sink).put(typeKey, alias);
} else if (sink instanceof DBObject) {
((DBObject) sink).put(typeKey, alias);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -19,40 +19,47 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Wrapper value object for a {@link BasicDBObject} to be able to access raw values by {@link MongoPersistentProperty}
* Wrapper value object for a {@link Document} to be able to access raw values by {@link MongoPersistentProperty}
* references. The accessors will transparently resolve nested document values that a {@link MongoPersistentProperty}
* might refer to through a path expression in field names.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
class DBObjectAccessor {
class DocumentAccessor {
private final BasicDBObject dbObject;
private final Bson document;
/**
* Creates a new {@link DBObjectAccessor} for the given {@link DBObject}.
* Creates a new {@link DocumentAccessor} for the given {@link Document}.
*
* @param dbObject must be a {@link BasicDBObject} effectively, must not be {@literal null}.
* @param document must be a {@link Document} effectively, must not be {@literal null}.
*/
public DBObjectAccessor(DBObject dbObject) {
public DocumentAccessor(Bson document) {
Assert.notNull(dbObject, "DBObject must not be null!");
Assert.isInstanceOf(BasicDBObject.class, dbObject, "Given DBObject must be a BasicDBObject!");
Assert.notNull(document, "Document must not be null!");
this.dbObject = (BasicDBObject) dbObject;
if (!(document instanceof Document) && !(document instanceof DBObject)) {
Assert.isInstanceOf(Document.class, document, "Given Bson must be a Document or DBObject!");
}
this.document = document;
}
/**
* Puts the given value into the backing {@link DBObject} based on the coordinates defined through the given
* Puts the given value into the backing {@link Document} based on the coordinates defined through the given
* {@link MongoPersistentProperty}. By default this will be the plain field name. But field names might also consist
* of path traversals so we might need to create intermediate {@link BasicDBObject}s.
* of path traversals so we might need to create intermediate {@link BasicDocument}s.
*
* @param prop must not be {@literal null}.
* @param value
@@ -63,21 +70,21 @@ class DBObjectAccessor {
String fieldName = prop.getFieldName();
if (!fieldName.contains(".")) {
dbObject.put(fieldName, value);
BsonUtils.addToMap(document, fieldName, value);
return;
}
Iterator<String> parts = Arrays.asList(fieldName.split("\\.")).iterator();
DBObject dbObject = this.dbObject;
Bson document = this.document;
while (parts.hasNext()) {
String part = parts.next();
if (parts.hasNext()) {
dbObject = getOrCreateNestedDbObject(part, dbObject);
document = getOrCreateNestedDocument(part, document);
} else {
dbObject.put(part, value);
BsonUtils.addToMap(document, part, value);
}
}
}
@@ -95,11 +102,11 @@ class DBObjectAccessor {
String fieldName = property.getFieldName();
if (!fieldName.contains(".")) {
return this.dbObject.get(fieldName);
return BsonUtils.asMap(this.document).get(fieldName);
}
Iterator<String> parts = Arrays.asList(fieldName.split("\\.")).iterator();
Map<String, Object> source = this.dbObject;
Map<String, Object> source = BsonUtils.asMap(this.document);
Object result = null;
while (source != null && parts.hasNext()) {
@@ -115,9 +122,9 @@ class DBObjectAccessor {
}
/**
* Returns whether the underlying {@link DBObject} has a value ({@literal null} or non-{@literal null}) for the given
* Returns whether the underlying {@link Document} has a value ({@literal null} or non-{@literal null}) for the given
* {@link MongoPersistentProperty}.
*
*
* @param property must not be {@literal null}.
* @return
*/
@@ -128,11 +135,25 @@ class DBObjectAccessor {
String fieldName = property.getFieldName();
if (!fieldName.contains(".")) {
return this.dbObject.containsField(fieldName);
if (this.document instanceof Document) {
return ((Document) this.document).containsKey(fieldName);
}
if (this.document instanceof DBObject) {
return ((DBObject) this.document).containsField(fieldName);
}
}
String[] parts = fieldName.split("\\.");
Map<String, Object> source = this.dbObject;
Map<String, Object> source;
if (this.document instanceof Document) {
source = ((Document) this.document);
}else {
source = ((DBObject) this.document).toMap();
}
Object result = null;
for (int i = 1; i < parts.length; i++) {
@@ -149,7 +170,7 @@ class DBObjectAccessor {
}
/**
* Returns the given source object as map, i.e. {@link BasicDBObject}s and maps as is or {@literal null} otherwise.
* Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise.
*
* @param source can be {@literal null}.
* @return
@@ -157,6 +178,10 @@ class DBObjectAccessor {
@SuppressWarnings("unchecked")
private static Map<String, Object> getAsMap(Object source) {
if (source instanceof Document) {
return (Document) source;
}
if (source instanceof BasicDBObject) {
return (BasicDBObject) source;
}
@@ -169,23 +194,23 @@ class DBObjectAccessor {
}
/**
* Returns the {@link DBObject} which either already exists in the given source under the given key, or creates a new
* Returns the {@link Document} which either already exists in the given source under the given key, or creates a new
* nested one, registers it with the source and returns it.
*
* @param key must not be {@literal null} or empty.
* @param source must not be {@literal null}.
* @return
*/
private static DBObject getOrCreateNestedDbObject(String key, DBObject source) {
private static Document getOrCreateNestedDocument(String key, Bson source) {
Object existing = source.get(key);
Object existing = BsonUtils.asMap(source).get(key);
if (existing instanceof BasicDBObject) {
return (BasicDBObject) existing;
if (existing instanceof Document) {
return (Document) existing;
}
DBObject nested = new BasicDBObject();
source.put(key, nested);
Document nested = new Document();
BsonUtils.addToMap(source, key, nested);
return nested;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2016 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.
@@ -17,21 +17,21 @@ package org.springframework.data.mongodb.core.convert;
import java.util.Map;
import org.bson.Document;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import com.mongodb.DBObject;
/**
* {@link PropertyAccessor} to allow entity based field access to {@link DBObject}s.
* {@link PropertyAccessor} to allow entity based field access to {@link Document}s.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
class DBObjectPropertyAccessor extends MapAccessor {
class DocumentPropertyAccessor extends MapAccessor {
static final MapAccessor INSTANCE = new DBObjectPropertyAccessor();
static final MapAccessor INSTANCE = new DocumentPropertyAccessor();
/*
* (non-Javadoc)
@@ -39,7 +39,7 @@ class DBObjectPropertyAccessor extends MapAccessor {
*/
@Override
public Class<?>[] getSpecificTargetClasses() {
return new Class[] { DBObject.class };
return new Class[] { Document.class };
}
/*

View File

@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
@@ -44,8 +45,6 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Wrapper class to contain useful geo structure converters for the usage with Mongo.
@@ -70,27 +69,27 @@ abstract class GeoConverters {
@SuppressWarnings("unchecked")
public static Collection<? extends Object> getConvertersToRegister() {
return Arrays.asList( //
BoxToDbObjectConverter.INSTANCE //
, PolygonToDbObjectConverter.INSTANCE //
, CircleToDbObjectConverter.INSTANCE //
, SphereToDbObjectConverter.INSTANCE //
, DbObjectToBoxConverter.INSTANCE //
, DbObjectToPolygonConverter.INSTANCE //
, DbObjectToCircleConverter.INSTANCE //
, DbObjectToSphereConverter.INSTANCE //
, DbObjectToPointConverter.INSTANCE //
, PointToDbObjectConverter.INSTANCE //
, GeoCommandToDbObjectConverter.INSTANCE //
, GeoJsonToDbObjectConverter.INSTANCE //
, GeoJsonPointToDbObjectConverter.INSTANCE //
, GeoJsonPolygonToDbObjectConverter.INSTANCE //
, DbObjectToGeoJsonPointConverter.INSTANCE //
, DbObjectToGeoJsonPolygonConverter.INSTANCE //
, DbObjectToGeoJsonLineStringConverter.INSTANCE //
, DbObjectToGeoJsonMultiLineStringConverter.INSTANCE //
, DbObjectToGeoJsonMultiPointConverter.INSTANCE //
, DbObjectToGeoJsonMultiPolygonConverter.INSTANCE //
, DbObjectToGeoJsonGeometryCollectionConverter.INSTANCE);
BoxToDocumentConverter.INSTANCE //
, PolygonToDocumentConverter.INSTANCE //
, CircleToDocumentConverter.INSTANCE //
, SphereToDocumentConverter.INSTANCE //
, DocumentToBoxConverter.INSTANCE //
, DocumentToPolygonConverter.INSTANCE //
, DocumentToCircleConverter.INSTANCE //
, DocumentToSphereConverter.INSTANCE //
, DocumentToPointConverter.INSTANCE //
, PointToDocumentConverter.INSTANCE //
, GeoCommandToDocumentConverter.INSTANCE //
, GeoJsonToDocumentConverter.INSTANCE //
, GeoJsonPointToDocumentConverter.INSTANCE //
, GeoJsonPolygonToDocumentConverter.INSTANCE //
, DocumentToGeoJsonPointConverter.INSTANCE //
, DocumentToGeoJsonPolygonConverter.INSTANCE //
, DocumentToGeoJsonLineStringConverter.INSTANCE //
, DocumentToGeoJsonMultiLineStringConverter.INSTANCE //
, DocumentToGeoJsonMultiPointConverter.INSTANCE //
, DocumentToGeoJsonMultiPolygonConverter.INSTANCE //
, DocumentToGeoJsonGeometryCollectionConverter.INSTANCE);
}
/**
@@ -100,7 +99,7 @@ abstract class GeoConverters {
* @since 1.5
*/
@ReadingConverter
static enum DbObjectToPointConverter implements Converter<DBObject, Point> {
static enum DocumentToPointConverter implements Converter<Document, Point> {
INSTANCE;
@@ -109,7 +108,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Point convert(DBObject source) {
public Point convert(Document source) {
if (source == null) {
return null;
@@ -117,8 +116,8 @@ abstract class GeoConverters {
Assert.isTrue(source.keySet().size() == 2, "Source must contain 2 elements");
if (source.containsField("type")) {
return DbObjectToGeoJsonPointConverter.INSTANCE.convert(source);
if (source.containsKey("type")) {
return DocumentToGeoJsonPointConverter.INSTANCE.convert(source);
}
return new Point((Double) source.get("x"), (Double) source.get("y"));
@@ -131,7 +130,7 @@ abstract class GeoConverters {
* @author Thomas Darimont
* @since 1.5
*/
static enum PointToDbObjectConverter implements Converter<Point, DBObject> {
static enum PointToDocumentConverter implements Converter<Point, Document> {
INSTANCE;
@@ -140,8 +139,8 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Point source) {
return source == null ? null : new BasicDBObject("x", source.getX()).append("y", source.getY());
public Document convert(Point source) {
return source == null ? null : new Document("x", source.getX()).append("y", source.getY());
}
}
@@ -152,7 +151,7 @@ abstract class GeoConverters {
* @since 1.5
*/
@WritingConverter
static enum BoxToDbObjectConverter implements Converter<Box, DBObject> {
static enum BoxToDocumentConverter implements Converter<Box, Document> {
INSTANCE;
@@ -161,15 +160,15 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Box source) {
public Document convert(Box source) {
if (source == null) {
return null;
}
BasicDBObject result = new BasicDBObject();
result.put("first", PointToDbObjectConverter.INSTANCE.convert(source.getFirst()));
result.put("second", PointToDbObjectConverter.INSTANCE.convert(source.getSecond()));
Document result = new Document();
result.put("first", PointToDocumentConverter.INSTANCE.convert(source.getFirst()));
result.put("second", PointToDocumentConverter.INSTANCE.convert(source.getSecond()));
return result;
}
}
@@ -181,7 +180,7 @@ abstract class GeoConverters {
* @since 1.5
*/
@ReadingConverter
static enum DbObjectToBoxConverter implements Converter<DBObject, Box> {
static enum DocumentToBoxConverter implements Converter<Document, Box> {
INSTANCE;
@@ -190,14 +189,14 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Box convert(DBObject source) {
public Box convert(Document source) {
if (source == null) {
return null;
}
Point first = DbObjectToPointConverter.INSTANCE.convert((DBObject) source.get("first"));
Point second = DbObjectToPointConverter.INSTANCE.convert((DBObject) source.get("second"));
Point first = DocumentToPointConverter.INSTANCE.convert((Document) source.get("first"));
Point second = DocumentToPointConverter.INSTANCE.convert((Document) source.get("second"));
return new Box(first, second);
}
@@ -209,7 +208,7 @@ abstract class GeoConverters {
* @author Thomas Darimont
* @since 1.5
*/
static enum CircleToDbObjectConverter implements Converter<Circle, DBObject> {
static enum CircleToDocumentConverter implements Converter<Circle, Document> {
INSTANCE;
@@ -218,14 +217,14 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Circle source) {
public Document convert(Circle source) {
if (source == null) {
return null;
}
DBObject result = new BasicDBObject();
result.put("center", PointToDbObjectConverter.INSTANCE.convert(source.getCenter()));
Document result = new Document();
result.put("center", PointToDocumentConverter.INSTANCE.convert(source.getCenter()));
result.put("radius", source.getRadius().getNormalizedValue());
result.put("metric", source.getRadius().getMetric().toString());
return result;
@@ -233,13 +232,13 @@ abstract class GeoConverters {
}
/**
* Converts a {@link DBObject} into a {@link Circle}.
* Converts a {@link Document} into a {@link Circle}.
*
* @author Thomas Darimont
* @since 1.5
*/
@ReadingConverter
static enum DbObjectToCircleConverter implements Converter<DBObject, Circle> {
static enum DocumentToCircleConverter implements Converter<Document, Circle> {
INSTANCE;
@@ -248,18 +247,18 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Circle convert(DBObject source) {
public Circle convert(Document source) {
if (source == null) {
return null;
}
DBObject center = (DBObject) source.get("center");
Document center = (Document) source.get("center");
Double radius = (Double) source.get("radius");
Distance distance = new Distance(radius);
if (source.containsField("metric")) {
if (source.containsKey("metric")) {
String metricString = (String) source.get("metric");
Assert.notNull(metricString, "Metric must not be null!");
@@ -270,7 +269,7 @@ abstract class GeoConverters {
Assert.notNull(center, "Center must not be null!");
Assert.notNull(radius, "Radius must not be null!");
return new Circle(DbObjectToPointConverter.INSTANCE.convert(center), distance);
return new Circle(DocumentToPointConverter.INSTANCE.convert(center), distance);
}
}
@@ -280,7 +279,7 @@ abstract class GeoConverters {
* @author Thomas Darimont
* @since 1.5
*/
static enum SphereToDbObjectConverter implements Converter<Sphere, DBObject> {
static enum SphereToDocumentConverter implements Converter<Sphere, Document> {
INSTANCE;
@@ -289,14 +288,14 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Sphere source) {
public Document convert(Sphere source) {
if (source == null) {
return null;
}
DBObject result = new BasicDBObject();
result.put("center", PointToDbObjectConverter.INSTANCE.convert(source.getCenter()));
Document result = new Document();
result.put("center", PointToDocumentConverter.INSTANCE.convert(source.getCenter()));
result.put("radius", source.getRadius().getNormalizedValue());
result.put("metric", source.getRadius().getMetric().toString());
return result;
@@ -310,7 +309,7 @@ abstract class GeoConverters {
* @since 1.5
*/
@ReadingConverter
static enum DbObjectToSphereConverter implements Converter<DBObject, Sphere> {
static enum DocumentToSphereConverter implements Converter<Document, Sphere> {
INSTANCE;
@@ -319,18 +318,18 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public Sphere convert(DBObject source) {
public Sphere convert(Document source) {
if (source == null) {
return null;
}
DBObject center = (DBObject) source.get("center");
Document center = (Document) source.get("center");
Double radius = (Double) source.get("radius");
Distance distance = new Distance(radius);
if (source.containsField("metric")) {
if (source.containsKey("metric")) {
String metricString = (String) source.get("metric");
Assert.notNull(metricString, "Metric must not be null!");
@@ -341,7 +340,7 @@ abstract class GeoConverters {
Assert.notNull(center, "Center must not be null!");
Assert.notNull(radius, "Radius must not be null!");
return new Sphere(DbObjectToPointConverter.INSTANCE.convert(center), distance);
return new Sphere(DocumentToPointConverter.INSTANCE.convert(center), distance);
}
}
@@ -351,7 +350,7 @@ abstract class GeoConverters {
* @author Thomas Darimont
* @since 1.5
*/
static enum PolygonToDbObjectConverter implements Converter<Polygon, DBObject> {
static enum PolygonToDocumentConverter implements Converter<Polygon, Document> {
INSTANCE;
@@ -360,20 +359,20 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(Polygon source) {
public Document convert(Polygon source) {
if (source == null) {
return null;
}
List<Point> points = source.getPoints();
List<DBObject> pointTuples = new ArrayList<DBObject>(points.size());
List<Document> pointTuples = new ArrayList<Document>(points.size());
for (Point point : points) {
pointTuples.add(PointToDbObjectConverter.INSTANCE.convert(point));
pointTuples.add(PointToDocumentConverter.INSTANCE.convert(point));
}
DBObject result = new BasicDBObject();
Document result = new Document();
result.put("points", pointTuples);
return result;
}
@@ -386,7 +385,7 @@ abstract class GeoConverters {
* @since 1.5
*/
@ReadingConverter
static enum DbObjectToPolygonConverter implements Converter<DBObject, Polygon> {
static enum DocumentToPolygonConverter implements Converter<Document, Polygon> {
INSTANCE;
@@ -396,19 +395,19 @@ abstract class GeoConverters {
*/
@Override
@SuppressWarnings({ "unchecked" })
public Polygon convert(DBObject source) {
public Polygon convert(Document source) {
if (source == null) {
return null;
}
List<DBObject> points = (List<DBObject>) source.get("points");
List<Document> points = (List<Document>) source.get("points");
List<Point> newPoints = new ArrayList<Point>(points.size());
for (DBObject element : points) {
for (Document element : points) {
Assert.notNull(element, "Point elements of polygon must not be null!");
newPoints.add(DbObjectToPointConverter.INSTANCE.convert(element));
newPoints.add(DocumentToPointConverter.INSTANCE.convert(element));
}
return new Polygon(newPoints);
@@ -421,7 +420,7 @@ abstract class GeoConverters {
* @author Thomas Darimont
* @since 1.5
*/
static enum GeoCommandToDbObjectConverter implements Converter<GeoCommand, DBObject> {
static enum GeoCommandToDocumentConverter implements Converter<GeoCommand, Document> {
INSTANCE;
@@ -431,18 +430,18 @@ abstract class GeoConverters {
*/
@Override
@SuppressWarnings("rawtypes")
public DBObject convert(GeoCommand source) {
public Document convert(GeoCommand source) {
if (source == null) {
return null;
}
BasicDBList argument = new BasicDBList();
List argument = new ArrayList();
Shape shape = source.getShape();
if (shape instanceof GeoJson) {
return GeoJsonToDbObjectConverter.INSTANCE.convert((GeoJson) shape);
return GeoJsonToDocumentConverter.INSTANCE.convert((GeoJson) shape);
}
if (shape instanceof Box) {
@@ -472,7 +471,7 @@ abstract class GeoConverters {
argument.add(((Sphere) shape).getRadius().getNormalizedValue());
}
return new BasicDBObject(source.getCommand(), argument);
return new Document(source.getCommand(), argument);
}
}
@@ -481,7 +480,7 @@ abstract class GeoConverters {
* @since 1.7
*/
@SuppressWarnings("rawtypes")
static enum GeoJsonToDbObjectConverter implements Converter<GeoJson, DBObject> {
static enum GeoJsonToDocumentConverter implements Converter<GeoJson, Document> {
INSTANCE;
@@ -490,17 +489,17 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(GeoJson source) {
public Document convert(GeoJson source) {
if (source == null) {
return null;
}
DBObject dbo = new BasicDBObject("type", source.getType());
Document dbo = new Document("type", source.getType());
if (source instanceof GeoJsonGeometryCollection) {
BasicDBList dbl = new BasicDBList();
List dbl = new ArrayList();
for (GeoJson geometry : ((GeoJsonGeometryCollection) source).getCoordinates()) {
dbl.add(convert(geometry));
@@ -523,7 +522,7 @@ abstract class GeoConverters {
if (candidate instanceof Iterable) {
BasicDBList dbl = new BasicDBList();
List dbl = new ArrayList();
for (Object element : (Iterable) candidate) {
dbl.add(convertIfNecessarry(element));
@@ -544,7 +543,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum GeoJsonPointToDbObjectConverter implements Converter<GeoJsonPoint, DBObject> {
static enum GeoJsonPointToDocumentConverter implements Converter<GeoJsonPoint, Document> {
INSTANCE;
@@ -553,8 +552,8 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(GeoJsonPoint source) {
return GeoJsonToDbObjectConverter.INSTANCE.convert(source);
public Document convert(GeoJsonPoint source) {
return GeoJsonToDocumentConverter.INSTANCE.convert(source);
}
}
@@ -562,7 +561,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum GeoJsonPolygonToDbObjectConverter implements Converter<GeoJsonPolygon, DBObject> {
static enum GeoJsonPolygonToDocumentConverter implements Converter<GeoJsonPolygon, Document> {
INSTANCE;
@@ -571,8 +570,8 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public DBObject convert(GeoJsonPolygon source) {
return GeoJsonToDbObjectConverter.INSTANCE.convert(source);
public Document convert(GeoJsonPolygon source) {
return GeoJsonToDocumentConverter.INSTANCE.convert(source);
}
}
@@ -580,7 +579,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonPointConverter implements Converter<DBObject, GeoJsonPoint> {
static enum DocumentToGeoJsonPointConverter implements Converter<Document, GeoJsonPoint> {
INSTANCE;
@@ -590,7 +589,7 @@ abstract class GeoConverters {
*/
@Override
@SuppressWarnings("unchecked")
public GeoJsonPoint convert(DBObject source) {
public GeoJsonPoint convert(Document source) {
if (source == null) {
return null;
@@ -608,7 +607,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonPolygonConverter implements Converter<DBObject, GeoJsonPolygon> {
static enum DocumentToGeoJsonPolygonConverter implements Converter<Document, GeoJsonPolygon> {
INSTANCE;
@@ -617,7 +616,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public GeoJsonPolygon convert(DBObject source) {
public GeoJsonPolygon convert(Document source) {
if (source == null) {
return null;
@@ -626,7 +625,7 @@ abstract class GeoConverters {
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "Polygon"),
String.format("Cannot convert type '%s' to Polygon.", source.get("type")));
return toGeoJsonPolygon((BasicDBList) source.get("coordinates"));
return toGeoJsonPolygon((List) source.get("coordinates"));
}
}
@@ -634,7 +633,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonMultiPolygonConverter implements Converter<DBObject, GeoJsonMultiPolygon> {
static enum DocumentToGeoJsonMultiPolygonConverter implements Converter<Document, GeoJsonMultiPolygon> {
INSTANCE;
@@ -643,7 +642,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public GeoJsonMultiPolygon convert(DBObject source) {
public GeoJsonMultiPolygon convert(Document source) {
if (source == null) {
return null;
@@ -652,11 +651,11 @@ abstract class GeoConverters {
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "MultiPolygon"),
String.format("Cannot convert type '%s' to MultiPolygon.", source.get("type")));
BasicDBList dbl = (BasicDBList) source.get("coordinates");
List dbl = (List) source.get("coordinates");
List<GeoJsonPolygon> polygones = new ArrayList<GeoJsonPolygon>();
for (Object polygon : dbl) {
polygones.add(toGeoJsonPolygon((BasicDBList) polygon));
polygones.add(toGeoJsonPolygon((List) polygon));
}
return new GeoJsonMultiPolygon(polygones);
@@ -667,7 +666,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonLineStringConverter implements Converter<DBObject, GeoJsonLineString> {
static enum DocumentToGeoJsonLineStringConverter implements Converter<Document, GeoJsonLineString> {
INSTANCE;
@@ -676,7 +675,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public GeoJsonLineString convert(DBObject source) {
public GeoJsonLineString convert(Document source) {
if (source == null) {
return null;
@@ -685,7 +684,7 @@ abstract class GeoConverters {
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "LineString"),
String.format("Cannot convert type '%s' to LineString.", source.get("type")));
BasicDBList cords = (BasicDBList) source.get("coordinates");
List cords = (List) source.get("coordinates");
return new GeoJsonLineString(toListOfPoint(cords));
}
@@ -695,7 +694,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonMultiPointConverter implements Converter<DBObject, GeoJsonMultiPoint> {
static enum DocumentToGeoJsonMultiPointConverter implements Converter<Document, GeoJsonMultiPoint> {
INSTANCE;
@@ -704,7 +703,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public GeoJsonMultiPoint convert(DBObject source) {
public GeoJsonMultiPoint convert(Document source) {
if (source == null) {
return null;
@@ -713,7 +712,7 @@ abstract class GeoConverters {
Assert.isTrue(ObjectUtils.nullSafeEquals(source.get("type"), "MultiPoint"),
String.format("Cannot convert type '%s' to MultiPoint.", source.get("type")));
BasicDBList cords = (BasicDBList) source.get("coordinates");
List cords = (List) source.get("coordinates");
return new GeoJsonMultiPoint(toListOfPoint(cords));
}
@@ -723,7 +722,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonMultiLineStringConverter implements Converter<DBObject, GeoJsonMultiLineString> {
static enum DocumentToGeoJsonMultiLineStringConverter implements Converter<Document, GeoJsonMultiLineString> {
INSTANCE;
@@ -732,7 +731,7 @@ abstract class GeoConverters {
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
@Override
public GeoJsonMultiLineString convert(DBObject source) {
public GeoJsonMultiLineString convert(Document source) {
if (source == null) {
return null;
@@ -742,10 +741,10 @@ abstract class GeoConverters {
String.format("Cannot convert type '%s' to MultiLineString.", source.get("type")));
List<GeoJsonLineString> lines = new ArrayList<GeoJsonLineString>();
BasicDBList cords = (BasicDBList) source.get("coordinates");
List cords = (List) source.get("coordinates");
for (Object line : cords) {
lines.add(new GeoJsonLineString(toListOfPoint((BasicDBList) line)));
lines.add(new GeoJsonLineString(toListOfPoint((List) line)));
}
return new GeoJsonMultiLineString(lines);
}
@@ -755,7 +754,7 @@ abstract class GeoConverters {
* @author Christoph Strobl
* @since 1.7
*/
static enum DbObjectToGeoJsonGeometryCollectionConverter implements Converter<DBObject, GeoJsonGeometryCollection> {
static enum DocumentToGeoJsonGeometryCollectionConverter implements Converter<Document, GeoJsonGeometryCollection> {
INSTANCE;
@@ -765,7 +764,7 @@ abstract class GeoConverters {
*/
@SuppressWarnings("rawtypes")
@Override
public GeoJsonGeometryCollection convert(DBObject source) {
public GeoJsonGeometryCollection convert(Document source) {
if (source == null) {
return null;
@@ -776,36 +775,36 @@ abstract class GeoConverters {
List<GeoJson<?>> geometries = new ArrayList<GeoJson<?>>();
for (Object o : (List) source.get("geometries")) {
geometries.add(convertGeometries((DBObject) o));
geometries.add(convertGeometries((Document) o));
}
return new GeoJsonGeometryCollection(geometries);
}
private static GeoJson<?> convertGeometries(DBObject source) {
private static GeoJson<?> convertGeometries(Document source) {
Object type = source.get("type");
if (ObjectUtils.nullSafeEquals(type, "Point")) {
return DbObjectToGeoJsonPointConverter.INSTANCE.convert(source);
return DocumentToGeoJsonPointConverter.INSTANCE.convert(source);
}
if (ObjectUtils.nullSafeEquals(type, "MultiPoint")) {
return DbObjectToGeoJsonMultiPointConverter.INSTANCE.convert(source);
return DocumentToGeoJsonMultiPointConverter.INSTANCE.convert(source);
}
if (ObjectUtils.nullSafeEquals(type, "LineString")) {
return DbObjectToGeoJsonLineStringConverter.INSTANCE.convert(source);
return DocumentToGeoJsonLineStringConverter.INSTANCE.convert(source);
}
if (ObjectUtils.nullSafeEquals(type, "MultiLineString")) {
return DbObjectToGeoJsonMultiLineStringConverter.INSTANCE.convert(source);
return DocumentToGeoJsonMultiLineStringConverter.INSTANCE.convert(source);
}
if (ObjectUtils.nullSafeEquals(type, "Polygon")) {
return DbObjectToGeoJsonPolygonConverter.INSTANCE.convert(source);
return DocumentToGeoJsonPolygonConverter.INSTANCE.convert(source);
}
if (ObjectUtils.nullSafeEquals(type, "MultiPolygon")) {
return DbObjectToGeoJsonMultiPolygonConverter.INSTANCE.convert(source);
return DocumentToGeoJsonMultiPolygonConverter.INSTANCE.convert(source);
}
throw new IllegalArgumentException(String.format("Cannot convert unknown GeoJson type %s", type));
@@ -824,7 +823,7 @@ abstract class GeoConverters {
* @since 1.7
*/
@SuppressWarnings("unchecked")
static List<Point> toListOfPoint(BasicDBList listOfCoordinatePairs) {
static List<Point> toListOfPoint(List listOfCoordinatePairs) {
List<Point> points = new ArrayList<Point>();
@@ -846,7 +845,7 @@ abstract class GeoConverters {
* @return
* @since 1.7
*/
static GeoJsonPolygon toGeoJsonPolygon(BasicDBList dbList) {
return new GeoJsonPolygon(toListOfPoint((BasicDBList) dbList.get(0)));
static GeoJsonPolygon toGeoJsonPolygon(List dbList) {
return new GeoJsonPolygon(toListOfPoint((List) dbList.get(0)));
}
}

View File

@@ -26,6 +26,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
@@ -64,6 +66,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
@@ -72,7 +75,7 @@ import com.mongodb.DBRef;
/**
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}.
* {@link Document}.
*
* @author Oliver Gierke
* @author Jon Brisbin
@@ -80,6 +83,7 @@ import com.mongodb.DBRef;
* @author Thomas Darimont
* @author Christoph Strobl
* @author Jordi Llach
* @author Mark Paluch
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {
@@ -101,7 +105,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}.
*
* @param mongoDbFactory must not be {@literal null}.
* @param dbRefResolver must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
*/
public MappingMongoConverter(DbRefResolver dbRefResolver,
@@ -117,7 +121,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext);
this.idMapper = new QueryMapper(this);
this.spELContext = new SpELContext(DBObjectPropertyAccessor.INSTANCE);
this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
}
/**
@@ -134,8 +138,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Configures the {@link MongoTypeMapper} to be used to add type information to {@link DBObject}s created by the
* converter and how to lookup type information from {@link DBObject}s when reading them. Uses a
* Configures the {@link MongoTypeMapper} to be used to add type information to {@link Document}s created by the
* converter and how to lookup type information from {@link Document}s when reading them. Uses a
* {@link DefaultMongoTypeMapper} by default. Setting this to {@literal null} will reset the {@link TypeMapper} to the
* default one.
*
@@ -187,46 +191,53 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.MongoReader#read(java.lang.Class, com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.core.MongoReader#read(java.lang.Class, com.mongodb.Document)
*/
public <S extends Object> S read(Class<S> clazz, final DBObject dbo) {
return read(ClassTypeInformation.from(clazz), dbo);
public <S extends Object> S read(Class<S> clazz, final Bson bson) {
return read(ClassTypeInformation.from(clazz), bson);
}
protected <S extends Object> S read(TypeInformation<S> type, DBObject dbo) {
return read(type, dbo, ObjectPath.ROOT);
protected <S extends Object> S read(TypeInformation<S> type, Bson bson) {
return read(type, bson, ObjectPath.ROOT);
}
@SuppressWarnings("unchecked")
private <S extends Object> S read(TypeInformation<S> type, DBObject dbo, ObjectPath path) {
private <S extends Object> S read(TypeInformation<S> type, Bson bson, ObjectPath path) {
if (null == dbo) {
if (null == bson) {
return null;
}
TypeInformation<? extends S> typeToUse = typeMapper.readType(dbo, type);
TypeInformation<? extends S> typeToUse = typeMapper.readType(bson, type);
Class<? extends S> rawType = typeToUse.getType();
if (conversions.hasCustomReadTarget(dbo.getClass(), rawType)) {
return conversionService.convert(dbo, rawType);
if (conversions.hasCustomReadTarget(bson.getClass(), rawType)) {
return conversionService.convert(bson, rawType);
}
if (DBObject.class.isAssignableFrom(rawType)) {
return (S) dbo;
return (S) bson;
}
if (typeToUse.isCollectionLike() && dbo instanceof BasicDBList) {
return (S) readCollectionOrArray(typeToUse, (BasicDBList) dbo, path);
if (Document.class.isAssignableFrom(rawType)) {
return (S) bson;
}
if (typeToUse.isCollectionLike() && bson instanceof List) {
return (S) readCollectionOrArray(typeToUse, (List) bson, path);
}
if (typeToUse.isMap()) {
return (S) readMap(typeToUse, dbo, path);
return (S) readMap(typeToUse, bson, path);
}
if (dbo instanceof BasicDBList) {
throw new MappingException(String.format(INCOMPATIBLE_TYPES, dbo, BasicDBList.class, typeToUse.getType(), path));
if (bson instanceof Collection) {
throw new MappingException(String.format(INCOMPATIBLE_TYPES, bson, BasicDBList.class, typeToUse.getType(), path));
}
if (typeToUse.equals(ClassTypeInformation.OBJECT)) {
return (S) bson;
}
// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext
.getPersistentEntity(typeToUse);
@@ -234,11 +245,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
return read(persistentEntity, dbo, path);
return read(persistentEntity, bson, path);
}
private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
DBObject source, DefaultSpELExpressionEvaluator evaluator, ObjectPath path) {
Bson source, DefaultSpELExpressionEvaluator evaluator, ObjectPath path) {
MongoDbPropertyValueProvider provider = new MongoDbPropertyValueProvider(source, evaluator, path);
PersistentEntityParameterValueProvider<MongoPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<MongoPersistentProperty>(
@@ -248,11 +259,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
path);
}
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final DBObject dbo, final ObjectPath path) {
private <S extends Object> S read(final MongoPersistentEntity<S> entity, final Bson bson, final ObjectPath path) {
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(dbo, spELContext);
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(bson, spELContext);
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, dbo, evaluator, path);
ParameterValueProvider<MongoPersistentProperty> provider = getParameterProvider(entity, bson, evaluator, path);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, provider);
@@ -264,14 +275,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
// make sure id property is set before all other properties
Object idValue = null;
final DBObjectAccessor dbObjectAccessor = new DBObjectAccessor(dbo);
DocumentAccessor documentAccessor = new DocumentAccessor(bson);
if (idProperty != null && dbObjectAccessor.hasValue(idProperty)) {
idValue = getValueInternal(idProperty, dbo, evaluator, path);
if (idProperty != null && documentAccessor.hasValue(idProperty)) {
idValue = getValueInternal(idProperty, bson, evaluator, path);
accessor.setProperty(idProperty, idValue);
}
final ObjectPath currentPath = path.push(result, entity, idValue != null ? dbObjectAccessor.get(idProperty) : null);
final ObjectPath currentPath = path.push(result, entity, idValue != null ? documentAccessor.get(idProperty) : null);
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@@ -282,11 +293,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return;
}
if (entity.isConstructorArgument(prop) || !dbObjectAccessor.hasValue(prop)) {
if (entity.isConstructorArgument(prop) || !documentAccessor.hasValue(prop)) {
return;
}
accessor.setProperty(prop, getValueInternal(prop, dbo, evaluator, currentPath));
accessor.setProperty(prop, getValueInternal(prop, bson, evaluator, currentPath));
}
});
@@ -295,7 +306,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
public void doWithAssociation(Association<MongoPersistentProperty> association) {
final MongoPersistentProperty property = association.getInverse();
Object value = dbObjectAccessor.get(property);
Object value = documentAccessor.get(property);
if (value == null || entity.isConstructorArgument(property)) {
return;
@@ -305,7 +316,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
DbRefProxyHandler handler = new DefaultDbRefProxyHandler(spELContext, mappingContext,
MappingMongoConverter.this);
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(dbo, currentPath, evaluator,
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(bson, currentPath, evaluator,
MappingMongoConverter.this);
accessor.setProperty(property, dbRefResolver.resolveDbRef(property, dbref, callback, handler));
@@ -337,68 +348,71 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Root entry method into write conversion. Adds a type discriminator to the {@link DBObject}. Shouldn't be called for
* Root entry method into write conversion. Adds a type discriminator to the {@link Document}. Shouldn't be called for
* nested conversions.
*
* @see org.springframework.data.mongodb.core.core.convert.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
* @see org.springframework.data.mongodb.core.core.convert.MongoWriter#write(java.lang.Object, com.mongodb.Document)
*/
public void write(final Object obj, final DBObject dbo) {
public void write(final Object obj, final Bson bson) {
if (null == obj) {
return;
}
Class<?> entityType = obj.getClass();
boolean handledByCustomConverter = conversions.getCustomWriteTarget(entityType, DBObject.class) != null;
Class<?> entityType = ClassUtils.getUserClass(obj.getClass());
TypeInformation<? extends Object> type = ClassTypeInformation.from(entityType);
if (!handledByCustomConverter && !(dbo instanceof BasicDBList)) {
typeMapper.writeType(type, dbo);
}
Object target = obj instanceof LazyLoadingProxy ? ((LazyLoadingProxy) obj).getTarget() : obj;
writeInternal(target, dbo, type);
writeInternal(target, bson, type);
if (asMap(bson).containsKey("_is") && asMap(bson).get("_id") == null) {
removeFromMap(bson, "_id");
}
boolean handledByCustomConverter = conversions.getCustomWriteTarget(entityType, Document.class) != null;
if (!handledByCustomConverter && !(bson instanceof Collection)) {
typeMapper.writeType(type, bson);
}
}
/**
* Internal write conversion method which should be used for nested invocations.
*
* @param obj
* @param dbo
* @param bson
*/
@SuppressWarnings("unchecked")
protected void writeInternal(final Object obj, final DBObject dbo, final TypeInformation<?> typeHint) {
protected void writeInternal(final Object obj, final Bson bson, final TypeInformation<?> typeHint) {
if (null == obj) {
return;
}
Class<?> entityType = obj.getClass();
Class<?> customTarget = conversions.getCustomWriteTarget(entityType, DBObject.class);
Class<?> customTarget = conversions.getCustomWriteTarget(entityType, Document.class);
if (customTarget != null) {
DBObject result = conversionService.convert(obj, DBObject.class);
dbo.putAll(result);
Document result = conversionService.convert(obj, Document.class);
addAllToMap(bson, result);
return;
}
if (Map.class.isAssignableFrom(entityType)) {
writeMapInternal((Map<Object, Object>) obj, dbo, ClassTypeInformation.MAP);
writeMapInternal((Map<Object, Object>) obj, bson, ClassTypeInformation.MAP);
return;
}
if (Collection.class.isAssignableFrom(entityType)) {
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (BasicDBList) dbo);
writeCollectionInternal((Collection<?>) obj, ClassTypeInformation.LIST, (List) bson);
return;
}
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType);
writeInternal(obj, dbo, entity);
addCustomTypeKeyIfNecessary(typeHint, obj, dbo);
writeInternal(obj, bson, entity);
addCustomTypeKeyIfNecessary(typeHint, obj, bson);
}
protected void writeInternal(Object obj, final DBObject dbo, MongoPersistentEntity<?> entity) {
protected void writeInternal(Object obj, final Bson bson, MongoPersistentEntity<?> entity) {
if (obj == null) {
return;
@@ -411,11 +425,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(obj);
final MongoPersistentProperty idProperty = entity.getIdProperty();
if (!dbo.containsField("_id") && null != idProperty) {
if (!asMap(bson).containsKey("_id") && null != idProperty) {
try {
Object id = accessor.getProperty(idProperty);
dbo.put("_id", idMapper.convertId(id));
addToMap(bson, "_id", idMapper.convertId(id));
} catch (ConversionException ignored) {}
}
@@ -432,9 +446,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (null != propertyObj) {
if (!conversions.isSimpleType(propertyObj.getClass())) {
writePropertyInternal(propertyObj, dbo, prop);
writePropertyInternal(propertyObj, bson, prop);
} else {
writeSimpleInternal(propertyObj, dbo, prop);
writeSimpleInternal(propertyObj, bson, prop);
}
}
}
@@ -448,32 +462,32 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Object propertyObj = accessor.getProperty(inverseProp);
if (null != propertyObj) {
writePropertyInternal(propertyObj, dbo, inverseProp);
writePropertyInternal(propertyObj, bson, inverseProp);
}
}
});
}
@SuppressWarnings({ "unchecked" })
protected void writePropertyInternal(Object obj, DBObject dbo, MongoPersistentProperty prop) {
protected void writePropertyInternal(Object obj, Bson bson, MongoPersistentProperty prop) {
if (obj == null) {
return;
}
DBObjectAccessor accessor = new DBObjectAccessor(dbo);
DocumentAccessor accessor = new DocumentAccessor(bson);
TypeInformation<?> valueType = ClassTypeInformation.from(obj.getClass());
TypeInformation<?> type = prop.getTypeInformation();
if (valueType.isCollectionLike()) {
DBObject collectionInternal = createCollection(asCollection(obj), prop);
List collectionInternal = createCollection(asCollection(obj), prop);
accessor.put(prop, collectionInternal);
return;
}
if (valueType.isMap()) {
DBObject mapDbObj = createMap((Map<Object, Object>) obj, prop);
Bson mapDbObj = createMap((Map<Object, Object>) obj, prop);
accessor.put(prop, mapDbObj);
return;
}
@@ -514,15 +528,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
Object existingValue = accessor.get(prop);
BasicDBObject propDbObj = existingValue instanceof BasicDBObject ? (BasicDBObject) existingValue
: new BasicDBObject();
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, propDbObj);
Document document = existingValue instanceof Document ? (Document) existingValue : new Document();
MongoPersistentEntity<?> entity = isSubtype(prop.getType(), obj.getClass())
? mappingContext.getPersistentEntity(obj.getClass()) : mappingContext.getPersistentEntity(type);
writeInternal(obj, propDbObj, entity);
accessor.put(prop, propDbObj);
writeInternal(obj, document, entity);
addCustomTypeKeyIfNecessary(ClassTypeInformation.from(prop.getRawType()), obj, document);
accessor.put(prop, document);
}
private boolean isSubtype(Class<?> left, Class<?> right) {
@@ -553,13 +566,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param property must not be {@literal null}.
* @return
*/
protected DBObject createCollection(Collection<?> collection, MongoPersistentProperty property) {
protected List<Object> createCollection(Collection<?> collection, MongoPersistentProperty property) {
if (!property.isDbReference()) {
return writeCollectionInternal(collection, property.getTypeInformation(), new BasicDBList());
return writeCollectionInternal(collection, property.getTypeInformation(), new ArrayList());
}
BasicDBList dbList = new BasicDBList();
List<Object> dbList = new ArrayList<Object>();
for (Object element : collection) {
@@ -581,16 +594,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param property must not be {@literal null}.
* @return
*/
protected DBObject createMap(Map<Object, Object> map, MongoPersistentProperty property) {
protected Bson createMap(Map<Object, Object> map, MongoPersistentProperty property) {
Assert.notNull(map, "Given map must not be null!");
Assert.notNull(property, "PersistentProperty must not be null!");
if (!property.isDbReference()) {
return writeMapInternal(map, new BasicDBObject(), property.getTypeInformation());
return writeMapInternal(map, new Document(), property.getTypeInformation());
}
BasicDBObject dbObject = new BasicDBObject();
Document document = new Document();
for (Map.Entry<Object, Object> entry : map.entrySet()) {
@@ -600,14 +613,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (conversions.isSimpleType(key.getClass())) {
String simpleKey = prepareMapKey(key.toString());
dbObject.put(simpleKey, value != null ? createDBRef(value, property) : null);
document.put(simpleKey, value != null ? createDBRef(value, property) : null);
} else {
throw new MappingException("Cannot use a complex object as a key value.");
}
}
return dbObject;
return document;
}
/**
@@ -618,7 +631,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param sink the {@link BasicDBList} to write to.
* @return
*/
private BasicDBList writeCollectionInternal(Collection<?> source, TypeInformation<?> type, BasicDBList sink) {
private List writeCollectionInternal(Collection<?> source, TypeInformation<?> type, List sink) {
TypeInformation<?> componentType = type == null ? null : type.getComponentType();
@@ -631,9 +644,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
} else if (element instanceof Collection || elementType.isArray()) {
sink.add(writeCollectionInternal(asCollection(element), componentType, new BasicDBList()));
} else {
BasicDBObject propDbObj = new BasicDBObject();
writeInternal(element, propDbObj, componentType);
sink.add(propDbObj);
Document document = new Document();
writeInternal(element, document, componentType);
sink.add(document);
}
}
@@ -641,14 +654,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Writes the given {@link Map} to the given {@link DBObject} considering the given {@link TypeInformation}.
* Writes the given {@link Map} to the given {@link Document} considering the given {@link TypeInformation}.
*
* @param obj must not be {@literal null}.
* @param dbo must not be {@literal null}.
* @param bson must not be {@literal null}.
* @param propertyType must not be {@literal null}.
* @return
*/
protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeInformation<?> propertyType) {
protected Bson writeMapInternal(Map<Object, Object> obj, Bson bson, TypeInformation<?> propertyType) {
for (Map.Entry<Object, Object> entry : obj.entrySet()) {
@@ -659,23 +672,23 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
String simpleKey = prepareMapKey(key);
if (val == null || conversions.isSimpleType(val.getClass())) {
writeSimpleInternal(val, dbo, simpleKey);
writeSimpleInternal(val, bson, simpleKey);
} else if (val instanceof Collection || val.getClass().isArray()) {
dbo.put(simpleKey,
addToMap(bson, simpleKey,
writeCollectionInternal(asCollection(val), propertyType.getMapValueType(), new BasicDBList()));
} else {
DBObject newDbo = new BasicDBObject();
Document document = new Document();
TypeInformation<?> valueTypeInfo = propertyType.isMap() ? propertyType.getMapValueType()
: ClassTypeInformation.OBJECT;
writeInternal(val, newDbo, valueTypeInfo);
dbo.put(simpleKey, newDbo);
writeInternal(val, document, valueTypeInfo);
addToMap(bson, simpleKey, document);
}
} else {
throw new MappingException("Cannot use a complex object as a key value.");
}
}
return dbo;
return bson;
}
/**
@@ -745,14 +758,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Adds custom type information to the given {@link DBObject} if necessary. That is if the value is not the same as
* Adds custom type information to the given {@link Document} if necessary. That is if the value is not the same as
* the one given. This is usually the case if you store a subtype of the actual declared type of the property.
*
* @param type
* @param value must not be {@literal null}.
* @param dbObject must not be {@literal null}.
* @param bson must not be {@literal null}.
*/
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, DBObject dbObject) {
protected void addCustomTypeKeyIfNecessary(TypeInformation<?> type, Object value, Bson bson) {
TypeInformation<?> actualType = type != null ? type.getActualType() : null;
Class<?> reference = actualType == null ? Object.class : actualType.getType();
@@ -760,23 +773,23 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
boolean notTheSameClass = !valueType.equals(reference);
if (notTheSameClass) {
typeMapper.writeType(valueType, dbObject);
typeMapper.writeType(valueType, bson);
}
}
/**
* Writes the given simple value to the given {@link DBObject}. Will store enum names for enum values.
* Writes the given simple value to the given {@link Document}. Will store enum names for enum values.
*
* @param value
* @param dbObject must not be {@literal null}.
* @param bson must not be {@literal null}.
* @param key must not be {@literal null}.
*/
private void writeSimpleInternal(Object value, DBObject dbObject, String key) {
dbObject.put(key, getPotentiallyConvertedSimpleWrite(value));
private void writeSimpleInternal(Object value, Bson bson, String key) {
addToMap(bson, key, getPotentiallyConvertedSimpleWrite(value));
}
private void writeSimpleInternal(Object value, DBObject dbObject, MongoPersistentProperty property) {
DBObjectAccessor accessor = new DBObjectAccessor(dbObject);
private void writeSimpleInternal(Object value, Bson bson, MongoPersistentProperty property) {
DocumentAccessor accessor = new DocumentAccessor(bson);
accessor.put(property, getPotentiallyConvertedSimpleWrite(value));
}
@@ -797,7 +810,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (customTarget != null) {
return conversionService.convert(value, customTarget);
} else {
} else if (ObjectUtils.isArray(value)) {
if (value instanceof byte[]) {
return value;
}
return asCollection(value);
}
else {
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value;
}
}
@@ -868,12 +889,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.DBObject, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object)
* @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object)
*/
@Override
public Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator evaluator,
public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
ObjectPath path) {
return new MongoDbPropertyValueProvider(dbo, evaluator, path).getPropertyValue(prop);
return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop);
}
/**
@@ -885,17 +906,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @return the converted {@link Collection} or array, will never be {@literal null}.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList sourceValue, ObjectPath path) {
private Object readCollectionOrArray(TypeInformation<?> targetType, List sourceValue, ObjectPath path) {
Assert.notNull(targetType, "Target type must not be null!");
Assert.notNull(path, "Object path must not be null!");
Class<?> collectionType = targetType.getType();
if (sourceValue.isEmpty()) {
return getPotentiallyConvertedSimpleRead(new HashSet<Object>(), collectionType);
}
TypeInformation<?> componentType = targetType.getComponentType();
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
@@ -903,6 +920,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>()
: CollectionFactory.createCollection(collectionType, rawComponentType, sourceValue.size());
if (sourceValue.isEmpty()) {
return getPotentiallyConvertedSimpleRead(items, collectionType);
}
if (!DBRef.class.equals(rawComponentType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceValue)) {
return bulkReadAndConvertDBRefs((List<DBRef>) (List) (sourceValue), componentType, path, rawComponentType);
}
@@ -910,13 +931,26 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
for (Object dbObjItem : sourceValue) {
if (dbObjItem instanceof DBRef) {
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem
: readAndConvertDBRef((DBRef) dbObjItem, componentType, path, rawComponentType));
} else if (dbObjItem instanceof DBObject) {
items.add(read(componentType, (DBObject) dbObjItem, path));
} else if (dbObjItem instanceof Document) {
items.add(read(componentType, (Document) dbObjItem, path));
} else if (dbObjItem instanceof BasicDBObject) {
items.add(read(componentType, (BasicDBObject) dbObjItem, path));
} else {
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
if (dbObjItem instanceof Collection) {
if (!rawComponentType.isArray() && !ClassUtils.isAssignable(Iterable.class, rawComponentType)) {
throw new MappingException(
String.format(INCOMPATIBLE_TYPES, dbObjItem, dbObjItem.getClass(), rawComponentType, path));
}
}
if (dbObjItem instanceof List) {
items.add(readCollectionOrArray(ClassTypeInformation.OBJECT, (List) dbObjItem, path));
} else {
items.add(getPotentiallyConvertedSimpleRead(dbObjItem, rawComponentType));
}
}
}
@@ -924,20 +958,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
/**
* Reads the given {@link DBObject} into a {@link Map}. will recursively resolve nested {@link Map}s as well.
* Reads the given {@link Document} into a {@link Map}. will recursively resolve nested {@link Map}s as well.
*
* @param type the {@link Map} {@link TypeInformation} to be used to unmarshall this {@link DBObject}.
* @param dbObject must not be {@literal null}
* @param type the {@link Map} {@link TypeInformation} to be used to unmarshall this {@link Document}.
* @param bson must not be {@literal null}
* @param path must not be {@literal null}
* @return
*/
@SuppressWarnings("unchecked")
protected Map<Object, Object> readMap(TypeInformation<?> type, DBObject dbObject, ObjectPath path) {
protected Map<Object, Object> readMap(TypeInformation<?> type, Bson bson, ObjectPath path) {
Assert.notNull(dbObject, "DBObject must not be null!");
Assert.notNull(bson, "Document must not be null!");
Assert.notNull(path, "Object path must not be null!");
Class<?> mapType = typeMapper.readType(dbObject, type).getType();
Class<?> mapType = typeMapper.readType(bson, type).getType();
TypeInformation<?> keyType = type.getComponentType();
Class<?> rawKeyType = keyType == null ? null : keyType.getType();
@@ -945,8 +979,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
TypeInformation<?> valueType = type.getMapValueType();
Class<?> rawValueType = valueType == null ? null : valueType.getType();
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, dbObject.keySet().size());
Map<String, Object> sourceMap = dbObject.toMap();
Map<String, Object> sourceMap = asMap(bson);
Map<Object, Object> map = CollectionFactory.createMap(mapType, rawKeyType, sourceMap.keySet().size());
if (!DBRef.class.equals(rawValueType) && isCollectionOfDbRefWhereBulkFetchIsPossible(sourceMap.values())) {
bulkReadAndConvertDBRefMapIntoTarget(valueType, rawValueType, sourceMap, map);
@@ -966,11 +1000,15 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
Object value = entry.getValue();
if (value instanceof DBObject) {
map.put(key, read(valueType, (DBObject) value, path));
if (value instanceof Document) {
map.put(key, read(valueType, (Document) value, path));
} else if (value instanceof BasicDBObject) {
map.put(key, read(valueType, (BasicDBObject) value, path));
} else if (value instanceof DBRef) {
map.put(key, DBRef.class.equals(rawValueType) ? value
: readAndConvertDBRef((DBRef) value, valueType, ObjectPath.ROOT, rawValueType));
} else if (value instanceof List) {
map.put(key, readCollectionOrArray(valueType, (List) value, path));
} else {
Class<?> valueClass = valueType == null ? null : valueType.getType();
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
@@ -980,6 +1018,69 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return map;
}
@SuppressWarnings("unchecked")
private Map<String, Object> asMap(Bson bson) {
if (bson instanceof Document) {
return (Document) bson;
}
if (bson instanceof DBObject) {
return ((DBObject) bson).toMap();
}
throw new IllegalArgumentException(
String.format("Cannot read %s. as map. Given Bson must be a Document or DBObject!", bson.getClass()));
}
private void addToMap(Bson bson, String key, Object value) {
if (bson instanceof Document) {
((Document) bson).put(key, value);
return;
}
if (bson instanceof DBObject) {
((DBObject) bson).put(key, value);
return;
}
throw new IllegalArgumentException(
String.format("Cannot add key/value pair to %s. as map. Given Bson must be a Document or DBObject!",
bson.getClass()));
}
@SuppressWarnings("unchecked")
private void addAllToMap(Bson bson, Map value) {
if (bson instanceof Document) {
((Document) bson).putAll(value);
return;
}
if (bson instanceof DBObject) {
((DBObject) bson).putAll(value);
return;
}
throw new IllegalArgumentException(String.format(
"Cannot add all to %s. Given Bson must be a Document or DBObject.", bson.getClass()));
}
private void removeFromMap(Bson bson, String key) {
if (bson instanceof Document) {
((Document) bson).remove(key);
return;
}
if (bson instanceof DBObject) {
((DBObject) bson).removeField(key);
return;
}
throw new IllegalArgumentException(
String.format("Cannot remove from %s. Given Bson must be a Document or DBObject.", bson.getClass()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
@@ -1003,14 +1104,21 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
TypeInformation<?> typeHint = typeInformation;
if (obj instanceof BasicDBList) {
return maybeConvertList((BasicDBList) obj, typeHint);
if (obj instanceof List) {
return maybeConvertList((List) obj, typeHint);
}
if (obj instanceof Document) {
Document newValueDocument = new Document();
for (String vk : ((Document) obj).keySet()) {
Object o = ((Document) obj).get(vk);
newValueDocument.put(vk, convertToMongoType(o, typeHint));
}
return newValueDocument;
}
if (obj instanceof DBObject) {
DBObject newValueDbo = new BasicDBObject();
Document newValueDbo = new Document();
for (String vk : ((DBObject) obj).keySet()) {
Object o = ((DBObject) obj).get(vk);
@@ -1022,18 +1130,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (obj instanceof Map) {
Map<Object, Object> converted = new LinkedHashMap<Object, Object>();
for (Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
TypeInformation<? extends Object> valueTypeHint = typeHint != null && typeHint.getMapValueType() != null
? typeHint.getMapValueType() : typeHint;
converted.put(getPotentiallyConvertedSimpleWrite(entry.getKey()).toString(),
convertToMongoType(entry.getValue(), valueTypeHint));
Document result = new Document();
for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) obj).entrySet()) {
result.put(entry.getKey().toString(), convertToMongoType(entry.getValue(), typeHint));
}
return new BasicDBObject(converted);
return result;
}
if (obj.getClass().isArray()) {
@@ -1044,23 +1146,23 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return maybeConvertList((Collection<?>) obj, typeHint);
}
DBObject newDbo = new BasicDBObject();
this.write(obj, newDbo);
Document newDocument = new Document();
this.write(obj, newDocument);
if (typeInformation == null) {
return removeTypeInfo(newDbo, true);
return removeTypeInfo(newDocument, true);
}
if (typeInformation.getType().equals(NestedDocument.class)) {
return removeTypeInfo(newDbo, false);
return removeTypeInfo(newDocument, false);
}
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfo(newDbo, true);
return !obj.getClass().equals(typeInformation.getType()) ? newDocument : removeTypeInfo(newDocument, true);
}
public BasicDBList maybeConvertList(Iterable<?> source, TypeInformation<?> typeInformation) {
public List maybeConvertList(Iterable<?> source, TypeInformation<?> typeInformation) {
BasicDBList newDbl = new BasicDBList();
List newDbl = new ArrayList();
for (Object element : source) {
newDbl.add(convertToMongoType(element, typeInformation));
}
@@ -1077,23 +1179,27 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
*/
private Object removeTypeInfo(Object object, boolean recursively) {
if (!(object instanceof DBObject)) {
if (!(object instanceof Document)) {
return object;
}
DBObject dbObject = (DBObject) object;
Document document = (Document) object;
String keyToRemove = null;
for (String key : dbObject.keySet()) {
for (String key : document.keySet()) {
if (recursively) {
Object value = dbObject.get(key);
Object value = document.get(key);
if (value instanceof BasicDBList) {
for (Object element : (BasicDBList) value) {
removeTypeInfo(element, recursively);
}
} else if (value instanceof List) {
for (Object element : (List) value) {
removeTypeInfo(element, recursively);
}
} else {
removeTypeInfo(value, recursively);
}
@@ -1110,21 +1216,21 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
if (keyToRemove != null) {
dbObject.removeField(keyToRemove);
document.remove(keyToRemove);
}
return dbObject;
return document;
}
/**
* {@link PropertyValueProvider} to evaluate a SpEL expression if present on the property or simply accesses the field
* of the configured source {@link DBObject}.
* of the configured source {@link Document}.
*
* @author Oliver Gierke
*/
private class MongoDbPropertyValueProvider implements PropertyValueProvider<MongoPersistentProperty> {
private final DBObjectAccessor source;
private final DocumentAccessor source;
private final SpELExpressionEvaluator evaluator;
private final ObjectPath path;
@@ -1136,12 +1242,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param evaluator must not be {@literal null}.
* @param path can be {@literal null}.
*/
public MongoDbPropertyValueProvider(DBObject source, SpELExpressionEvaluator evaluator, ObjectPath path) {
public MongoDbPropertyValueProvider(Bson source, SpELExpressionEvaluator evaluator, ObjectPath path) {
Assert.notNull(source);
Assert.notNull(evaluator);
this.source = new DBObjectAccessor(source);
this.source = new DocumentAccessor(source);
this.evaluator = evaluator;
this.path = path;
}
@@ -1208,10 +1314,12 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return (T) conversionService.convert(value, rawType);
} else if (value instanceof DBRef) {
return potentiallyReadOrResolveDbRef((DBRef) value, type, path, rawType);
} else if (value instanceof BasicDBList) {
return (T) readCollectionOrArray(type, (BasicDBList) value, path);
} else if (value instanceof List) {
return (T) readCollectionOrArray(type, (List) value, path);
} else if (value instanceof Document) {
return (T) read(type, (Document) value, path);
} else if (value instanceof DBObject) {
return (T) read(type, (DBObject) value, path);
return (T) read(type, (BasicDBObject) value, path);
} else {
return (T) getPotentiallyConvertedSimpleRead(value, rawType);
}
@@ -1257,13 +1365,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return Collections.emptyList();
}
List<DBObject> referencedRawDocuments = dbrefs.size() == 1
List<Document> referencedRawDocuments = dbrefs.size() == 1
? Collections.singletonList(readRef(dbrefs.iterator().next())) : bulkReadRefs(dbrefs);
String collectionName = dbrefs.iterator().next().getCollectionName();
List<T> targeList = new ArrayList<T>(dbrefs.size());
for (DBObject document : referencedRawDocuments) {
for (Document document : referencedRawDocuments) {
if (document != null) {
maybeEmitEvent(new AfterLoadEvent<T>(document, (Class<T>) rawType, collectionName));
@@ -1297,7 +1405,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @param ref
* @return
*/
DBObject readRef(DBRef ref) {
Document readRef(DBRef ref) {
return dbRefResolver.fetch(ref);
}
@@ -1308,13 +1416,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* @return never {@literal null}.
* @since 1.10
*/
List<DBObject> bulkReadRefs(List<DBRef> references) {
List<Document> bulkReadRefs(List<DBRef> references) {
return dbRefResolver.bulkFetch(references);
}
/**
* Returns whether the given {@link Iterable} contains {@link DBRef} instances all pointing to the same collection.
*
*
* @param source must not be {@literal null}.
* @return
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,26 +15,27 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.convert.EntityConverter;
import org.springframework.data.convert.EntityReader;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.DBObject;
/**
* Central Mongo specific converter interface which combines {@link MongoWriter} and {@link MongoReader}.
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
public interface MongoConverter extends
EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, DBObject>, MongoWriter<Object>,
EntityReader<Object, DBObject> {
public interface MongoConverter
extends EntityConverter<MongoPersistentEntity<?>, MongoPersistentProperty, Object, Bson>, MongoWriter<Object>,
EntityReader<Object, Bson> {
/**
* Returns thw {@link TypeMapper} being used to write type information into {@link DBObject}s created with that
* Returns thw {@link TypeMapper} being used to write type information into {@link Document}s created with that
* converter.
*
* @return will never be {@literal null}.

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.mongodb.core.convert;
import reactor.core.publisher.Flux;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
@@ -26,8 +28,10 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.bson.Document;
import org.bson.types.Code;
import org.bson.types.ObjectId;
import org.reactivestreams.Publisher;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalConverter;
@@ -41,16 +45,13 @@ import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
/**
* Wrapper class to contain useful converters for the usage with Mongo.
*
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
abstract class MongoConverters {
@@ -61,7 +62,7 @@ abstract class MongoConverters {
/**
* Returns the converters to be registered.
*
*
* @return
* @since 1.9
*/
@@ -75,10 +76,10 @@ abstract class MongoConverters {
converters.add(StringToBigIntegerConverter.INSTANCE);
converters.add(URLToStringConverter.INSTANCE);
converters.add(StringToURLConverter.INSTANCE);
converters.add(DBObjectToStringConverter.INSTANCE);
converters.add(DocumentToStringConverter.INSTANCE);
converters.add(TermToStringConverter.INSTANCE);
converters.add(NamedMongoScriptToDBObjectConverter.INSTANCE);
converters.add(DBObjectToNamedMongoScriptCoverter.INSTANCE);
converters.add(NamedMongoScriptToDocumentConverter.INSTANCE);
converters.add(DocumentToNamedMongoScriptConverter.INSTANCE);
converters.add(CurrencyToStringConverter.INSTANCE);
converters.add(StringToCurrencyConverter.INSTANCE);
converters.add(AtomicIntegerToIntegerConverter.INSTANCE);
@@ -91,7 +92,7 @@ abstract class MongoConverters {
/**
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
*
*
* @author Oliver Gierke
*/
public static enum ObjectIdToStringConverter implements Converter<ObjectId, String> {
@@ -104,7 +105,7 @@ abstract class MongoConverters {
/**
* Simple singleton to convert {@link String}s to their {@link ObjectId} representation.
*
*
* @author Oliver Gierke
*/
public static enum StringToObjectIdConverter implements Converter<String, ObjectId> {
@@ -117,7 +118,7 @@ abstract class MongoConverters {
/**
* Simple singleton to convert {@link ObjectId}s to their {@link java.math.BigInteger} representation.
*
*
* @author Oliver Gierke
*/
public static enum ObjectIdToBigIntegerConverter implements Converter<ObjectId, BigInteger> {
@@ -130,7 +131,7 @@ abstract class MongoConverters {
/**
* Simple singleton to convert {@link BigInteger}s to their {@link ObjectId} representation.
*
*
* @author Oliver Gierke
*/
public static enum BigIntegerToObjectIdConverter implements Converter<BigInteger, ObjectId> {
@@ -198,13 +199,18 @@ abstract class MongoConverters {
}
@ReadingConverter
public static enum DBObjectToStringConverter implements Converter<DBObject, String> {
public static enum DocumentToStringConverter implements Converter<Document, String> {
INSTANCE;
@Override
public String convert(DBObject source) {
return source == null ? null : source.toString();
public String convert(Document source) {
if (source == null) {
return null;
}
return source.toJson();
}
}
@@ -227,12 +233,12 @@ abstract class MongoConverters {
* @author Christoph Strobl
* @since 1.7
*/
public static enum DBObjectToNamedMongoScriptCoverter implements Converter<DBObject, NamedMongoScript> {
public static enum DocumentToNamedMongoScriptConverter implements Converter<Document, NamedMongoScript> {
INSTANCE;
@Override
public NamedMongoScript convert(DBObject source) {
public NamedMongoScript convert(Document source) {
if (source == null) {
return null;
@@ -249,29 +255,29 @@ abstract class MongoConverters {
* @author Christoph Strobl
* @since 1.7
*/
public static enum NamedMongoScriptToDBObjectConverter implements Converter<NamedMongoScript, DBObject> {
public static enum NamedMongoScriptToDocumentConverter implements Converter<NamedMongoScript, Document> {
INSTANCE;
@Override
public DBObject convert(NamedMongoScript source) {
public Document convert(NamedMongoScript source) {
if (source == null) {
return new BasicDBObject();
return new Document();
}
BasicDBObjectBuilder builder = new BasicDBObjectBuilder();
Document document = new Document();
builder.append("_id", source.getName());
builder.append("value", new Code(source.getCode()));
document.put("_id", source.getName());
document.put("value", new Code(source.getCode()));
return builder.get();
return document;
}
}
/**
* {@link Converter} implementation converting {@link Currency} into its ISO 4217 {@link String} representation.
*
*
* @author Christoph Strobl
* @since 1.9
*/
@@ -292,7 +298,7 @@ abstract class MongoConverters {
/**
* {@link Converter} implementation converting ISO 4217 {@link String} into {@link Currency}.
*
*
* @author Christoph Strobl
* @since 1.9
*/
@@ -315,12 +321,12 @@ abstract class MongoConverters {
* {@link ConverterFactory} implementation using {@link NumberUtils} for number conversion and parsing. Additionally
* deals with {@link AtomicInteger} and {@link AtomicLong} by calling {@code get()} before performing the actual
* conversion.
*
*
* @author Christoph Strobl
* @since 1.9
*/
@WritingConverter
public static enum NumberToNumberConverterFactory implements ConverterFactory<Number, Number>,ConditionalConverter {
public static enum NumberToNumberConverterFactory implements ConverterFactory<Number, Number>, ConditionalConverter {
INSTANCE;
@@ -348,13 +354,13 @@ abstract class MongoConverters {
/**
* Creates a new {@link NumberToNumberConverter} for the given target type.
*
*
* @param targetType must not be {@literal null}.
*/
public NumberToNumberConverter(Class<T> targetType) {
Assert.notNull(targetType, "Target type must not be null!");
this.targetType = targetType;
}

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;
import org.bson.Document;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher.NullHandler;
import org.springframework.data.domain.ExampleMatcher.PropertyValueTransformer;
@@ -44,9 +45,6 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* @author Christoph Strobl
* @author Mark Paluch
@@ -71,13 +69,13 @@ public class MongoExampleMapper {
}
/**
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
* Returns the given {@link Example} as {@link Document} holding matching values extracted from
* {@link Example#getProbe()}.
*
* @param example must not be {@literal null}.
* @return
*/
public DBObject getMappedExample(Example<?> example) {
public Document getMappedExample(Example<?> example) {
Assert.notNull(example, "Example must not be null!");
@@ -85,46 +83,47 @@ public class MongoExampleMapper {
}
/**
* Returns the given {@link Example} as {@link DBObject} holding matching values extracted from
* Returns the given {@link Example} as {@link Document} holding matching values extracted from
* {@link Example#getProbe()}.
*
* @param example must not be {@literal null}.
* @param entity must not be {@literal null}.
* @return
*/
public DBObject getMappedExample(Example<?> example, MongoPersistentEntity<?> entity) {
@SuppressWarnings({ "unchecked", "rawtypes" })
public Document getMappedExample(Example<?> example, MongoPersistentEntity<?> entity) {
Assert.notNull(example, "Example must not be null!");
Assert.notNull(entity, "MongoPersistentEntity must not be null!");
DBObject reference = (DBObject) converter.convertToMongoType(example.getProbe());
Document reference = (Document) converter.convertToMongoType(example.getProbe());
if (entity.hasIdProperty() && entity.getIdentifierAccessor(example.getProbe()).getIdentifier() == null) {
reference.removeField(entity.getIdProperty().getFieldName());
reference.remove(entity.getIdProperty().getFieldName());
}
ExampleMatcherAccessor matcherAccessor = new ExampleMatcherAccessor(example.getMatcher());
applyPropertySpecs("", reference, example.getProbeType(), matcherAccessor);
DBObject flattened = ObjectUtils.nullSafeEquals(NullHandler.INCLUDE, matcherAccessor.getNullHandler()) ? reference
: new BasicDBObject(SerializationUtils.flattenMap(reference));
DBObject result = example.getMatcher().isAllMatching() ? flattened : orConcatenate(flattened);
Document flattened = ObjectUtils.nullSafeEquals(NullHandler.INCLUDE, matcherAccessor.getNullHandler()) ? reference
: new Document(SerializationUtils.flattenMap(reference));
Document result = example.getMatcher().isAllMatching() ? flattened : orConcatenate(flattened);
this.converter.getTypeMapper().writeTypeRestrictions(result, getTypesToMatch(example));
return result;
}
private static DBObject orConcatenate(DBObject source) {
private static Document orConcatenate(Document source) {
List<DBObject> foo = new ArrayList<DBObject>(source.keySet().size());
List<Document> foo = new ArrayList<Document>(source.keySet().size());
for (String key : source.keySet()) {
foo.add(new BasicDBObject(key, source.get(key)));
foo.add(new Document(key, source.get(key)));
}
return new BasicDBObject("$or", foo);
return new Document("$or", foo);
}
private Set<Class<?>> getTypesToMatch(Example<?> example) {
@@ -187,14 +186,14 @@ public class MongoExampleMapper {
}
private void applyPropertySpecs(String path, DBObject source, Class<?> probeType,
private void applyPropertySpecs(String path, Document source, Class<?> probeType,
ExampleMatcherAccessor exampleSpecAccessor) {
if (!(source instanceof BasicDBObject)) {
if (!(source instanceof Document)) {
return;
}
Iterator<Map.Entry<String, Object>> iter = ((BasicDBObject) source).entrySet().iterator();
Iterator<Map.Entry<String, Object>> iter = ((Document) source).entrySet().iterator();
while (iter.hasNext()) {
@@ -240,8 +239,8 @@ public class MongoExampleMapper {
if (entry.getValue() instanceof String) {
applyStringMatcher(entry, stringMatcher, ignoreCase);
} else if (entry.getValue() instanceof BasicDBObject) {
applyPropertySpecs(propertyPath, (BasicDBObject) entry.getValue(), probeType, exampleSpecAccessor);
} else if (entry.getValue() instanceof Document) {
applyPropertySpecs(propertyPath, (Document) entry.getValue(), probeType, exampleSpecAccessor);
}
}
}
@@ -252,24 +251,24 @@ public class MongoExampleMapper {
private void applyStringMatcher(Map.Entry<String, Object> entry, StringMatcher stringMatcher, boolean ignoreCase) {
BasicDBObject dbo = new BasicDBObject();
Document document = new Document();
if (ObjectUtils.nullSafeEquals(StringMatcher.DEFAULT, stringMatcher)) {
if (ignoreCase) {
dbo.put("$regex", Pattern.quote((String) entry.getValue()));
entry.setValue(dbo);
document.put("$regex", Pattern.quote((String) entry.getValue()));
entry.setValue(document);
}
} else {
Type type = stringMatcherPartMapping.get(stringMatcher);
String expression = MongoRegexCreator.INSTANCE.toRegularExpression((String) entry.getValue(), type);
dbo.put("$regex", expression);
entry.setValue(dbo);
document.put("$regex", expression);
entry.setValue(document);
}
if (ignoreCase) {
dbo.put("$options", "i");
document.put("$options", "i");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2016 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.
@@ -17,16 +17,18 @@ package org.springframework.data.mongodb.core.convert;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.convert.TypeMapper;
import com.mongodb.DBObject;
/**
* Mongo-specific {@link TypeMapper} exposing that {@link DBObject}s might contain a type key.
* Mongo-specific {@link TypeMapper} exposing that {@link Document}s might contain a type key.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @since 1.0
*/
public interface MongoTypeMapper extends TypeMapper<DBObject> {
public interface MongoTypeMapper extends TypeMapper<Bson> {
/**
* Returns whether the given key is the type key.
@@ -36,12 +38,12 @@ public interface MongoTypeMapper extends TypeMapper<DBObject> {
boolean isTypeKey(String key);
/**
* Writes type restrictions to the given {@link DBObject}. This usually results in an {@code $in}-clause to be
* Writes type restrictions to the given {@link Document}. This usually results in an {@code $in}-clause to be
* generated that restricts the type-key (e.g. {@code _class}) to be in the set of type aliases for the given
* {@code restrictedTypes}.
*
* @param result must not be {@literal null}
* @param restrictedTypes must not be {@literal null}
*/
void writeTypeRestrictions(DBObject result, Set<Class<?>> restrictedTypes);
void writeTypeRestrictions(Document result, Set<Class<?>> restrictedTypes);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,22 +15,23 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.conversions.Bson;
import org.springframework.data.convert.EntityWriter;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.util.TypeInformation;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
/**
* A MongoWriter is responsible for converting an object of type T to the native MongoDB representation DBObject.
* A MongoWriter is responsible for converting an object of type T to the native MongoDB representation Document.
*
* @param <T> the type of the object to convert to a DBObject
* @param <T> the type of the object to convert to a Document
* @author Mark Pollack
* @author Thomas Risberg
* @author Oliver Gierke
* @author Christoph Strobl
*/
public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
public interface MongoWriter<T> extends EntityWriter<T, Bson> {
/**
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -23,14 +23,12 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.DBObject;
/**
* A path of objects nested into each other. The type allows access to all parent objects currently in creation even
* when resolving more nested objects. This allows to avoid re-resolving object instances that are logically equivalent
* to already resolved ones.
* <p>
* An immutable ordered set of target objects for {@link DBObject} to {@link Object} conversions. Object paths can be
* An immutable ordered set of target objects for {@link Document} to {@link Object} conversions. Object paths can be
* constructed by the {@link #toObjectPath(Object)} method and extended via {@link #push(Object)}.
*
* @author Thomas Darimont

View File

@@ -23,6 +23,8 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
@@ -41,6 +43,7 @@ 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.Query;
import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -63,7 +66,7 @@ import com.mongodb.DBRef;
public class QueryMapper {
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
private static final DBObject META_TEXT_SCORE = new BasicDBObject("$meta", "textScore");
private static final Document META_TEXT_SCORE = new Document("$meta", "textScore");
static final ClassTypeInformation<?> NESTED_DOCUMENT = ClassTypeInformation.from(NestedDocument.class);
private enum MetaMapping {
@@ -91,7 +94,7 @@ public class QueryMapper {
}
/**
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
* Replaces the property keys used in the given {@link Document} with the appropriate keys by using the
* {@link PersistentEntity} metadata.
*
* @param query must not be {@literal null}.
@@ -99,21 +102,21 @@ public class QueryMapper {
* @return
*/
@SuppressWarnings("deprecation")
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
public Document getMappedObject(Bson query, MongoPersistentEntity<?> entity) {
if (isNestedKeyword(query)) {
return getMappedKeyword(new Keyword(query), entity);
}
DBObject result = new BasicDBObject();
Document result = new Document();
for (String key : query.keySet()) {
for (String key : BsonUtils.asMap(query).keySet()) {
// TODO: remove one once QueryMapper can work with Query instances directly
if (Query.isRestrictedTypeKey(key)) {
@SuppressWarnings("unchecked")
Set<Class<?>> restrictedTypes = (Set<Class<?>>) query.get(key);
Set<Class<?>> restrictedTypes = (Set<Class<?>>) BsonUtils.get(query, key);
this.converter.getTypeMapper().writeTypeRestrictions(result, restrictedTypes);
continue;
@@ -127,16 +130,16 @@ public class QueryMapper {
try {
Field field = createPropertyField(entity, key, mappingContext);
Entry<String, Object> entry = getMappedObjectForField(field, query.get(key));
Entry<String, Object> entry = getMappedObjectForField(field, BsonUtils.get(query, key));
result.put(entry.getKey(), entry.getValue());
} catch (InvalidPersistentPropertyPath invalidPathException) {
// in case the object has not already been mapped
if (!(query.get(key) instanceof DBObject)) {
if (!(BsonUtils.get(query, key) instanceof Document)) {
throw invalidPathException;
}
result.put(key, query.get(key));
result.put(key, BsonUtils.get(query, key));
}
}
@@ -152,13 +155,13 @@ public class QueryMapper {
* @return
* @since 1.6
*/
public DBObject getMappedSort(DBObject sortObject, MongoPersistentEntity<?> entity) {
public Document getMappedSort(Document sortObject, MongoPersistentEntity<?> entity) {
if (sortObject == null) {
return null;
}
DBObject mappedSort = getMappedObject(sortObject, entity);
Document mappedSort = getMappedObject(sortObject, entity);
mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT);
return mappedSort;
}
@@ -172,14 +175,14 @@ public class QueryMapper {
* @return
* @since 1.6
*/
public DBObject getMappedFields(DBObject fieldsObject, MongoPersistentEntity<?> entity) {
public Document getMappedFields(Document fieldsObject, MongoPersistentEntity<?> entity) {
DBObject mappedFields = fieldsObject != null ? getMappedObject(fieldsObject, entity) : new BasicDBObject();
Document mappedFields = fieldsObject != null ? getMappedObject(fieldsObject, entity) : new Document();
mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE);
return mappedFields.keySet().isEmpty() ? null : mappedFields;
}
private void mapMetaAttributes(DBObject source, MongoPersistentEntity<?> entity, MetaMapping metaMapping) {
private void mapMetaAttributes(Document source, MongoPersistentEntity<?> entity, MetaMapping metaMapping) {
if (entity == null || source == null) {
return;
@@ -188,14 +191,14 @@ public class QueryMapper {
if (entity.hasTextScoreProperty() && !MetaMapping.IGNORE.equals(metaMapping)) {
MongoPersistentProperty textScoreProperty = entity.getTextScoreProperty();
if (MetaMapping.FORCE.equals(metaMapping)
|| (MetaMapping.WHEN_PRESENT.equals(metaMapping) && source.containsField(textScoreProperty.getFieldName()))) {
|| (MetaMapping.WHEN_PRESENT.equals(metaMapping) && source.containsKey(textScoreProperty.getFieldName()))) {
source.putAll(getMappedTextScoreField(textScoreProperty));
}
}
}
private DBObject getMappedTextScoreField(MongoPersistentProperty property) {
return new BasicDBObject(property.getFieldName(), META_TEXT_SCORE);
private Document getMappedTextScoreField(MongoPersistentProperty property) {
return new Document(property.getFieldName(), META_TEXT_SCORE);
}
/**
@@ -211,7 +214,7 @@ public class QueryMapper {
Object value;
if (isNestedKeyword(rawValue) && !field.isIdField()) {
Keyword keyword = new Keyword((DBObject) rawValue);
Keyword keyword = new Keyword((Document) rawValue);
value = getMappedKeyword(field, keyword);
} else {
value = getMappedValue(field, rawValue);
@@ -232,33 +235,33 @@ public class QueryMapper {
}
/**
* Returns the given {@link DBObject} representing a keyword by mapping the keyword's value.
* Returns the given {@link Document} representing a keyword by mapping the keyword's value.
*
* @param keyword the {@link DBObject} representing a keyword (e.g. {@code $ne : … } )
* @param keyword the {@link Document} representing a keyword (e.g. {@code $ne : … } )
* @param entity
* @return
*/
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
protected Document getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
// $or/$nor
if (keyword.isOrOrNor() || (keyword.hasIterableValue() && !keyword.isGeometry())) {
Iterable<?> conditions = keyword.getValue();
BasicDBList newConditions = new BasicDBList();
List<Object> newConditions = new ArrayList<Object>();
for (Object condition : conditions) {
newConditions.add(isDBObject(condition) ? getMappedObject((DBObject) condition, entity)
: convertSimpleOrDBObject(condition, entity));
newConditions.add(isDocument(condition) ? getMappedObject((Document) condition, entity)
: convertSimpleOrDocument(condition, entity));
}
return new BasicDBObject(keyword.getKey(), newConditions);
return new Document(keyword.getKey(), newConditions);
}
if (keyword.isSample()) {
return exampleMapper.getMappedExample(keyword.<Example<?>> getValue(), entity);
}
return new BasicDBObject(keyword.getKey(), convertSimpleOrDBObject(keyword.getValue(), entity));
return new Document(keyword.getKey(), convertSimpleOrDocument(keyword.getValue(), entity));
}
/**
@@ -268,7 +271,7 @@ public class QueryMapper {
* @param keyword
* @return
*/
protected DBObject getMappedKeyword(Field property, Keyword keyword) {
protected Document getMappedKeyword(Field property, Keyword keyword) {
boolean needsAssociationConversion = property.isAssociation() && !keyword.isExists();
Object value = keyword.getValue();
@@ -276,7 +279,7 @@ public class QueryMapper {
Object convertedValue = needsAssociationConversion ? convertAssociation(value, property)
: getMappedValue(property.with(keyword.getKey()), value);
return new BasicDBObject(keyword.key, convertedValue);
return new Document(keyword.key, convertedValue);
}
/**
@@ -288,13 +291,14 @@ public class QueryMapper {
* @param newKey the key the value will be bound to eventually
* @return
*/
@SuppressWarnings("unchecked")
protected Object getMappedValue(Field documentField, Object value) {
if (documentField.isIdField()) {
if (isDBObject(value)) {
DBObject valueDbo = (DBObject) value;
DBObject resultDbo = new BasicDBObject(valueDbo.toMap());
Document resultDbo = new Document(valueDbo.toMap());
if (valueDbo.containsField("$in") || valueDbo.containsField("$nin")) {
String inKey = valueDbo.containsField("$in") ? "$in" : "$nin";
@@ -302,13 +306,31 @@ public class QueryMapper {
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
ids.add(convertId(id));
}
resultDbo.put(inKey, ids.toArray(new Object[ids.size()]));
resultDbo.put(inKey, ids);
} else if (valueDbo.containsField("$ne")) {
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
} else {
return getMappedObject(resultDbo, null);
}
return resultDbo;
}
else if (isDocument(value)) {
Document valueDbo = (Document) value;
Document resultDbo = new Document(valueDbo);
if (valueDbo.containsKey("$in") || valueDbo.containsKey("$nin")) {
String inKey = valueDbo.containsKey("$in") ? "$in" : "$nin";
List<Object> ids = new ArrayList<Object>();
for (Object id : (Iterable<?>) valueDbo.get(inKey)) {
ids.add(convertId(id));
}
resultDbo.put(inKey, ids);
} else if (valueDbo.containsKey("$ne")) {
resultDbo.put("$ne", convertId(valueDbo.get("$ne")));
} else {
return getMappedObject(resultDbo, null);
}
return resultDbo;
} else {
@@ -317,14 +339,14 @@ public class QueryMapper {
}
if (isNestedKeyword(value)) {
return getMappedKeyword(new Keyword((DBObject) value), documentField.getPropertyEntity());
return getMappedKeyword(new Keyword((Bson) value), documentField.getPropertyEntity());
}
if (isAssociationConversionNecessary(documentField, value)) {
return convertAssociation(value, documentField);
}
return convertSimpleOrDBObject(value, documentField.getPropertyEntity());
return convertSimpleOrDocument(value, documentField.getPropertyEntity());
}
/**
@@ -362,20 +384,28 @@ public class QueryMapper {
}
/**
* Retriggers mapping if the given source is a {@link DBObject} or simply invokes the
* Retriggers mapping if the given source is a {@link Document} or simply invokes the
*
* @param source
* @param entity
* @return
*/
protected Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
protected Object convertSimpleOrDocument(Object source, MongoPersistentEntity<?> entity) {
if (source instanceof List) {
return delegateConvertToMongoType(source, entity);
}
if (isDocument(source)) {
return getMappedObject((Document) source, entity);
}
if (source instanceof BasicDBList) {
return delegateConvertToMongoType(source, entity);
}
if (isDBObject(source)) {
return getMappedObject((DBObject) source, entity);
return getMappedObject((BasicDBObject) source, entity);
}
return delegateConvertToMongoType(source, entity);
@@ -406,7 +436,7 @@ public class QueryMapper {
*/
protected Object convertAssociation(Object source, MongoPersistentProperty property) {
if (property == null || source == null || source instanceof DBObject) {
if (property == null || source == null || source instanceof Document || source instanceof DBObject) {
return source;
}
@@ -425,8 +455,8 @@ public class QueryMapper {
}
if (property.isMap()) {
BasicDBObject result = new BasicDBObject();
DBObject dbObject = (DBObject) source;
Document result = new Document();
Document dbObject = (Document) source;
for (String key : dbObject.keySet()) {
result.put(key, createDbRefFor(dbObject.get(key), property));
}
@@ -437,11 +467,21 @@ public class QueryMapper {
}
/**
* Checks whether the given value is a {@link DBObject}.
* Checks whether the given value is a {@link Document}.
*
* @param value can be {@literal null}.
* @return
*/
protected final boolean isDocument(Object value) {
return value instanceof Document;
}
/**
* 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;
}
@@ -504,19 +544,18 @@ public class QueryMapper {
}
/**
* Returns whether the given {@link Object} is a keyword, i.e. if it's a {@link DBObject} with a keyword key.
* Returns whether the given {@link Object} is a keyword, i.e. if it's a {@link Document} with a keyword key.
*
* @param candidate
* @return
*/
protected boolean isNestedKeyword(Object candidate) {
if (!(candidate instanceof BasicDBObject)) {
if (!(candidate instanceof Document)) {
return false;
}
BasicDBObject dbObject = (BasicDBObject) candidate;
Set<String> keys = dbObject.keySet();
Set<String> keys = BsonUtils.asMap((Bson) candidate).keySet();
if (keys.size() != 1) {
return false;
@@ -548,18 +587,18 @@ public class QueryMapper {
private final String key;
private final Object value;
public Keyword(DBObject source, String key) {
public Keyword(Bson source, String key) {
this.key = key;
this.value = source.get(key);
this.value = BsonUtils.get(source, key);
}
public Keyword(DBObject dbObject) {
public Keyword(Bson bson) {
Set<String> keys = dbObject.keySet();
Assert.isTrue(keys.size() == 1, "Can only use a single value DBObject!");
Set<String> keys = BsonUtils.asMap(bson).keySet();
Assert.isTrue(keys.size() == 1, "Can only use a single value Document!");
this.key = keys.iterator().next();
this.value = dbObject.get(key);
this.value = BsonUtils.get(bson, key);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.
@@ -20,12 +20,13 @@ import static org.springframework.util.ReflectionUtils.*;
import java.lang.reflect.Method;
import org.bson.Document;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.util.Assert;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.client.model.Filters;
/**
* {@link ReflectiveDBRefResolver} provides reflective access to {@link DBRef} API that is not consistently available
@@ -51,16 +52,18 @@ class ReflectiveDBRefResolver {
* @param ref must not be {@literal null}.
* @return the document that this references.
*/
public static DBObject fetch(MongoDbFactory factory, DBRef ref) {
public static Document fetch(MongoDbFactory factory, DBRef ref) {
Assert.notNull(ref, "DBRef to fetch must not be null!");
if (isMongo3Driver()) {
Assert.notNull(factory, "DbFactory to fetch DB from must not be null!");
return factory.getDb().getCollection(ref.getCollectionName()).findOne(ref.getId());
return factory.getDb().getCollection(ref.getCollectionName(), Document.class).find(Filters.eq("_id", ref.getId()))
.first();
}
return (DBObject) invokeMethod(FETCH_METHOD, ref);
return (Document) invokeMethod(FETCH_METHOD, ref);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2016 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.
@@ -17,6 +17,8 @@ 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;
@@ -28,15 +30,13 @@ import org.springframework.data.mongodb.core.query.Update.Modifiers;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
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
* @author Mark Paluch
*/
public class UpdateMapper extends QueryMapper {
@@ -53,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.
@@ -73,8 +137,8 @@ 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 (isDocument(rawValue)) {
return createMapEntry(field, convertSimpleOrDocument(rawValue, field.getPropertyEntity()));
}
if (isQuery(rawValue)) {
@@ -98,10 +162,10 @@ public class UpdateMapper extends QueryMapper {
} else if (rawValue instanceof Modifiers) {
DBObject modificationOperations = new BasicDBObject();
Document modificationOperations = new Document();
for (Modifier modifier : ((Modifiers) rawValue).getModifiers()) {
modificationOperations.putAll(getMappedValue(field, modifier).toMap());
modificationOperations.putAll(getMappedValue(field, modifier));
}
value = modificationOperations;
@@ -129,12 +193,12 @@ public class UpdateMapper extends QueryMapper {
return value instanceof Query;
}
private DBObject getMappedValue(Field field, Modifier modifier) {
private Document getMappedValue(Field field, Modifier modifier) {
TypeInformation<?> typeHint = field == null ? ClassTypeInformation.OBJECT : field.getTypeHint();
Object value = converter.convertToMongoType(modifier.getValue(), typeHint);
return new BasicDBObject(modifier.getKey(), value);
return new Document(modifier.getKey(), value);
}
private TypeInformation<?> getTypeHintForEntity(Object source, MongoPersistentEntity<?> entity) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,28 +15,28 @@
*/
package org.springframework.data.mongodb.core.convert;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import com.mongodb.DBObject;
/**
* Internal API to trigger the resolution of properties.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
interface ValueResolver {
/**
* Resolves the value for the given {@link MongoPersistentProperty} within the given {@link DBObject} using the given
* Resolves the value for the given {@link MongoPersistentProperty} within the given {@link Document} using the given
* {@link SpELExpressionEvaluator} and {@link ObjectPath}.
*
* @param prop
* @param dbo
* @param bson
* @param evaluator
* @param parent
* @return
*/
Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator evaluator,
ObjectPath parent);
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath parent);
}

View File

@@ -125,17 +125,6 @@ public @interface CompoundIndex {
*/
boolean useGeneratedName() default false;
/**
* The collection the index will be created in. Will default to the collection the annotated domain class will be
* stored in.
*
* @return
* @deprecated The collection name is derived from the domain type. Fixing the collection via this attribute might
* result in broken definitions. Will be removed in 1.7.
*/
@Deprecated
String collection() default "";
/**
* If {@literal true} the index will be created in the background.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-2016 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.
@@ -15,11 +15,9 @@
*/
package org.springframework.data.mongodb.core.index;
import org.bson.Document;
import org.springframework.util.Assert;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Index definition to span multiple keys.
*
@@ -28,14 +26,14 @@ import com.mongodb.DBObject;
*/
public class CompoundIndexDefinition extends Index {
private DBObject keys;
private Document keys;
/**
* Creates a new {@link CompoundIndexDefinition} for the given keys.
*
* @param keys must not be {@literal null}.
*/
public CompoundIndexDefinition(DBObject keys) {
public CompoundIndexDefinition(Document keys) {
Assert.notNull(keys, "Keys must not be null!");
this.keys = keys;
@@ -46,11 +44,11 @@ public class CompoundIndexDefinition extends Index {
* @see org.springframework.data.mongodb.core.index.Index#getIndexKeys()
*/
@Override
public DBObject getIndexKeys() {
public Document getIndexKeys() {
BasicDBObject dbo = new BasicDBObject();
dbo.putAll(this.keys);
dbo.putAll(super.getIndexKeys());
return dbo;
Document document = new Document();
document.putAll(this.keys);
document.putAll(super.getIndexKeys());
return document;
}
}

View File

@@ -83,16 +83,6 @@ public @interface GeoSpatialIndexed {
*/
boolean useGeneratedName() default false;
/**
* Name of the collection in which to create the index.
*
* @return
* @deprecated The collection name is derived from the domain type. Fixing the collection via this attribute might
* result in broken definitions. Will be removed in 1.7.
*/
@Deprecated
String collection() default "";
/**
* Minimum value for indexed values.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 the original author or authors.
* Copyright 2010-2016 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.
@@ -15,12 +15,10 @@
*/
package org.springframework.data.mongodb.core.index;
import org.bson.Document;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Value object to capture data to create a geo index.
*
@@ -119,42 +117,42 @@ public class GeospatialIndex implements IndexDefinition {
return this;
}
public DBObject getIndexKeys() {
public Document getIndexKeys() {
DBObject dbo = new BasicDBObject();
Document document = new Document();
switch (type) {
case GEO_2D:
dbo.put(field, "2d");
document.put(field, "2d");
break;
case GEO_2DSPHERE:
dbo.put(field, "2dsphere");
document.put(field, "2dsphere");
break;
case GEO_HAYSTACK:
dbo.put(field, "geoHaystack");
document.put(field, "geoHaystack");
if (!StringUtils.hasText(additionalField)) {
throw new IllegalArgumentException("When defining geoHaystack index, an additionnal field must be defined");
}
dbo.put(additionalField, 1);
document.put(additionalField, 1);
break;
default:
throw new IllegalArgumentException("Unsupported geospatial index " + type);
}
return dbo;
return document;
}
public DBObject getIndexOptions() {
public Document getIndexOptions() {
if (!StringUtils.hasText(name) && min == null && max == null && bucketSize == null) {
return null;
}
DBObject dbo = new BasicDBObject();
Document dbo = new Document();
if (StringUtils.hasText(name)) {
dbo.put("name", name);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 the original author or authors.
* Copyright 2010-2016 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.
@@ -20,14 +20,11 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import org.bson.Document;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.query.Order;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* @author Oliver Gierke
* @author Christoph Strobl
@@ -36,17 +33,7 @@ import com.mongodb.DBObject;
public class Index implements IndexDefinition {
public enum Duplicates {
RETAIN, //
/**
* Dropping Duplicates was removed in MongoDB Server 2.8.0-rc0.
* <p>
* See https://jira.mongodb.org/browse/SERVER-14710
*
* @deprecated since 1.7.
*/
@Deprecated //
DROP
RETAIN
}
private final Map<String, Direction> fieldSpec = new LinkedHashMap<String, Direction>();
@@ -69,31 +56,6 @@ public class Index implements IndexDefinition {
fieldSpec.put(key, direction);
}
/**
* Creates a new {@link Indexed} on the given key and {@link Order}.
*
* @deprecated use {@link #Index(String, Direction)} instead.
* @param key must not be {@literal null} or empty.
* @param order must not be {@literal null}.
*/
@Deprecated
public Index(String key, Order order) {
this(key, order.toDirection());
}
/**
* Adds the given field to the index.
*
* @deprecated use {@link #on(String, Direction)} instead.
* @param key must not be {@literal null} or empty.
* @param order must not be {@literal null}.
* @return
*/
@Deprecated
public Index on(String key, Order order) {
return on(key, order.toDirection());
}
public Index on(String key, Direction direction) {
fieldSpec.put(key, direction);
return this;
@@ -164,56 +126,44 @@ public class Index implements IndexDefinition {
return this;
}
/**
* @see http://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping
* @param duplicates
* @return
*/
public Index unique(Duplicates duplicates) {
if (duplicates == Duplicates.DROP) {
this.dropDuplicates = true;
}
return unique();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexKeys()
*/
public DBObject getIndexKeys() {
public Document getIndexKeys() {
DBObject dbo = new BasicDBObject();
Document document = new Document();
for (Entry<String, Direction> entry : fieldSpec.entrySet()) {
dbo.put(entry.getKey(), Direction.ASC.equals(entry.getValue()) ? 1 : -1);
document.put(entry.getKey(), Direction.ASC.equals(entry.getValue()) ? 1 : -1);
}
return dbo;
return document;
}
public DBObject getIndexOptions() {
public Document getIndexOptions() {
DBObject dbo = new BasicDBObject();
Document document = new Document();
if (StringUtils.hasText(name)) {
dbo.put("name", name);
document.put("name", name);
}
if (unique) {
dbo.put("unique", true);
document.put("unique", true);
}
if (dropDuplicates) {
dbo.put("dropDups", true);
document.put("dropDups", true);
}
if (sparse) {
dbo.put("sparse", true);
document.put("sparse", true);
}
if (background) {
dbo.put("background", true);
document.put("background", true);
}
if (expire >= 0) {
dbo.put("expireAfterSeconds", expire);
document.put("expireAfterSeconds", expire);
}
return dbo;
return document;
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2014 by the original author(s).
* Copyright (c) 2011-2016 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.springframework.data.mongodb.core.index;
import com.mongodb.DBObject;
import org.bson.Document;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
@@ -24,7 +24,7 @@ import com.mongodb.DBObject;
*/
public interface IndexDefinition {
DBObject getIndexKeys();
Document getIndexKeys();
DBObject getIndexOptions();
Document getIndexOptions();
}

Some files were not shown because too many files have changed in this diff Show More