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

internal.data.CompositeValueImpl.kt Maven / Gradle / Ivy

There is a newer version: 2.16.0
Show newest version
/*
 * Copyright 2019-2021 Mamoe Technologies and contributors.
 *
 *  此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
 *  Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
 *
 *  https://github.com/mamoe/mirai/blob/master/LICENSE
 */

@file:Suppress("unused")

package net.mamoe.mirai.console.internal.data

import net.mamoe.mirai.console.data.*


// type inference bug
internal fun  PluginData.createCompositeSetValueImpl(tToValue: (T) -> Value): CompositeSetValueImpl {
    return object : CompositeSetValueImpl(tToValue) {
        override fun onChanged() {
            [email protected](this)
        }
    }
}

internal abstract class CompositeSetValueImpl(
    tToValue: (T) -> Value // should override onChanged
) : CompositeSetValue, AbstractValueImpl>() {
    private val internalSet: MutableSet> = mutableSetOf()

    private var _value: Set = internalSet.shadowMap({ it.value }, tToValue).observable { onChanged() }

    override var value: Set
        get() = _value
        set(v) {
            if (_value != v) {
                @Suppress("LocalVariableName")
                val _value = _value as MutableSet
                _value.clear()
                _value.addAll(v)
                onChanged()
            }
        }

    override fun setValueBySerializer(value: Set) {
        val thisValue = this.value
        if (!thisValue.tryPatch(value)) {
            this.value = value // deep set
        }
    }

    protected abstract fun onChanged()
    override fun toString(): String = _value.toString()
    override fun equals(other: Any?): Boolean =
        other is CompositeSetValueImpl<*> && other::class.java == this::class.java && other._value == this._value

    override fun hashCode(): Int {
        val value = _value
        return value.hashCode() * 31 + super.hashCode()
    }
}


// type inference bug
internal fun  PluginData.createCompositeListValueImpl(tToValue: (T) -> Value): CompositeListValueImpl {
    return object : CompositeListValueImpl(tToValue) {
        override fun onChanged() {
            [email protected](this)
        }
    }
}

internal abstract class CompositeListValueImpl(
    tToValue: (T) -> Value // should override onChanged
) : CompositeListValue, AbstractValueImpl>() {
    private val internalList: MutableList> = mutableListOf()

    private val _value: List = internalList.shadowMap({ it.value }, tToValue).observable { onChanged() }

    override var value: List
        get() = _value
        set(v) {
            if (_value != v) {
                @Suppress("LocalVariableName")
                val _value = _value as MutableList
                _value.clear()
                _value.addAll(v)
                onChanged()
            }
        }

    override fun setValueBySerializer(value: List) {
        val thisValue = this.value
        if (!thisValue.tryPatch(value)) {
            this.value = value // deep set
        }
    }

    protected abstract fun onChanged()
    override fun toString(): String = _value.toString()
    override fun equals(other: Any?): Boolean =
        other is CompositeListValueImpl<*> && other::class.java == this::class.java && other._value == this._value

    override fun hashCode(): Int {
        val value = _value
        return value.hashCode() * 31 + super.hashCode()
    }
}

// workaround to a type inference bug
internal fun  PluginData.createCompositeMapValueImpl(
    mapInitializer: (() -> MutableMap, Value>?)? = null,
    kToValue: (K) -> Value,
    vToValue: (V) -> Value,
    valueToK: (Value) -> K = Value::value,
    valueToV: (Value) -> V = Value::value,
    applyToShadowedMap: ((MutableMap) -> (MutableMap))? = null
): CompositeMapValueImpl {
    return object : CompositeMapValueImpl(mapInitializer, kToValue, vToValue, valueToK, valueToV, applyToShadowedMap) {
        override fun onChanged() = [email protected](this)
    }
}

// TODO: 2020/6/24 在一个 Value 被删除后停止追踪其更新.

internal abstract class CompositeMapValueImpl(
    mapInitializer: (() -> MutableMap, Value>?)? = null,
    @JvmField internal val kToValue: (K) -> Value, // should override onChanged
    @JvmField internal val vToValue: (V) -> Value, // should override onChanged
    @JvmField internal val valueToK: (Value) -> K = Value::value,
    @JvmField internal val valueToV: (Value) -> V = Value::value,
    applyToShadowedMap: ((MutableMap) -> (MutableMap))? = null
) : CompositeMapValue, AbstractValueImpl>() {
    @JvmField
    internal val internalList: MutableMap, Value> = mapInitializer?.invoke() ?: mutableMapOf()

    private var _value: MutableMap =
        internalList.shadowMap(valueToK, kToValue, valueToV, vToValue).let {
            applyToShadowedMap?.invoke(it) ?: it
        }.observable { onChanged() }

    override var value: Map
        get() = _value
        set(v) {
            if (_value != v) {
                @Suppress("LocalVariableName")
                val _value = _value
                _value.clear()
                _value.putAll(v)
                onChanged()
            }
        }

    override fun setValueBySerializer(value: Map) {
        val thisValue = this.value as MutableMap
        if (!thisValue.tryPatch(value)) {
            this.value = value // deep set
        }
    }

    protected abstract fun onChanged()
    override fun toString(): String = _value.toString()
    override fun equals(other: Any?): Boolean =
        other is CompositeMapValueImpl<*, *> && other::class.java == this::class.java && other._value == this._value

    override fun hashCode(): Int {
        val value = _value
        return value.hashCode() * 31 + super.hashCode()
    }
}

internal fun  MutableMap.patchImpl(_new: Map) {
    val new = _new.toMutableMap()
    val iterator = this.iterator()
    for (entry in iterator) {
        val newValue = new.remove(entry.key)

        if (newValue != null) {
            // has replacer
            if (entry.value?.tryPatch(newValue) != true) {
                // patch not supported, or old value is null
                entry.setValue(newValue)
            } // else: patched, no remove
        } else {
            // no replacer
            iterator.remove()
        }
    }
    putAll(new)
}

internal fun , E> C.patchImpl(_new: Collection) {
    this.clear()
    this.addAll(_new)
}

/**
 * True if successfully patched
 */
@Suppress("UNCHECKED_CAST")
internal fun Any.tryPatch(any: Any): Boolean = when {
    this is MutableCollection<*> && any is Collection<*> -> {
        (this as MutableCollection).patchImpl(any as Collection)
        true
    }
    this is MutableMap<*, *> && any is Map<*, *> -> {
        (this as MutableMap).patchImpl(any as Map)
        true
    }
    this is Value<*> && any is Value<*> -> any.value?.let { otherValue -> this.value?.tryPatch(otherValue) } == true
    else -> false
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy