DATAMONGO-1689 - Add Kotlin extensions for [Reactive]MongoOperations.

We now offer dedicated Kotlin extensions for MongoOperations and ReactiveMongoOperations.

Original pull request: #463.
This commit is contained in:
Sebastien Deleuze
2017-05-15 15:55:14 +02:00
committed by Oliver Gierke
parent a90f238574
commit 2359357977
5 changed files with 1973 additions and 0 deletions

View File

@@ -18,6 +18,7 @@
<properties>
<objenesis>1.3</objenesis>
<equalsverifier>1.5</equalsverifier>
<kotlin>1.1.2-3</kotlin>
</properties>
<dependencies>
@@ -230,12 +231,94 @@
<artifactId>spring-webmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.nhaarman</groupId>
<artifactId>mockito-kotlin</artifactId>
<version>1.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin}</version>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>

View File

@@ -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 <T : Any> MongoOperations.getCollectionName(entityClass: KClass<T>): 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 <reified T : Any> 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 <reified T : Any> MongoOperations.execute(action: CollectionCallback<T>): 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 <reified T : Any> MongoOperations.stream(query: Query): CloseableIterator<T> =
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 <reified T : Any> MongoOperations.stream(query: Query,
collectionName: String? = null): CloseableIterator<T> =
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 <T : Any> MongoOperations.createCollection(entityClass: KClass<T>,
collectionOptions: CollectionOptions? = null): MongoCollection<Document> =
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 <reified T : Any> MongoOperations.createCollection(
collectionOptions: CollectionOptions? = null): MongoCollection<Document> =
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 <T : Any> MongoOperations.collectionExists(entityClass: KClass<T>): 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 <reified T : Any> MongoOperations.collectionExists(): Boolean =
collectionExists(T::class.java)
/**
* Extension for [MongoOperations.dropCollection] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> MongoOperations.dropCollection(entityClass: KClass<T>) {
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 <reified T : Any> MongoOperations.dropCollection() {
dropCollection(T::class.java)
}
/**
* Extension for [MongoOperations.indexOps] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> MongoOperations.indexOps(entityClass: KClass<T>): 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 <reified T : Any> MongoOperations.indexOps(): IndexOperations =
indexOps(T::class.java)
/**
* Extension for [MongoOperations.bulkOps] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> MongoOperations.bulkOps(bulkMode: BulkMode, entityClass: KClass<T>,
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 <reified T : Any> 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 <reified T : Any> MongoOperations.findAll(collectionName: String? = null): List<T> =
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 <reified T : Any> MongoOperations.group(inputCollectionName: String, groupBy: GroupBy): GroupByResults<T> =
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 <reified T : Any> MongoOperations.group(criteria: Criteria,
inputCollectionName: String, groupBy: GroupBy): GroupByResults<T> =
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 <reified O : Any> MongoOperations.aggregate(aggregation: Aggregation,
inputType: KClass<*>): AggregationResults<O> =
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 <reified O : Any> MongoOperations.aggregate(aggregation: Aggregation,
collectionName: String): AggregationResults<O> =
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 <reified O : Any> MongoOperations.aggregateStream(aggregation: Aggregation,
inputType: KClass<*>): CloseableIterator<O> =
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 <reified O : Any> MongoOperations.aggregateStream(aggregation: Aggregation,
collectionName: String): CloseableIterator<O> =
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 <reified T : Any> MongoOperations.mapReduce(collectionName: String,
mapFunction: String, reduceFunction: String, options: MapReduceOptions? = null): MapReduceResults<T> =
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 <reified T : Any> MongoOperations.mapReduce(query: Query, collectionName: String,
mapFunction: String, reduceFunction: String, options: MapReduceOptions? = null): MapReduceResults<T> =
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 <reified T : Any> MongoOperations.geoNear(near: NearQuery,
collectionName: String? = null): GeoResults<T> =
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 <reified T : Any> 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 <T : Any> MongoOperations.exists(query: Query, entityClass: KClass<T>,
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 <reified T : Any> 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 <reified T : Any> MongoOperations.find(query: Query, collectionName: String? = null): List<T> =
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 <reified T : Any> 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 <reified T : Any> 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 <reified T : Any> 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 <T : Any> MongoOperations.count(query: Query = Query(), entityClass: KClass<T>,
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 <reified T : Any> 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 <T : Any> MongoOperations.insert(batchToSave: Collection<T>, entityClass: KClass<T>) {
insert(batchToSave, entityClass.java)
}
/**
* Extension for [MongoOperations.upsert] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> MongoOperations.upsert(query: Query, update: Update, entityClass: KClass<T>,
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 <reified T : Any> 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 <T : Any> MongoOperations.updateFirst(query: Query, update: Update, entityClass: KClass<T>,
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 <reified T : Any> 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 <T : Any> MongoOperations.updateMulti(query: Query, update: Update, entityClass: KClass<T>,
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 <reified T : Any> 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 <T : Any> MongoOperations.remove(query: Query, entityClass: KClass<T>,
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 <reified T : Any> 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 <reified T : Any> MongoOperations.findAllAndRemove(query: Query): List<T> =
findAllAndRemove(query, T::class.java)

View File

@@ -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 <T : Any> ReactiveMongoOperations.indexOps(entityClass: KClass<T>): 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 <reified T : Any> 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 <reified T : Any> ReactiveMongoOperations.execute(action: ReactiveCollectionCallback<T>): Flux<T> =
execute(T::class.java, action)
/**
* Extension for [ReactiveMongoOperations.createCollection] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> ReactiveMongoOperations.createCollection(entityClass: KClass<T>,
collectionOptions: CollectionOptions? = null): Mono<MongoCollection<Document>> =
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 <reified T : Any> ReactiveMongoOperations.createCollection(
collectionOptions: CollectionOptions? = null): Mono<MongoCollection<Document>> =
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 <T : Any> ReactiveMongoOperations.collectionExists(entityClass: KClass<T>): Mono<Boolean> =
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 <reified T : Any> ReactiveMongoOperations.collectionExists(): Mono<Boolean> =
collectionExists(T::class.java)
/**
* Extension for [ReactiveMongoOperations.dropCollection] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> ReactiveMongoOperations.dropCollection(entityClass: KClass<T>): Mono<Void> =
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 <reified T : Any> ReactiveMongoOperations.dropCollection(): Mono<Void> =
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 <reified T : Any> ReactiveMongoOperations.findAll(collectionName: String? = null): Flux<T> =
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 <reified T : Any> ReactiveMongoOperations.findOne(query: Query, collectionName: String? = null): Mono<T> =
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 <T : Any> ReactiveMongoOperations.exists(query: Query, entityClass: KClass<T>,
collectionName: String? = null): Mono<Boolean> =
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 <reified T : Any> ReactiveMongoOperations.exists(query: Query,
collectionName: String? = null): Mono<Boolean> =
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 <reified T : Any> ReactiveMongoOperations.find(query: Query, collectionName: String? = null): Flux<T> =
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 <reified T : Any> ReactiveMongoOperations.findById(id: Any, collectionName: String? = null): Mono<T> =
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 <reified T : Any> ReactiveMongoOperations.geoNear(near: NearQuery,
collectionName: String? = null): Flux<GeoResult<T>> =
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 <reified T : Any> ReactiveMongoOperations.findAndModify(query: Query,
update: Update, options: FindAndModifyOptions, collectionName: String? = null): Mono<T> =
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 <reified T : Any> ReactiveMongoOperations.findAndRemove(query: Query,
collectionName: String? = null): Mono<T> =
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 <T : Any> ReactiveMongoOperations.count(query: Query = Query(), entityClass: KClass<T>,
collectionName: String? = null): Mono<Long> =
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 <reified T : Any> ReactiveMongoOperations.count(query: Query = Query(),
collectionName: String? = null): Mono<Long> =
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 <T : Any> ReactiveMongoOperations.insert(batchToSave: Collection<T>, entityClass: KClass<T>): Flux<T> =
insert(batchToSave, entityClass.java)
/**
* Extension for [ReactiveMongoOperations.insertAll] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> ReactiveMongoOperations.insertAll(batchToSave: Mono<out Collection<T>>,
entityClass: KClass<T>): Flux<T> =
insertAll(batchToSave, entityClass.java)
/**
* Extension for [ReactiveMongoOperations.upsert] providing a [KClass] based variant.
*
* @author Sebastien Deleuze
* @since 5.0
*/
fun <T : Any> ReactiveMongoOperations.upsert(query: Query, update: Update, entityClass: KClass<T>,
collectionName: String? = null): Mono<UpdateResult> =
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 <reified T : Any> ReactiveMongoOperations.upsert(query: Query, update: Update,
collectionName: String? = null): Mono<UpdateResult> =
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 <T : Any> ReactiveMongoOperations.updateFirst(query: Query, update: Update,
entityClass: KClass<T>, collectionName: String? = null): Mono<UpdateResult> =
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 <reified T : Any> ReactiveMongoOperations.updateFirst(query: Query, update: Update,
collectionName: String? = null): Mono<UpdateResult> =
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 <T : Any> ReactiveMongoOperations.updateMulti(query: Query, update: Update,
entityClass: KClass<T>, collectionName: String? = null): Mono<UpdateResult> =
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 <reified T : Any> ReactiveMongoOperations.updateMulti(query: Query, update: Update,
collectionName: String? = null): Mono<UpdateResult> =
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 <T : Any> ReactiveMongoOperations.remove(query: Query, entityClass: KClass<T>,
collectionName: String? = null): Mono<DeleteResult> =
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 <reified T : Any> ReactiveMongoOperations.remove(query: Query,
collectionName: String? = null): Mono<DeleteResult> =
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 <reified T : Any> ReactiveMongoOperations.findAllAndRemove(query: Query): Flux<T> =
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 <reified T : Any> ReactiveMongoOperations.tail(query: Query, collectionName: String? = null): Flux<T> =
if (collectionName != null) tail(query, T::class.java, collectionName) else tail(query, T::class.java)

View File

@@ -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<First>()
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<CollectionCallback<First>>()
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<Query>()
operations.stream<First>(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<Query>()
val collectionName = "foo"
operations.stream<First>(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<CollectionOptions>()
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<First>()
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<CollectionOptions>()
operations.createCollection<First>(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<First>()
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<First>()
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<First>()
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<First>(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<First>(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<First>()
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<First>(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<GroupBy>()
operations.group<First>(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<Criteria>()
val collectionName = "foo"
val groupBy = mock<GroupBy>()
operations.group<First>(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<Aggregation>()
operations.aggregate<First>(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<Aggregation>()
val collectionName = "foo"
operations.aggregate<First>(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<Aggregation>()
operations.aggregateStream<First>(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<Aggregation>()
val collectionName = "foo"
operations.aggregateStream<First>(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<First>(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<MapReduceOptions>()
operations.mapReduce<First>(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<Query>()
val collectionName = "foo"
val mapFunction = "bar"
val reduceFunction = "baz"
operations.mapReduce<First>(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<Query>()
val collectionName = "foo"
val mapFunction = "bar"
val reduceFunction = "baz"
val options = mock<MapReduceOptions>()
operations.mapReduce<First>(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<First>(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<First>(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<Query>()
operations.findOne<First>(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<Query>()
operations.findOne<First>(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<Query>()
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<Query>()
operations.exists<First>(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<Query>()
operations.find<First>(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<Query>()
operations.find<First>(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<First>(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<First>(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<Query>()
val update = mock<Update>()
val options = mock<FindAndModifyOptions>()
operations.findAndModify<First>(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<Query>()
val update = mock<Update>()
val options = mock<FindAndModifyOptions>()
operations.findAndModify<First>(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<Query>()
operations.findAndRemove<First>(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<Query>()
val collectionName = "foo"
operations.findAndRemove<First>(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<First>()
verify(operations, times(1)).count(any<Query>(), eq(First::class.java))
}
@Test
fun `count(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.count<First>(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<Query>()
val collectionName = "foo"
operations.count<First>(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<Query>()
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<Query>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.upsert<First>(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<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.upsert<First>(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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.updateFirst<First>(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<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.updateFirst<First>(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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.updateMulti<First>(query, update)
verify(operations, times(1)).updateMulti(query, update, First::class.java)
}
@Test
fun `updateMulti(Query, Update, String) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.updateMulti<First>(query, update, collectionName)
verify(operations, times(1)).updateMulti(query, update, First::class.java, collectionName)
}
@Test
fun `remove(Query, KClass) extension should call its Java counterpart`() {
val query = mock<Query>()
operations.remove(query, First::class)
verify(operations, times(1)).remove(query, First::class.java)
}
@Test
fun `remove(Query, KClass, String) extension should call its Java counterpart`() {
val query = mock<Query>()
val collectionName = "foo"
operations.remove(query, First::class, collectionName)
verify(operations, times(1)).remove(query, First::class.java, collectionName)
}
@Test
fun `remove(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.remove<First>(query)
verify(operations, times(1)).remove(query, First::class.java)
}
@Test
fun `remove(Query, String) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val collectionName = "foo"
operations.remove<First>(query, collectionName)
verify(operations, times(1)).remove(query, First::class.java, collectionName)
}
@Test
fun `findAllAndRemove(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.findAllAndRemove<First>(query)
verify(operations, times(1)).findAllAndRemove(query, First::class.java)
}
}

View File

@@ -0,0 +1,434 @@
/*
* 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 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.query.NearQuery
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import reactor.core.publisher.Mono
/**
* @author Sebastien Deleuze
*/
@RunWith(MockitoJUnitRunner::class)
class ReactiveMongoOperationsExtensionsTests {
@Mock(answer = Answers.RETURNS_MOCKS)
lateinit var operations: ReactiveMongoOperations
@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<First>()
verify(operations, times(1)).indexOps(First::class.java)
}
@Test
fun `execute(ReactiveCollectionCallback) with reified type parameter extension should call its Java counterpart`() {
val collectionCallback = mock<ReactiveCollectionCallback<First>>()
operations.execute(collectionCallback)
verify(operations, times(1)).execute(First::class.java, collectionCallback)
}
@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<CollectionOptions>()
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<First>()
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<CollectionOptions>()
operations.createCollection<First>(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<First>()
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<First>()
verify(operations, times(1)).dropCollection(First::class.java)
}
@Test
fun `findAll() with reified type parameter extension should call its Java counterpart`() {
operations.findAll<First>()
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<First>(collectionName)
verify(operations, times(1)).findAll(First::class.java, collectionName)
}
@Test
fun `findOne(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.findOne<First>(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<Query>()
operations.findOne<First>(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<Query>()
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<Query>()
operations.exists<First>(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<Query>()
operations.find<First>(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<Query>()
operations.find<First>(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<First>(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<First>(id, collectionName)
verify(operations, times(1)).findById(id, First::class.java, collectionName)
}
@Test
fun `geoNear(Query) with reified type parameter extension should call its Java counterpart`() {
val query = NearQuery.near(0.0, 0.0)
operations.geoNear<First>(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<First>(query, collectionName)
verify(operations, times(1)).geoNear(query, First::class.java, collectionName)
}
@Test
fun `findAndModify(Query, Update, FindAndModifyOptions) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val update = mock<Update>()
val options = mock<FindAndModifyOptions>()
operations.findAndModify<First>(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<Query>()
val update = mock<Update>()
val options = mock<FindAndModifyOptions>()
operations.findAndModify<First>(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<Query>()
operations.findAndRemove<First>(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<Query>()
val collectionName = "foo"
operations.findAndRemove<First>(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<First>()
verify(operations, times(1)).count(any<Query>(), eq(First::class.java))
}
@Test
fun `count(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.count<First>(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<Query>()
val collectionName = "foo"
operations.count<First>(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<Query>()
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<Query>()
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 `insertAll(Mono, KClass) extension should call its Java counterpart`() {
val collection = Mono.just(listOf(First(), First()))
operations.insertAll(collection, First::class)
verify(operations, times(1)).insertAll(collection, First::class.java)
}
@Test
fun `upsert(Query, Update, KClass) extension should call its Java counterpart`() {
val query = mock<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.upsert<First>(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<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.upsert<First>(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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.updateFirst<First>(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<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.updateFirst<First>(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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
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<Query>()
val update = mock<Update>()
operations.updateMulti<First>(query, update)
verify(operations, times(1)).updateMulti(query, update, First::class.java)
}
@Test
fun `updateMulti(Query, Update, String) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val update = mock<Update>()
val collectionName = "foo"
operations.updateMulti<First>(query, update, collectionName)
verify(operations, times(1)).updateMulti(query, update, First::class.java, collectionName)
}
@Test
fun `remove(Query, KClass) extension should call its Java counterpart`() {
val query = mock<Query>()
operations.remove(query, First::class)
verify(operations, times(1)).remove(query, First::class.java)
}
@Test
fun `remove(Query, KClass, String) extension should call its Java counterpart`() {
val query = mock<Query>()
val collectionName = "foo"
operations.remove(query, First::class, collectionName)
verify(operations, times(1)).remove(query, First::class.java, collectionName)
}
@Test
fun `remove(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.remove<First>(query)
verify(operations, times(1)).remove(query, First::class.java)
}
@Test
fun `remove(Query, String) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val collectionName = "foo"
operations.remove<First>(query, collectionName)
verify(operations, times(1)).remove(query, First::class.java, collectionName)
}
@Test
fun `findAllAndRemove(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.findAllAndRemove<First>(query)
verify(operations, times(1)).findAllAndRemove(query, First::class.java)
}
@Test
fun `tail(Query) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
operations.tail<First>(query)
verify(operations, times(1)).tail(query, First::class.java)
}
@Test
fun `tail(Query, String) with reified type parameter extension should call its Java counterpart`() {
val query = mock<Query>()
val collectionName = "foo"
operations.tail<First>(query, collectionName)
verify(operations, times(1)).tail(query, First::class.java, collectionName)
}
}