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

loggersoft.kotlin.utils.CachedProperty.kt Maven / Gradle / Ivy

/*
 * Copyright (C) 2018 Alexander Kornilov ([email protected])
 *
 * 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 loggersoft.kotlin.utils

import kotlin.reflect.KProperty

/**
 * Implementation of cached read-only property which based on another object.
 *
 * @param instance a tracked object. If instance implements [StateTrackable] interface
 *                 the [StateTrackable.revision] will be used; [Any.hashCode] otherwise.
 * @param hint a some [CacheHint] for cache strategy.
 * @param maker a maker of a value which holds in a property.
 *
 * @author Alexander Kornilov ([email protected]).
 */
class CachedProperty(private val instance: E,
                                             private val hint: CacheHint = CacheHint.None,
                                             private val maker: E.() -> T) {

    /**
     * A cache hint variants.
     */
    enum class CacheHint {

        /**
         * A value will be initialized at first access and be updated only when
         * revision of instance be changed.
         */
        None,

        /**
         * A value will be initialized at first access (like as [lazy]).
         */
        Immutable,

        /**
         * A value will be updated at each access (not recommended).
         */
        Dynamic
    }

    /**
     * Returns the cached value of the property.
     */
    operator fun getValue(obj: Any, prop: KProperty<*>): T =
        when(hint) {
            CacheHint.None -> {
                val value = currentValue
                val instanceRevision = if (instance is StateTrackable<*>) instance.revision else instance.hashCode()
                if (value != null && currentRevision == instanceRevision) value else {
                    val newValue = instance.maker()
                    currentValue = newValue
                    currentRevision = instanceRevision
                    newValue
                }
            }
            CacheHint.Immutable -> {
                val value = currentValue
                if (value != null) value else {
                    val newValue = instance.maker()
                    currentValue = newValue
                    newValue
                }
            }
            CacheHint.Dynamic -> instance.maker()
        }

    private var currentValue: T? = null
    private var currentRevision = 0
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy