commonMain.io.realm.kotlin.internal.RealmResultsImpl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of library-base-jvm Show documentation
Show all versions of library-base-jvm Show documentation
Library code for Realm Kotlin. This artifact is not supposed to be consumed directly, but through 'io.realm.kotlin:gradle-plugin:1.11.1' instead.
/*
* Copyright 2020 Realm Inc.
*
* 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 io.realm.kotlin.internal
import io.realm.kotlin.internal.RealmValueArgumentConverter.convertToQueryArgs
import io.realm.kotlin.internal.interop.Callback
import io.realm.kotlin.internal.interop.ClassKey
import io.realm.kotlin.internal.interop.RealmChangesPointer
import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.interop.RealmInterop.realm_results_get
import io.realm.kotlin.internal.interop.RealmKeyPathArrayPointer
import io.realm.kotlin.internal.interop.RealmNotificationTokenPointer
import io.realm.kotlin.internal.interop.RealmResultsPointer
import io.realm.kotlin.internal.interop.getterScope
import io.realm.kotlin.internal.interop.inputScope
import io.realm.kotlin.internal.query.ObjectQuery
import io.realm.kotlin.internal.util.Validation.sdkError
import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.notifications.internal.InitialResultsImpl
import io.realm.kotlin.notifications.internal.UpdatedResultsImpl
import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.TRUE_PREDICATE
import io.realm.kotlin.types.BaseRealmObject
import kotlinx.coroutines.channels.ProducerScope
import kotlinx.coroutines.flow.Flow
import kotlin.reflect.KClass
/**
* Primitive results are not exposed through the public API but might be needed when implementing
* `RealmDictionary.values` as Core returns those as results.
*/
// TODO OPTIMIZE Perhaps we should map the output of dictionary.values to a RealmList so that
// primitive typed results are never ever exposed publicly.
// TODO OPTIMIZE We create the same type every time, so don't have to perform map/distinction every time
internal class RealmResultsImpl constructor(
internal val realm: RealmReference,
internal val nativePointer: RealmResultsPointer,
private val classKey: ClassKey,
private val clazz: KClass,
private val mediator: Mediator,
@Suppress("UnusedPrivateMember")
private val mode: Mode = Mode.RESULTS,
) : AbstractList(), RealmResults, InternalDeleteable, CoreNotifiable, ResultsChange>, RealmStateHolder {
internal enum class Mode {
// FIXME Needed to make working with @LinkingObjects easier.
EMPTY, // RealmResults that is always empty.
RESULTS // RealmResults wrapping a Realm Core Results.
}
override val size: Int
get() = RealmInterop.realm_results_count(nativePointer).toInt()
override fun get(index: Int): E = getterScope {
realmValueToRealmObject(
realm_results_get(nativePointer, index.toLong()),
clazz,
mediator,
realm
) as E
}
override fun query(query: String, vararg args: Any?): RealmQuery = inputScope {
// If an empty query is passed in, reconstruct the original query backing this RealmResults
val queryPointer = if (query.trim().compareTo(TRUE_PREDICATE, ignoreCase = true) == 0 && args.isEmpty()) {
RealmInterop.realm_results_get_query(nativePointer)
} else {
try {
RealmInterop.realm_query_parse_for_results(
nativePointer,
query,
convertToQueryArgs(args)
)
} catch (e: IndexOutOfBoundsException) {
throw IllegalArgumentException(e.message, e.cause)
}
}
ObjectQuery(
realm,
classKey,
clazz,
mediator,
queryPointer,
)
}
override fun asFlow(keyPaths: List?): Flow> {
realm.checkClosed()
val keyPathInfo = keyPaths?.let {
Pair(classKey, keyPaths)
}
return realm.owner.registerObserver(this, keyPathInfo)
}
override fun delete() {
// TODO OPTIMIZE Are there more efficient ways to do this? realm_query_delete_all is not
// available in C-API yet
RealmInterop.realm_results_delete_all(nativePointer)
}
/**
* Returns a frozen copy of this query result. If it is already frozen, the same instance
* is returned.
*/
override fun freeze(frozenRealm: RealmReference): RealmResultsImpl {
val frozenDbPointer = frozenRealm.dbPointer
val frozenResults = RealmInterop.realm_results_resolve_in(nativePointer, frozenDbPointer)
return RealmResultsImpl(frozenRealm, frozenResults, classKey, clazz, mediator)
}
/**
* Thaw the frozen query result, turning it back into a live, thread-confined RealmResults.
*/
override fun thaw(liveRealm: RealmReference): RealmResultsImpl {
val liveDbPointer = liveRealm.dbPointer
val liveResultPtr = RealmInterop.realm_results_resolve_in(nativePointer, liveDbPointer)
return RealmResultsImpl(liveRealm, liveResultPtr, classKey, clazz, mediator)
}
override fun registerForNotification(
keyPaths: RealmKeyPathArrayPointer?,
callback: Callback
): RealmNotificationTokenPointer {
return RealmInterop.realm_results_add_notification_callback(nativePointer, keyPaths, callback)
}
override fun changeFlow(scope: ProducerScope>): ChangeFlow, ResultsChange> =
ResultChangeFlow(scope)
override fun realmState(): RealmState = realm
override fun isValid(): Boolean {
return !nativePointer.isReleased() && !realm.isClosed()
}
}
internal class ResultChangeFlow(scope: ProducerScope>) :
ChangeFlow, ResultsChange>(scope) {
override fun initial(frozenRef: RealmResultsImpl): ResultsChange =
InitialResultsImpl(frozenRef)
override fun update(
frozenRef: RealmResultsImpl,
change: RealmChangesPointer
): ResultsChange {
val listChangeSetBuilderImpl = ListChangeSetBuilderImpl(change)
return UpdatedResultsImpl(frozenRef, listChangeSetBuilderImpl.build())
}
override fun delete(): ResultsChange =
sdkError("Results should never have been deleted")
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy