All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.realm.kotlin.ext.BaseRealmObjectExt.kt Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 3.0.0
Show newest version
/*
 * Copyright 2022 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.ext

import io.realm.kotlin.Realm
import io.realm.kotlin.VersionId
import io.realm.kotlin.dynamic.DynamicRealmObject
import io.realm.kotlin.internal.UnmanagedState
import io.realm.kotlin.internal.checkNotificationsAvailable
import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.realmObjectReference
import io.realm.kotlin.internal.runIfManaged
import io.realm.kotlin.migration.AutomaticSchemaMigration
import io.realm.kotlin.notifications.DeletedObject
import io.realm.kotlin.notifications.InitialObject
import io.realm.kotlin.notifications.ObjectChange
import io.realm.kotlin.notifications.UpdatedObject
import io.realm.kotlin.types.BaseRealmObject
import io.realm.kotlin.types.EmbeddedRealmObject
import io.realm.kotlin.types.RealmObject
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow

/**
 * Returns whether the object is frozen or not.
 *
 * A frozen object is tied to a specific version of the data in the realm and fields retrieved
 * from this object instance will not update even if the object is updated in the Realm.
 *
 * @return true if the object is frozen, false otherwise.
 */
public fun BaseRealmObject.isFrozen(): Boolean =
    (realmObjectReference ?: UnmanagedState).isFrozen()

/**
 * Returns the Realm version of this object. This version number is tied to the transaction the object was read from.
 */
public fun BaseRealmObject.version(): VersionId =
    (realmObjectReference ?: UnmanagedState).version()

/**
 * Returns whether or not this object is managed by Realm.
 *
 * Managed objects are only valid to use while the Realm is open, but also have access to all Realm API's like
 * queries or change listeners. Unmanaged objects behave like normal Kotlin objects and are completely separate from
 * Realm.
 */
public fun BaseRealmObject.isManaged(): Boolean = realmObjectReference != null

/**
 * Returns true if this object is still valid to use, i.e. the Realm is open and the underlying object has
 * not been deleted. Unmanaged objects are always valid.
 */
public fun BaseRealmObject.isValid(): Boolean = runIfManaged {
    return !objectPointer.isReleased() && RealmInterop.realm_object_is_valid(objectPointer)
} ?: true

/**
 * Observe changes to a Realm object. The flow would emit an [InitialObject] once subscribed and
 * then, on every change to the object an [UpdatedObject]. If the observed object is deleted from
 * the Realm, the flow would emit a [DeletedObject] and then will complete, otherwise it will
 * continue running until canceled.
 *
 * The change calculations will be executed on the thread represented by
 * `Configuration.notificationDispatcher`.
 *
 * The flow has an internal buffer of [Channel.BUFFERED] but if the consumer fails to consume
 * the elements in a timely manner the coroutine scope will be cancelled with a
 * [CancellationException].
 *
 * @param keyPaths An optional list of properties that defines when a change to the object will
 * result in a change being emitted. Nested properties can be defined using a dotted
 * syntax, e.g. `parent.child.name`. Wildcards `*` can be be used to capture all properties at a
 * given level, e.g. `child.*` or `*.*`. If no keypaths are provided, changes to all top-level
 * properties and nested properties 4 levels down will trigger a change.
 * @return a flow representing changes to the object.
 * @throws UnsupportedOperationException if called on a live [RealmObject] or [EmbeddedRealmObject]
 * from a write transaction ([Realm.write]) or on a [DynamicRealmObject] inside a migration
 * ([AutomaticSchemaMigration.migrate]).
 * @throws IllegalArgumentException if an invalid keypath is provided.
 */
public fun  T.asFlow(keyPaths: List? = null): Flow> = runIfManaged {
    checkNotificationsAvailable()
    val keyPathInfo = keyPaths?.let {
        Pair(this.metadata.classKey, keyPaths)
    }

    return owner.owner.registerObserver(this, keyPathInfo) as Flow>
} ?: throw IllegalStateException("Changes cannot be observed on unmanaged objects.")




© 2015 - 2024 Weber Informatics LLC | Privacy Policy