org.litote.kmongo.MongoIterables.kt Maven / Gradle / Ivy
/*
* Copyright (C) 2016/2022 Litote
*
* 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.litote.kmongo
import com.mongodb.client.MongoIterable
private val NULL = Any()
private class NullIterator(val iterator: Iterator) : Iterator by iterator {
override fun next(): T? = iterator.next()?.takeUnless { it === NULL }
}
private class NullHandlerSequence(val sequence: Sequence) : Sequence {
override fun iterator(): Iterator = NullIterator(sequence.iterator())
}
/**
* Evaluates the current [MongoIterable] given the [expression] of Sequences.
*
* The mongo cursor is closed before returning the result.
*
* Sample:
* ```
* col.find().evaluate {
* //this is a sequence evaluation
* //If the first row has a name like "Fred", only one row is loaded in memory!
* filter { it.name != "Joe" }.first()
* }
* ```
*/
fun MongoIterable.evaluate(expression: Sequence.() -> R): R {
@Suppress("UNCHECKED_CAST")
return iterator().run {
use {
expression(
NullHandlerSequence(
generateSequence {
if (hasNext()) {
next() ?: NULL
} else {
null
}
}
) as Sequence
)
}
}
}