diff --git a/pom.xml b/pom.xml
index 23d6477249..ada5446016 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
pom
Spring Data MongoDB
@@ -15,7 +15,7 @@
org.springframework.data.build
spring-data-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATABUILD-369-SNAPSHOT
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index 4a49168713..72cf07e714 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
../pom.xml
@@ -48,7 +48,7 @@
org.springframework.data
spring-data-mongodb
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 750ed23aa8..54b1c2bd59 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml
index 50d0a6454a..b4692cd9a5 100644
--- a/spring-data-mongodb-log4j/pom.xml
+++ b/spring-data-mongodb-log4j/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 99ef83a54b..d77efc652c 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,13 +11,14 @@
org.springframework.data
spring-data-mongodb-parent
- 2.0.0.BUILD-SNAPSHOT
+ 2.0.0.DATAMONGO-1689-SNAPSHOT
../pom.xml
1.3
1.5
+ 1.1.2-5
@@ -230,12 +231,108 @@
spring-webmvc
test
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ ${kotlin}
+ true
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ ${kotlin}
+ true
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin}
+ test
+
+
+ com.nhaarman
+ mockito-kotlin
+ 1.5.0
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+
+
+ org.mockito
+ mockito-core
+
+
+
+
+ kotlin-maven-plugin
+ org.jetbrains.kotlin
+ ${kotlin}
+
+ 1.8
+
+
+
+ compile
+ compile
+ compile
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/main/java
+
+
+
+
+ test-compile
+ test-compile
+ test-compile
+
+
+ ${project.basedir}/src/test/kotlin
+ ${project.basedir}/src/test/java
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+ none
+
+
+ default-testCompile
+ none
+
+
+ java-compile
+ compile
+ compile
+
+
+ java-test-compile
+ test-compile
+ testCompile
+
+
+
+
com.mysema.maven
apt-maven-plugin
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt
new file mode 100644
index 0000000000..5b43222c42
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensions.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 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 kotlin.reflect.KClass
+
+/**
+ * Extension for [ExecutableAggregationOperation.aggregateAndReturn] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ExecutableAggregationOperation.aggregateAndReturn(entityClass: KClass): ExecutableAggregationOperation.AggregationOperation =
+ aggregateAndReturn(entityClass.java)
+
+/**
+ * Extension for [ExecutableAggregationOperation.aggregateAndReturn] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ExecutableAggregationOperation.aggregateAndReturn(): ExecutableAggregationOperation.AggregationOperation =
+ aggregateAndReturn(T::class.java)
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt
new file mode 100644
index 0000000000..be445235e1
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensions.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017 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 kotlin.reflect.KClass
+
+/**
+ * Extension for [ExecutableFindOperation.query] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ExecutableFindOperation.query(entityClass: KClass): ExecutableFindOperation.FindOperation =
+ query(entityClass.java)
+
+/**
+ * Extension for [ExecutableFindOperation.query] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ExecutableFindOperation.query(): ExecutableFindOperation.FindOperation =
+ query(T::class.java)
+
+
+/**
+ * Extension for [ExecutableFindOperation.FindOperationWithProjection.as] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ExecutableFindOperation.FindOperationWithProjection.asType(resultType: KClass): ExecutableFindOperation.FindOperationWithQuery =
+ `as`(resultType.java)
+
+/**
+ * Extension for [ExecutableFindOperation.FindOperationWithProjection.as] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ExecutableFindOperation.FindOperationWithProjection.asType(): ExecutableFindOperation.FindOperationWithQuery =
+ `as`(T::class.java)
+
+
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt
new file mode 100644
index 0000000000..1b0f80fcc0
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensions.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 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 kotlin.reflect.KClass
+
+/**
+ * Extension for [ExecutableInsertOperation.insert] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ExecutableInsertOperation.insert(entityClass: KClass): ExecutableInsertOperation.InsertOperation =
+ insert(entityClass.java)
+
+/**
+ * Extension for [ExecutableInsertOperation.insert] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ExecutableInsertOperation.insert(): ExecutableInsertOperation.InsertOperation =
+ insert(T::class.java)
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt
new file mode 100644
index 0000000000..5c84e67d64
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensions.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017 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 kotlin.reflect.KClass
+
+/**
+ * Extension for [ExecutableRemoveOperation.remove] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ExecutableRemoveOperation.remove(entityClass: KClass): ExecutableRemoveOperation.RemoveOperation =
+ remove(entityClass.java)
+
+/**
+ * Extension for [ExecutableRemoveOperation.remove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ExecutableRemoveOperation.remove(): ExecutableRemoveOperation.RemoveOperation =
+ remove(T::class.java)
\ No newline at end of file
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt
new file mode 100644
index 0000000000..7956df812b
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2017 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.client.MongoCollection
+import com.mongodb.client.result.DeleteResult
+import com.mongodb.client.result.UpdateResult
+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
+import org.springframework.data.mongodb.core.aggregation.AggregationResults
+import org.springframework.data.mongodb.core.mapreduce.GroupBy
+import org.springframework.data.mongodb.core.mapreduce.GroupByResults
+import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions
+import org.springframework.data.mongodb.core.mapreduce.MapReduceResults
+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 org.springframework.data.util.CloseableIterator
+import kotlin.reflect.KClass
+
+/**
+ * Extension for [MongoOperations.getCollectionName] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.getCollectionName(entityClass: KClass): String =
+ getCollectionName(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.getCollectionName] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.getCollectionName(): String =
+ getCollectionName(T::class.java)
+
+/**
+ * Extension for [MongoOperations.execute] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.execute(action: CollectionCallback): T =
+ execute(T::class.java, action)
+
+/**
+ * Extension for [MongoOperations.stream] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.stream(query: Query): CloseableIterator =
+ stream(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.stream] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.stream(query: Query, collectionName: String? = null): CloseableIterator =
+ if (collectionName != null) stream(query, T::class.java, collectionName)
+ else stream(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.createCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.createCollection(entityClass: KClass, collectionOptions: CollectionOptions? = null): MongoCollection =
+ if (collectionOptions != null) createCollection(entityClass.java, collectionOptions)
+ else createCollection(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.createCollection] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.createCollection(
+ collectionOptions: CollectionOptions? = null): MongoCollection =
+ if (collectionOptions != null) createCollection(T::class.java, collectionOptions)
+ else createCollection(T::class.java)
+
+/**
+ * Extension for [MongoOperations.collectionExists] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.collectionExists(entityClass: KClass): Boolean =
+ collectionExists(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.collectionExists] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.collectionExists(): Boolean =
+ collectionExists(T::class.java)
+
+/**
+ * Extension for [MongoOperations.dropCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.dropCollection(entityClass: KClass) {
+ dropCollection(entityClass.java)
+}
+
+/**
+ * Extension for [MongoOperations.dropCollection] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.dropCollection() {
+ dropCollection(T::class.java)
+}
+
+/**
+ * Extension for [MongoOperations.indexOps] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.indexOps(entityClass: KClass): IndexOperations =
+ indexOps(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.indexOps] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.indexOps(): IndexOperations =
+ indexOps(T::class.java)
+
+/**
+ * Extension for [MongoOperations.bulkOps] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.bulkOps(bulkMode: BulkMode, entityClass: KClass, collectionName: String? = null): BulkOperations =
+ if (collectionName != null) bulkOps(bulkMode, entityClass.java, collectionName)
+ else bulkOps(bulkMode, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.bulkOps] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.bulkOps(bulkMode: BulkMode, collectionName: String? = null): BulkOperations =
+ if (collectionName != null) bulkOps(bulkMode, T::class.java, collectionName)
+ else bulkOps(bulkMode, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findAll] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findAll(collectionName: String? = null): List =
+ if (collectionName != null) findAll(T::class.java, collectionName) else findAll(T::class.java)
+
+/**
+ * Extension for [MongoOperations.group] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.group(inputCollectionName: String, groupBy: GroupBy): GroupByResults =
+ group(inputCollectionName, groupBy, T::class.java)
+
+/**
+ * Extension for [MongoOperations.group] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.group(criteria: Criteria, inputCollectionName: String, groupBy: GroupBy): GroupByResults =
+ group(criteria, inputCollectionName, groupBy, T::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregate] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.aggregate(aggregation: Aggregation, inputType: KClass<*>): AggregationResults =
+ aggregate(aggregation, inputType.java, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregate] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.aggregate(aggregation: Aggregation, collectionName: String): AggregationResults =
+ aggregate(aggregation, collectionName, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregateStream] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.aggregateStream(aggregation: Aggregation, inputType: KClass<*>): CloseableIterator =
+ aggregateStream(aggregation, inputType.java, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregateStream] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.aggregateStream(aggregation: Aggregation, collectionName: String): CloseableIterator =
+ aggregateStream(aggregation, collectionName, O::class.java)
+
+/**
+ * Extension for [MongoOperations.mapReduce] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.mapReduce(collectionName: String, mapFunction: String, reduceFunction: String, options: MapReduceOptions? = null): MapReduceResults =
+ if (options != null) mapReduce(collectionName, mapFunction, reduceFunction, options, T::class.java)
+ else mapReduce(collectionName, mapFunction, reduceFunction, T::class.java)
+
+/**
+ * Extension for [MongoOperations.mapReduce] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 52.0
+ */
+inline fun MongoOperations.mapReduce(query: Query, collectionName: String, mapFunction: String, reduceFunction: String, options: MapReduceOptions? = null): MapReduceResults =
+ if (options != null) mapReduce(query, collectionName, mapFunction, reduceFunction, options, T::class.java)
+ else mapReduce(query, collectionName, mapFunction, reduceFunction, T::class.java)
+
+/**
+ * Extension for [MongoOperations.geoNear] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.geoNear(near: NearQuery, collectionName: String? = null): GeoResults =
+ if (collectionName != null) geoNear(near, T::class.java, collectionName)
+ else geoNear(near, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findOne] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findOne(query: Query, collectionName: String? = null): T =
+ if (collectionName != null) findOne(query, T::class.java, collectionName) else findOne(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.exists] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.exists(query: Query, entityClass: KClass, collectionName: String? = null): Boolean =
+ if (collectionName != null) exists(query, entityClass.java, collectionName)
+ else exists(query, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.exists] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.exists(query: Query, collectionName: String? = null): Boolean =
+ if (collectionName != null) exists(query, T::class.java, collectionName)
+ else exists(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.find] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.find(query: Query, collectionName: String? = null): List =
+ if (collectionName != null) find(query, T::class.java, collectionName)
+ else find(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findById] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findById(id: Any, collectionName: String? = null): T =
+ if (collectionName != null) findById(id, T::class.java, collectionName)
+ else findById(id, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findAndModify] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findAndModify(query: Query, update: Update, options: FindAndModifyOptions, collectionName: String? = null): T =
+ if (collectionName != null) findAndModify(query, update, options, T::class.java, collectionName)
+ else findAndModify(query, update, options, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findAndRemove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findAndRemove(query: Query, collectionName: String? = null): T =
+ if (collectionName != null) findAndRemove(query, T::class.java, collectionName)
+ else findAndRemove(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.count] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.count(query: Query = Query(), entityClass: KClass, collectionName: String? = null): Long =
+ if (collectionName != null) count(query, entityClass.java, collectionName)
+ else count(query, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.count] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.count(query: Query = Query(), collectionName: String? = null): Long =
+ if (collectionName != null) count(query, T::class.java, collectionName) else count(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.insert] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.insert(batchToSave: Collection, entityClass: KClass) {
+ insert(batchToSave, entityClass.java)
+}
+
+/**
+ * Extension for [MongoOperations.upsert] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.upsert(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) upsert(query, update, entityClass.java, collectionName)
+ else upsert(query, update, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.upsert] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.upsert(query: Query, update: Update, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) upsert(query, update, T::class.java, collectionName)
+ else upsert(query, update, T::class.java)
+
+/**
+ * Extension for [MongoOperations.updateFirst] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.updateFirst(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) updateFirst(query, update, entityClass.java, collectionName)
+ else updateFirst(query, update, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.updateFirst] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.updateFirst(query: Query, update: Update, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) updateFirst(query, update, T::class.java, collectionName)
+ else updateFirst(query, update, T::class.java)
+
+
+/**
+ * Extension for [MongoOperations.updateMulti] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.updateMulti(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) updateMulti(query, update, entityClass.java, collectionName)
+ else updateMulti(query, update, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.updateMulti] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.updateMulti(query: Query, update: Update, collectionName: String? = null): UpdateResult =
+ if (collectionName != null) updateMulti(query, update, T::class.java, collectionName)
+ else updateMulti(query, update, T::class.java)
+
+/**
+ * Extension for [MongoOperations.remove] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun MongoOperations.remove(query: Query, entityClass: KClass, collectionName: String? = null): DeleteResult =
+ if (collectionName != null) remove(query, entityClass.java, collectionName)
+ else remove(query, entityClass.java)
+
+/**
+ * Extension for [MongoOperations.remove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun MongoOperations.remove(query: Query, collectionName: String? = null): DeleteResult =
+ if (collectionName != null) remove(query, T::class.java, collectionName)
+ else remove(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.findAllAndRemove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun MongoOperations.findAllAndRemove(query: Query): List =
+ findAllAndRemove(query, T::class.java)
diff --git a/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt
new file mode 100644
index 0000000000..5e92c8db49
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2017 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.client.result.DeleteResult
+import com.mongodb.client.result.UpdateResult
+import com.mongodb.reactivestreams.client.MongoCollection
+import org.bson.Document
+import org.springframework.data.geo.GeoResult
+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 reactor.core.publisher.Flux
+import reactor.core.publisher.Mono
+import kotlin.reflect.KClass
+
+/**
+ * Extension for [ReactiveMongoOperations.indexOps] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.indexOps(entityClass: KClass): ReactiveIndexOperations =
+ indexOps(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.indexOps] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.indexOps(): ReactiveIndexOperations =
+ indexOps(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.execute] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.execute(action: ReactiveCollectionCallback): Flux =
+ execute(T::class.java, action)
+
+/**
+ * Extension for [ReactiveMongoOperations.createCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.createCollection(entityClass: KClass, collectionOptions: CollectionOptions? = null): Mono> =
+ if (collectionOptions != null) createCollection(entityClass.java, collectionOptions) else createCollection(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.createCollection] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.createCollection(collectionOptions: CollectionOptions? = null): Mono> =
+ if (collectionOptions != null) createCollection(T::class.java, collectionOptions) else createCollection(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.collectionExists] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.collectionExists(entityClass: KClass): Mono =
+ collectionExists(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.collectionExists] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.collectionExists(): Mono =
+ collectionExists(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.dropCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.dropCollection(entityClass: KClass): Mono =
+ dropCollection(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.dropCollection] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.dropCollection(): Mono =
+ dropCollection(T::class.java)
+
+
+/**
+ * Extension for [ReactiveMongoOperations.findAll] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.findAll(collectionName: String? = null): Flux =
+ if (collectionName != null) findAll(T::class.java, collectionName) else findAll(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.findOne] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.findOne(query: Query, collectionName: String? = null): Mono =
+ if (collectionName != null) findOne(query, T::class.java, collectionName) else findOne(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.exists] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.exists(query: Query, entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) exists(query, entityClass.java, collectionName) else exists(query, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.exists] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.exists(query: Query, collectionName: String? = null): Mono =
+ if (collectionName != null) exists(query, T::class.java, collectionName) else exists(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.find] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.find(query: Query, collectionName: String? = null): Flux =
+ if (collectionName != null) find(query, T::class.java, collectionName) else find(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.findById] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.findById(id: Any, collectionName: String? = null): Mono =
+ if (collectionName != null) findById(id, T::class.java, collectionName) else findById(id, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.geoNear] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.geoNear(near: NearQuery, collectionName: String? = null): Flux> =
+ if (collectionName != null) geoNear(near, T::class.java, collectionName) else geoNear(near, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.findAndModify] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.findAndModify(query: Query, update: Update, options: FindAndModifyOptions, collectionName: String? = null): Mono =
+ if (collectionName != null) findAndModify(query, update, options, T::class.java, collectionName) else findAndModify(query, update, options, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.findAndRemove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.findAndRemove(query: Query, collectionName: String? = null): Mono =
+ if (collectionName != null) findAndRemove(query, T::class.java, collectionName)
+ else findAndRemove(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.count] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.count(query: Query = Query(), entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) count(query, entityClass.java, collectionName)
+ else count(query, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.count] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.count(query: Query = Query(), collectionName: String? = null): Mono =
+ if (collectionName != null) count(query, T::class.java, collectionName)
+ else count(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.insert] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.insert(batchToSave: Collection, entityClass: KClass): Flux =
+ insert(batchToSave, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.insertAll] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.insertAll(batchToSave: Mono>, entityClass: KClass): Flux =
+ insertAll(batchToSave, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.upsert] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.upsert(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) upsert(query, update, entityClass.java, collectionName) else upsert(query, update, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.upsert] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.upsert(query: Query, update: Update, collectionName: String? = null): Mono =
+ if (collectionName != null) upsert(query, update, T::class.java, collectionName)
+ else upsert(query, update, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.updateFirst] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.updateFirst(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) updateFirst(query, update, entityClass.java, collectionName)
+ else updateFirst(query, update, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.updateFirst] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.updateFirst(query: Query, update: Update, collectionName: String? = null): Mono =
+ if (collectionName != null) updateFirst(query, update, T::class.java, collectionName)
+ else updateFirst(query, update, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.updateMulti] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.updateMulti(query: Query, update: Update, entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) updateMulti(query, update, entityClass.java, collectionName)
+ else updateMulti(query, update, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.updateMulti] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.updateMulti(query: Query, update: Update, collectionName: String? = null): Mono =
+ if (collectionName != null) updateMulti(query, update, T::class.java, collectionName)
+ else updateMulti(query, update, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.remove] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+fun ReactiveMongoOperations.remove(query: Query, entityClass: KClass, collectionName: String? = null): Mono =
+ if (collectionName != null) remove(query, entityClass.java, collectionName)
+ else remove(query, entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.remove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.remove(query: Query, collectionName: String? = null): Mono =
+ if (collectionName != null) remove(query, T::class.java, collectionName)
+ else remove(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.findAllAndRemove] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.findAllAndRemove(query: Query): Flux =
+ findAllAndRemove(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.tail] leveraging reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 2.0
+ */
+inline fun ReactiveMongoOperations.tail(query: Query, collectionName: String? = null): Flux =
+ if (collectionName != null) tail(query, T::class.java, collectionName) else tail(query, T::class.java)
diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt
new file mode 100644
index 0000000000..2f49a75998
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableAggregationOperationExtensionsTests.kt
@@ -0,0 +1,32 @@
+package org.springframework.data.mongodb.core
+
+import example.first.First
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnitRunner
+
+/**
+ * @author Sebastien Deleuze
+ */
+@RunWith(MockitoJUnitRunner::class)
+class ExecutableAggregationOperationExtensionsTests {
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operation: ExecutableAggregationOperation
+
+ @Test // DATAMONGO-1689
+ fun `aggregateAndReturn(KClass) extension should call its Java counterpart`() {
+ operation.aggregateAndReturn(First::class)
+ Mockito.verify(operation, Mockito.times(1)).aggregateAndReturn(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `aggregateAndReturn() with reified type parameter extension should call its Java counterpart`() {
+ operation.aggregateAndReturn()
+ Mockito.verify(operation, Mockito.times(1)).aggregateAndReturn(First::class.java)
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt
new file mode 100644
index 0000000000..20aa74484d
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableFindOperationExtensionsTests.kt
@@ -0,0 +1,47 @@
+package org.springframework.data.mongodb.core
+
+import example.first.First
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnitRunner
+
+/**
+ * @author Sebastien Deleuze
+ */
+@RunWith(MockitoJUnitRunner::class)
+class ExecutableFindOperationExtensionsTests {
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operation: ExecutableFindOperation
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operationWithProjection: ExecutableFindOperation.FindOperationWithProjection
+
+ @Test // DATAMONGO-1689
+ fun `ExecutableFindOperation#query(KClass) extension should call its Java counterpart`() {
+ operation.query(First::class)
+ Mockito.verify(operation, Mockito.times(1)).query(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `ExecutableFindOperation#query() with reified type parameter extension should call its Java counterpart`() {
+ operation.query()
+ Mockito.verify(operation, Mockito.times(1)).query(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `ExecutableFindOperation#FindOperationWithProjection#asType(KClass) extension should call its Java counterpart`() {
+ operationWithProjection.asType(First::class)
+ Mockito.verify(operationWithProjection, Mockito.times(1)).`as`(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `ExecutableFindOperation#FindOperationWithProjection#asType() with reified type parameter extension should call its Java counterpart`() {
+ operationWithProjection.asType()
+ Mockito.verify(operationWithProjection, Mockito.times(1)).`as`(First::class.java)
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt
new file mode 100644
index 0000000000..800c8dd82f
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableInsertOperationExtensionsTests.kt
@@ -0,0 +1,32 @@
+package org.springframework.data.mongodb.core
+
+import example.first.First
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnitRunner
+
+/**
+ * @author Sebastien Deleuze
+ */
+@RunWith(MockitoJUnitRunner::class)
+class ExecutableInsertOperationExtensionsTests {
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operation: ExecutableInsertOperation
+
+ @Test // DATAMONGO-1689
+ fun `insert(KClass) extension should call its Java counterpart`() {
+ operation.insert(First::class)
+ Mockito.verify(operation, Mockito.times(1)).insert(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `insert() with reified type parameter extension should call its Java counterpart`() {
+ operation.insert()
+ Mockito.verify(operation, Mockito.times(1)).insert(First::class.java)
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt
new file mode 100644
index 0000000000..126ff42e8b
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ExecutableRemoveOperationExtensionsTests.kt
@@ -0,0 +1,32 @@
+package org.springframework.data.mongodb.core
+
+import example.first.First
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnitRunner
+
+/**
+ * @author Sebastien Deleuze
+ */
+@RunWith(MockitoJUnitRunner::class)
+class ExecutableRemoveOperationExtensionsTests {
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operation: ExecutableRemoveOperation
+
+ @Test // DATAMONGO-1689
+ fun `remove(KClass) extension should call its Java counterpart`() {
+ operation.remove(First::class)
+ Mockito.verify(operation, Mockito.times(1)).remove(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `remove() with reified type parameter extension should call its Java counterpart`() {
+ operation.remove()
+ Mockito.verify(operation, Mockito.times(1)).remove(First::class.java)
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt
new file mode 100644
index 0000000000..ec3ee3ac4b
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt
@@ -0,0 +1,680 @@
+/*
+ * Copyright 2017 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.nhaarman.mockito_kotlin.mock
+import example.first.First
+import example.second.Second
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.Mock
+import org.mockito.Mockito.*
+import org.mockito.junit.MockitoJUnitRunner
+import org.springframework.data.mongodb.core.BulkOperations.BulkMode
+import org.springframework.data.mongodb.core.aggregation.Aggregation
+import org.springframework.data.mongodb.core.mapreduce.GroupBy
+import org.springframework.data.mongodb.core.mapreduce.MapReduceOptions
+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
+
+/**
+ * @author Sebastien Deleuze
+ */
+@RunWith(MockitoJUnitRunner::class)
+class MongoOperationsExtensionsTests {
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ lateinit var operations: MongoOperations
+
+ @Test // DATAMONGO-1689
+ fun `getCollectionName(KClass) extension should call its Java counterpart`() {
+
+ operations.getCollectionName(First::class)
+ verify(operations, times(1)).getCollectionName(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `getCollectionName() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.getCollectionName()
+ verify(operations, times(1)).getCollectionName(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `execute(CollectionCallback) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionCallback = mock>()
+ operations.execute(collectionCallback)
+ verify(operations, times(1)).execute(First::class.java, collectionCallback)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `stream(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ operations.stream(query)
+ verify(operations, times(1)).stream(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `stream(Query, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ val collectionName = "foo"
+ operations.stream(query, collectionName)
+ verify(operations, times(1)).stream(query, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `createCollection(KClass) extension should call its Java counterpart`() {
+
+ operations.createCollection(First::class)
+ verify(operations, times(1)).createCollection(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `createCollection(KClass, CollectionOptions) extension should call its Java counterpart`() {
+
+ val collectionOptions = mock()
+ operations.createCollection(First::class, collectionOptions)
+ verify(operations, times(1)).createCollection(First::class.java, collectionOptions)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `createCollection() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.createCollection()
+ verify(operations, times(1)).createCollection(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `createCollection(CollectionOptions) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionOptions = mock()
+ operations.createCollection(collectionOptions)
+ verify(operations, times(1)).createCollection(First::class.java, collectionOptions)
+ }
+
+
+ @Test // DATAMONGO-1689
+ fun `collectionExists(KClass) extension should call its Java counterpart`() {
+
+ operations.collectionExists(First::class)
+ verify(operations, times(1)).collectionExists(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `collectionExists() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.collectionExists()
+ verify(operations, times(1)).collectionExists(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `dropCollection(KClass) extension should call its Java counterpart`() {
+
+ operations.dropCollection(First::class)
+ verify(operations, times(1)).dropCollection(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `dropCollection() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.dropCollection()
+ verify(operations, times(1)).dropCollection(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `indexOps(KClass) extension should call its Java counterpart`() {
+
+ operations.indexOps(First::class)
+ verify(operations, times(1)).indexOps(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `indexOps() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.indexOps()
+ verify(operations, times(1)).indexOps(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `bulkOps(BulkMode, KClass) extension should call its Java counterpart`() {
+
+ val bulkMode = BulkMode.ORDERED
+
+ operations.bulkOps(bulkMode, First::class)
+ verify(operations, times(1)).bulkOps(bulkMode, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `bulkOps(BulkMode, KClass, String) extension should call its Java counterpart`() {
+
+ val bulkMode = BulkMode.ORDERED
+ val collectionName = "foo"
+
+ operations.bulkOps(bulkMode, First::class, collectionName)
+ verify(operations, times(1)).bulkOps(bulkMode, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `bulkOps(BulkMode) with reified type parameter extension should call its Java counterpart`() {
+
+ val bulkMode = BulkMode.ORDERED
+
+ operations.bulkOps(bulkMode)
+ verify(operations, times(1)).bulkOps(bulkMode, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `bulkOps(BulkMode, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val bulkMode = BulkMode.ORDERED
+ val collectionName = "foo"
+
+ operations.bulkOps(bulkMode, collectionName)
+ verify(operations, times(1)).bulkOps(bulkMode, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAll() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.findAll()
+ verify(operations, times(1)).findAll(First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAll(String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+
+ operations.findAll(collectionName)
+ verify(operations, times(1)).findAll(First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `group(String, GroupBy) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val groupBy = mock()
+
+ operations.group(collectionName, groupBy)
+ verify(operations, times(1)).group(collectionName, groupBy, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `group(Criteria, String, GroupBy) with reified type parameter extension should call its Java counterpart`() {
+
+ val criteria = mock()
+ val collectionName = "foo"
+ val groupBy = mock()
+
+ operations.group(criteria, collectionName, groupBy)
+ verify(operations, times(1)).group(criteria, collectionName, groupBy, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `aggregate(Aggregation, KClass) with reified type parameter extension should call its Java counterpart`() {
+
+ val aggregation = mock()
+
+ operations.aggregate(aggregation, Second::class)
+ verify(operations, times(1)).aggregate(aggregation, Second::class.java, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `aggregate(Aggregation, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val aggregation = mock()
+ val collectionName = "foo"
+
+ operations.aggregate(aggregation, collectionName)
+ verify(operations, times(1)).aggregate(aggregation, collectionName, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `aggregateStream(Aggregation, KClass) with reified type parameter extension should call its Java counterpart`() {
+
+ val aggregation = mock()
+
+ operations.aggregateStream(aggregation, Second::class)
+ verify(operations, times(1)).aggregateStream(aggregation, Second::class.java, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `aggregateStream(Aggregation, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val aggregation = mock()
+ val collectionName = "foo"
+
+ operations.aggregateStream(aggregation, collectionName)
+ verify(operations, times(1)).aggregateStream(aggregation, collectionName, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `mapReduce(String, String, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val mapFunction = "bar"
+ val reduceFunction = "baz"
+
+ operations.mapReduce(collectionName, mapFunction, reduceFunction)
+ verify(operations, times(1)).mapReduce(collectionName, mapFunction, reduceFunction, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `mapReduce(String, String, String, MapReduceOptions) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val mapFunction = "bar"
+ val reduceFunction = "baz"
+ val options = mock()
+
+ operations.mapReduce(collectionName, mapFunction, reduceFunction, options)
+ verify(operations, times(1)).mapReduce(collectionName, mapFunction, reduceFunction, options, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `mapReduce(Query, String, String, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ val collectionName = "foo"
+ val mapFunction = "bar"
+ val reduceFunction = "baz"
+
+ operations.mapReduce(query, collectionName, mapFunction, reduceFunction)
+ verify(operations, times(1)).mapReduce(query, collectionName, mapFunction, reduceFunction, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `mapReduce(Query, String, String, String, MapReduceOptions) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ val collectionName = "foo"
+ val mapFunction = "bar"
+ val reduceFunction = "baz"
+ val options = mock()
+
+ operations.mapReduce(query, collectionName, mapFunction, reduceFunction, options)
+ verify(operations, times(1)).mapReduce(query, collectionName, mapFunction, reduceFunction, options, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `geoNear(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = NearQuery.near(0.0, 0.0)
+
+ operations.geoNear(query)
+ verify(operations, times(1)).geoNear(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `geoNear(Query, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val query = NearQuery.near(0.0, 0.0)
+
+ operations.geoNear(query, collectionName)
+ verify(operations, times(1)).geoNear(query, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findOne(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+
+ operations.findOne(query)
+ verify(operations, times(1)).findOne(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findOne(Query, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val query = mock()
+
+ operations.findOne(query, collectionName)
+ verify(operations, times(1)).findOne(query, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `exists(Query, KClass) extension should call its Java counterpart`() {
+
+ val query = mock()
+
+ operations.exists(query, First::class)
+ verify(operations, times(1)).exists(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `exists(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+
+ operations.exists(query)
+ verify(operations, times(1)).exists(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `find(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+
+ operations.find(query)
+ verify(operations, times(1)).find(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `find(Query, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val query = mock()
+
+ operations.find(query, collectionName)
+ verify(operations, times(1)).find(query, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findById(Any) with reified type parameter extension should call its Java counterpart`() {
+
+ val id = 1L
+
+ operations.findById(id)
+ verify(operations, times(1)).findById(id, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findById(Any, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val id = 1L
+
+ operations.findById(id, collectionName)
+ verify(operations, times(1)).findById(id, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAndModify(Query, Update, FindAndModifyOptions) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ val update = mock()
+ val options = mock()
+
+ operations.findAndModify(query, update, options)
+ verify(operations, times(1)).findAndModify(query, update, options, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAndModify(Query, Update, FindAndModifyOptions, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val collectionName = "foo"
+ val query = mock()
+ val update = mock()
+ val options = mock()
+
+ operations.findAndModify(query, update, options, collectionName)
+ verify(operations, times(1)).findAndModify(query, update, options, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAndRemove(Query) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+
+ operations.findAndRemove(query)
+ verify(operations, times(1)).findAndRemove(query, First::class.java)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `findAndRemove(Query, String) with reified type parameter extension should call its Java counterpart`() {
+
+ val query = mock()
+ val collectionName = "foo"
+
+ operations.findAndRemove(query, collectionName)
+ verify(operations, times(1)).findAndRemove(query, First::class.java, collectionName)
+ }
+
+ @Test // DATAMONGO-1689
+ fun `count() with reified type parameter extension should call its Java counterpart`() {
+
+ operations.count()
+ verify(operations, times(1)).count(any