All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
internal.data.CompositeValueImpl.kt Maven / Gradle / Ivy
/*
* 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
}