diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 99ef83a54..7e964146a 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -18,6 +18,7 @@
1.3
1.5
+ 1.1.2-3
@@ -230,12 +231,94 @@
spring-webmvc
test
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jre8
+ ${kotlin}
+ true
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ ${kotlin}
+ true
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin}
+ test
+
+
+ com.nhaarman
+ mockito-kotlin
+ 1.4.0
+ test
+
+
+ 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/MongoOperationsExtensions.kt b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt
new file mode 100644
index 000000000..27afc6cc0
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensions.kt
@@ -0,0 +1,520 @@
+/*
+ * 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 5.0
+ */
+fun MongoOperations.getCollectionName(entityClass: KClass): String =
+ getCollectionName(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.getCollectionName] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.getCollectionName(): String =
+ getCollectionName(T::class.java)
+
+/**
+ * Extension for [MongoOperations.execute] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.execute(action: CollectionCallback): T =
+ execute(T::class.java, action)
+
+/**
+ * Extension for [MongoOperations.stream] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.stream(query: Query): CloseableIterator =
+ stream(query, T::class.java)
+
+/**
+ * Extension for [MongoOperations.stream] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.0
+ */
+fun MongoOperations.collectionExists(entityClass: KClass): Boolean =
+ collectionExists(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.collectionExists] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.collectionExists(): Boolean =
+ collectionExists(T::class.java)
+
+/**
+ * Extension for [MongoOperations.dropCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+fun MongoOperations.dropCollection(entityClass: KClass) {
+ dropCollection(entityClass.java)
+}
+
+/**
+ * Extension for [MongoOperations.dropCollection] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.dropCollection() {
+ dropCollection(T::class.java)
+}
+
+/**
+ * Extension for [MongoOperations.indexOps] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+fun MongoOperations.indexOps(entityClass: KClass): IndexOperations =
+ indexOps(entityClass.java)
+
+/**
+ * Extension for [MongoOperations.indexOps] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.indexOps(): IndexOperations =
+ indexOps(T::class.java)
+
+/**
+ * Extension for [MongoOperations.bulkOps] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.group(inputCollectionName: String, groupBy: GroupBy): GroupByResults =
+ group(inputCollectionName, groupBy, T::class.java)
+
+/**
+ * Extension for [MongoOperations.group] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.group(criteria: Criteria,
+ inputCollectionName: String, groupBy: GroupBy): GroupByResults =
+ group(criteria, inputCollectionName, groupBy, T::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregate] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.aggregate(aggregation: Aggregation,
+ inputType: KClass<*>): AggregationResults =
+ aggregate(aggregation, inputType.java, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregate] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.aggregate(aggregation: Aggregation,
+ collectionName: String): AggregationResults =
+ aggregate(aggregation, collectionName, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregateStream] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.aggregateStream(aggregation: Aggregation,
+ inputType: KClass<*>): CloseableIterator =
+ aggregateStream(aggregation, inputType.java, O::class.java)
+
+/**
+ * Extension for [MongoOperations.aggregateStream] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun MongoOperations.aggregateStream(aggregation: Aggregation,
+ collectionName: String): CloseableIterator =
+ aggregateStream(aggregation, collectionName, O::class.java)
+
+/**
+ * Extension for [MongoOperations.mapReduce] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 000000000..bc00f4707
--- /dev/null
+++ b/spring-data-mongodb/src/main/kotlin/org/springframework/data/mongodb/core/ReactiveMongoOperationsExtensions.kt
@@ -0,0 +1,374 @@
+/*
+ * 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 5.0
+ */
+fun ReactiveMongoOperations.indexOps(entityClass: KClass): ReactiveIndexOperations =
+ indexOps(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.indexOps] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun ReactiveMongoOperations.indexOps(): ReactiveIndexOperations =
+ indexOps(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.execute] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.0
+ */
+fun ReactiveMongoOperations.collectionExists(entityClass: KClass): Mono =
+ collectionExists(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.collectionExists] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun ReactiveMongoOperations.collectionExists(): Mono =
+ collectionExists(T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.dropCollection] providing a [KClass] based variant.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+fun ReactiveMongoOperations.dropCollection(entityClass: KClass): Mono =
+ dropCollection(entityClass.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.dropCollection] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+inline fun ReactiveMongoOperations.dropCollection(): Mono =
+ dropCollection(T::class.java)
+
+
+/**
+ * Extension for [ReactiveMongoOperations.findAll] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.0
+ */
+@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
+inline fun ReactiveMongoOperations.findAllAndRemove(query: Query): Flux =
+ findAllAndRemove(query, T::class.java)
+
+/**
+ * Extension for [ReactiveMongoOperations.tail] avoiding requiring the type parameter
+ * thanks to Kotlin reified type parameters.
+ *
+ * @author Sebastien Deleuze
+ * @since 5.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/MongoOperationsExtensionsTests.kt b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt
new file mode 100644
index 000000000..97b895060
--- /dev/null
+++ b/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/MongoOperationsExtensionsTests.kt
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2016-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
+ fun `getCollectionName(KClass) extension should call its Java counterpart`() {
+ operations.getCollectionName(First::class)
+ verify(operations, times(1)).getCollectionName(First::class.java)
+ }
+
+ @Test
+ fun `getCollectionName() with reified type parameter extension should call its Java counterpart`() {
+ operations.getCollectionName()
+ verify(operations, times(1)).getCollectionName(First::class.java)
+ }
+
+ @Test
+ 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
+ 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
+ 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
+ fun `createCollection(KClass) extension should call its Java counterpart`() {
+ operations.createCollection(First::class)
+ verify(operations, times(1)).createCollection(First::class.java)
+ }
+
+ @Test
+ 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
+ fun `createCollection() with reified type parameter extension should call its Java counterpart`() {
+ operations.createCollection()
+ verify(operations, times(1)).createCollection(First::class.java)
+ }
+
+ @Test
+ 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
+ fun `collectionExists(KClass) extension should call its Java counterpart`() {
+ operations.collectionExists(First::class)
+ verify(operations, times(1)).collectionExists(First::class.java)
+ }
+
+ @Test
+ fun `collectionExists() with reified type parameter extension should call its Java counterpart`() {
+ operations.collectionExists()
+ verify(operations, times(1)).collectionExists(First::class.java)
+ }
+
+ @Test
+ fun `dropCollection(KClass) extension should call its Java counterpart`() {
+ operations.dropCollection(First::class)
+ verify(operations, times(1)).dropCollection(First::class.java)
+ }
+
+ @Test
+ fun `dropCollection() with reified type parameter extension should call its Java counterpart`() {
+ operations.dropCollection()
+ verify(operations, times(1)).dropCollection(First::class.java)
+ }
+
+ @Test
+ fun `indexOps(KClass) extension should call its Java counterpart`() {
+ operations.indexOps(First::class)
+ verify(operations, times(1)).indexOps(First::class.java)
+ }
+
+ @Test
+ fun `indexOps() with reified type parameter extension should call its Java counterpart`() {
+ operations.indexOps()
+ verify(operations, times(1)).indexOps(First::class.java)
+ }
+
+ @Test
+ 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
+ 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
+ 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
+ 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
+ fun `findAll() with reified type parameter extension should call its Java counterpart`() {
+ operations.findAll()
+ verify(operations, times(1)).findAll(First::class.java)
+ }
+
+ @Test
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ fun `count() with reified type parameter extension should call its Java counterpart`() {
+ operations.count()
+ verify(operations, times(1)).count(any(), eq(First::class.java))
+ }
+
+ @Test
+ fun `count(Query) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ operations.count(query)
+ verify(operations, times(1)).count(query, First::class.java)
+ }
+
+ @Test
+ fun `count(Query, String) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val collectionName = "foo"
+ operations.count(query, collectionName)
+ verify(operations, times(1)).count(query, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `count(Query, KClass) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ operations.count(query, First::class)
+ verify(operations, times(1)).count(query, First::class.java)
+ }
+
+ @Test
+ fun `count(Query, KClass, String) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val collectionName = "foo"
+ operations.count(query, First::class, collectionName)
+ verify(operations, times(1)).count(query, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `insert(Collection, KClass) extension should call its Java counterpart`() {
+ val collection = listOf(First(), First())
+ operations.insert(collection, First::class)
+ verify(operations, times(1)).insert(collection, First::class.java)
+ }
+
+ @Test
+ fun `upsert(Query, Update, KClass) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.upsert(query, update, First::class)
+ verify(operations, times(1)).upsert(query, update, First::class.java)
+ }
+
+ @Test
+ fun `upsert(Query, Update, KClass, String) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ val collectionName = "foo"
+ operations.upsert(query, update, First::class, collectionName)
+ verify(operations, times(1)).upsert(query, update, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `upsert(Query, Update) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.upsert(query, update)
+ verify(operations, times(1)).upsert(query, update, First::class.java)
+ }
+
+ @Test
+ fun `upsert(Query, Update, String) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ val collectionName = "foo"
+ operations.upsert(query, update, collectionName)
+ verify(operations, times(1)).upsert(query, update, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `updateFirst(Query, Update, KClass) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.updateFirst(query, update, First::class)
+ verify(operations, times(1)).updateFirst(query, update, First::class.java)
+ }
+
+ @Test
+ fun `updateFirst(Query, Update, KClass, String) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ val collectionName = "foo"
+ operations.updateFirst(query, update, First::class, collectionName)
+ verify(operations, times(1)).updateFirst(query, update, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `updateFirst(Query, Update) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.updateFirst(query, update)
+ verify(operations, times(1)).updateFirst(query, update, First::class.java)
+ }
+
+ @Test
+ fun `updateFirst(Query, Update, String) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ val collectionName = "foo"
+ operations.updateFirst(query, update, collectionName)
+ verify(operations, times(1)).updateFirst(query, update, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `updateMulti(Query, Update, KClass) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.updateMulti(query, update, First::class)
+ verify(operations, times(1)).updateMulti(query, update, First::class.java)
+ }
+
+ @Test
+ fun `updateMulti(Query, Update, KClass, String) extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ val collectionName = "foo"
+ operations.updateMulti(query, update, First::class, collectionName)
+ verify(operations, times(1)).updateMulti(query, update, First::class.java, collectionName)
+ }
+
+ @Test
+ fun `updateMulti(Query, Update) with reified type parameter extension should call its Java counterpart`() {
+ val query = mock()
+ val update = mock()
+ operations.updateMulti