From b0cd84037696c509cdad3d22d93423dcdd9e5660 Mon Sep 17 00:00:00 2001 From: tursom <tursom@foxmail.com> Date: Mon, 12 Apr 2021 11:03:33 +0800 Subject: [PATCH] update --- build.gradle.kts | 3 - .../kotlin/cn/tursom/core/SimpThreadLocal.kt | 26 ++- .../core/ThreadLocalSimpleDateFormat.kt | 4 +- .../src/main/kotlin/cn/tursom/core/Tools.kt | 48 +++-- .../AutoUpdatableMutableDelegatedField.kt | 29 +++ .../delegation/DecoratorDelegateProvider.kt | 9 +- .../DecoratorMutableDelegateProvider.kt | 10 +- .../DecoratorMutableDelegatedField.kt | 3 +- .../core/delegation/DelegateProvider.kt | 2 +- .../delegation/DelegatedFieldAttachmentKey.kt | 7 +- .../ExecutorMutableDelegatedField.kt | 20 +- .../ExpirableMutableDelegatedField.kt | 46 ++++ .../core/delegation/FilterDelegatedField.kt | 12 +- .../core/delegation/GetterDelegatedField.kt | 6 +- .../delegation/GetterMutableDelegatedField.kt | 6 +- .../KPropertyMutableDelegatedField.kt | 6 +- .../cn/tursom/core/delegation/Listenable.kt | 10 + .../core/delegation/ListenableListener.kt | 6 + .../ListenableMutableDelegatedField.kt | 61 ++++++ .../cn/tursom/core/delegation/Listener.kt | 7 + .../delegation/LockMutableDelegatedField.kt | 10 +- .../delegation/MutableDelegatedFieldValue.kt | 2 +- .../core/delegation/NotNullDelegatedField.kt | 24 ++- .../NotNullMutableDelegatedField.kt | 26 ++- .../ReadWriteLockMutableDelegatedField.kt | 14 +- .../delegation/ReflectionDelegatedField.kt | 49 +++++ .../delegation/SetterMutableDelegatedField.kt | 6 +- .../SimpThreadLocalMutableDelegatedField.kt | 29 ++- .../ThreadLocalMutableDelegatedField.kt | 23 +- .../delegation/UnmonitoredFieldException.kt | 9 + .../cn/tursom/core/delegation/delegations.kt | 197 +++++++++++++++--- 31 files changed, 585 insertions(+), 125 deletions(-) create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/AutoUpdatableMutableDelegatedField.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExpirableMutableDelegatedField.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listenable.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableListener.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableMutableDelegatedField.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listener.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReflectionDelegatedField.kt create mode 100644 ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/UnmonitoredFieldException.kt diff --git a/build.gradle.kts b/build.gradle.kts index b49c786..9ac12af 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -53,9 +53,6 @@ dependencies { api(kotlin("stdlib-jdk8")) api(kotlin("reflect")) testImplementation(group = "junit", name = "junit", version = "4.12") - - val commonVersion = "1.0.RELEASE" - api("com.ddbes", "common-kotlin", commonVersion) } tasks.register("install") { diff --git a/ts-core/src/main/kotlin/cn/tursom/core/SimpThreadLocal.kt b/ts-core/src/main/kotlin/cn/tursom/core/SimpThreadLocal.kt index 120bad7..65b4469 100644 --- a/ts-core/src/main/kotlin/cn/tursom/core/SimpThreadLocal.kt +++ b/ts-core/src/main/kotlin/cn/tursom/core/SimpThreadLocal.kt @@ -1,12 +1,26 @@ package cn.tursom.core -open class SimpThreadLocal<T>(private val new: () -> T) : ThreadLocal<T>() { - override fun get(): T = super.get() ?: update() +open class SimpThreadLocal<T : Any>( + private val threadLocal: ThreadLocal<T?>? = null, + val new: () -> T, +) : ThreadLocal<T>() { + override fun get(): T { + var value = if (threadLocal != null) threadLocal.get() else super.get() + return if (value == null) { + value = new() + set(value) + value + } else { + value + } + } - private fun update(): T { - val value = new() - set(value) - return value + override fun set(value: T) { + if (threadLocal != null) threadLocal.set(value) else super.set(value) + } + + override fun remove() { + if (threadLocal != null) threadLocal.remove() else super.remove() } } diff --git a/ts-core/src/main/kotlin/cn/tursom/core/ThreadLocalSimpleDateFormat.kt b/ts-core/src/main/kotlin/cn/tursom/core/ThreadLocalSimpleDateFormat.kt index 29c267a..38c5364 100644 --- a/ts-core/src/main/kotlin/cn/tursom/core/ThreadLocalSimpleDateFormat.kt +++ b/ts-core/src/main/kotlin/cn/tursom/core/ThreadLocalSimpleDateFormat.kt @@ -4,8 +4,8 @@ import java.text.SimpleDateFormat import java.util.* class ThreadLocalSimpleDateFormat( - val format: String = "YYYY-MM-dd'T'HH:mm:ssZZ" -) : SimpThreadLocal<SimpleDateFormat>({ + val format: String = "YYYY-MM-dd'T'HH:mm:ssZZ", +) : SimpThreadLocal<SimpleDateFormat>(null, { SimpleDateFormat(format) }) { fun format(date: Any) = get().format(date) diff --git a/ts-core/src/main/kotlin/cn/tursom/core/Tools.kt b/ts-core/src/main/kotlin/cn/tursom/core/Tools.kt index b24adc7..bdfd008 100644 --- a/ts-core/src/main/kotlin/cn/tursom/core/Tools.kt +++ b/ts-core/src/main/kotlin/cn/tursom/core/Tools.kt @@ -112,9 +112,18 @@ inline fun <T, R : Any> Iterable<T>.toSetNotNull(transform: (T) -> R?): Set<R> { } +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +//@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +annotation class UncheckedCast + +@UncheckedCast @Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") inline fun <T> Any?.cast() = this as T +@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") +inline fun <T> Any?.uncheckedCast() = this as T + @Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") inline fun <reified T> Any?.castOrNull() = if (this is T) this else null @@ -280,12 +289,7 @@ inline fun usingNanoTime(action: () -> Unit): Long { } inline fun Class<*>.forAllFields(action: (Field) -> Unit) { - var clazz = this - while (clazz != Any::class.java) { - clazz.declaredFields.forEach(action) - clazz = clazz.superclass - } - clazz.declaredFields.forEach(action) + allFieldsSequence.forEach(action) } val Class<*>.allFields: List<Field> @@ -295,6 +299,17 @@ val Class<*>.allFields: List<Field> return fieldList } +val Class<*>.allFieldsSequence: Sequence<Field> + get() = sequence { + var clazz = this@allFieldsSequence + while (clazz != Any::class.java) { + clazz.declaredFields.forEach { field -> + yield(field) + } + clazz = clazz.superclass + } + } + fun Class<*>.getFieldForAll(name: String): Field? { forAllFields { if (it.name == name) return it @@ -303,12 +318,7 @@ fun Class<*>.getFieldForAll(name: String): Field? { } inline fun Class<*>.forAllMethods(action: (Method) -> Unit) { - var clazz = this - while (clazz != Any::class.java) { - clazz.declaredMethods.forEach(action) - clazz = clazz.superclass - } - clazz.declaredMethods.forEach(action) + allMethodsSequence.forEach(action) } fun Class<*>.getMethodForAll(name: String, vararg parameterTypes: Class<*>?): Method? { @@ -325,6 +335,20 @@ val Class<*>.allMethods: List<Method> return fieldList } +val Class<*>.allMethodsSequence: Sequence<Method> + get() = sequence { + var clazz = this@allMethodsSequence + while (clazz != Any::class.java) { + clazz.declaredMethods.forEach { + yield(it) + } + clazz = clazz.superclass + } + clazz.declaredMethods.forEach { + yield(it) + } + } + /** * 获取一个 KProperty<*> 对应的对象 */ diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/AutoUpdatableMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/AutoUpdatableMutableDelegatedField.kt new file mode 100644 index 0000000..b5ab2a5 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/AutoUpdatableMutableDelegatedField.kt @@ -0,0 +1,29 @@ +package cn.tursom.core.delegation + +import cn.tursom.core.uncheckedCast +import kotlin.reflect.KProperty + +/** + * 当从上一级 MutableDelegatedField 获得到空值时 + * 自动调用updateValue方法更新值 + */ +class AutoUpdatableMutableDelegatedField<in T, V : Any>( + override val delegatedField: MutableDelegatedField<T, V?>, + val updateValue: T.(property: KProperty<*>) -> V, +) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(), + DecoratorMutableDelegatedField<T, V?> { + override fun getValue(thisRef: T, property: KProperty<*>): V { + var value = delegatedField.getValue(thisRef, property) + if (value == null) { + value = thisRef.updateValue(property) + delegatedField.setValue(thisRef, property, value) + } + return value + } +} + +fun <T, V : Any> MutableDelegatedField<T, V?>.autoUpdate( + updateValue: T.(property: KProperty<*>) -> V, +): MutableDelegatedField<T, V> { + return AutoUpdatableMutableDelegatedField(this, updateValue) +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorDelegateProvider.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorDelegateProvider.kt index 9e8db36..24db0c7 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorDelegateProvider.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorDelegateProvider.kt @@ -3,7 +3,10 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty interface DecoratorDelegateProvider<in T, out V> : - DelegateProvider<T, DelegatedField<T, V>>, - DecoratorDelegatedField<T, V> { - override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): DelegatedField<T, V> = delegatedField + DelegateProvider<T, DelegatedField<T, V>>, + DecoratorDelegatedField<T, V> { + override operator fun provideDelegate( + thisRef: T, + prop: KProperty<*>, + ): DelegatedField<T, V> = delegatedField } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegateProvider.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegateProvider.kt index 2c6011d..781a290 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegateProvider.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegateProvider.kt @@ -3,9 +3,9 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty interface DecoratorMutableDelegateProvider<in T, V> : - DelegateProvider<T, MutableDelegatedField<T, V>>, - //DecoratorProvideDelegate<T, V>, - DecoratorMutableDelegatedField<T, V> { - override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> = - mutableDelegatedField + DelegateProvider<T, MutableDelegatedField<T, V>>, + //DecoratorProvideDelegate<T, V>, + DecoratorMutableDelegatedField<T, V> { + override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> = + delegatedField } diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegatedField.kt index 3b5ca37..11f550f 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DecoratorMutableDelegatedField.kt @@ -1,6 +1,5 @@ package cn.tursom.core.delegation interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> { - val mutableDelegatedField: MutableDelegatedField<T, V> - override val delegatedField: DelegatedField<T, V> get() = mutableDelegatedField + override val delegatedField: MutableDelegatedField<T, V> } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegateProvider.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegateProvider.kt index 945e0db..0dbae74 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegateProvider.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegateProvider.kt @@ -3,5 +3,5 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty interface DelegateProvider<in T, out R> { - operator fun provideDelegate(thisRef: T, prop: KProperty<*>): R + operator fun provideDelegate(thisRef: T, prop: KProperty<*>): R } diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegatedFieldAttachmentKey.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegatedFieldAttachmentKey.kt index f843077..4654c65 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegatedFieldAttachmentKey.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/DelegatedFieldAttachmentKey.kt @@ -1,3 +1,8 @@ package cn.tursom.core.delegation -interface DelegatedFieldAttachmentKey<V> \ No newline at end of file +import kotlin.reflect.KProperty0 + +interface DelegatedFieldAttachmentKey<V> { + operator fun get(delegatedField: DelegatedField<*, *>) = delegatedField[this] + operator fun get(property0: KProperty0<*>) = property0.getDelegatedAttachmentValue(this) +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExecutorMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExecutorMutableDelegatedField.kt index d16d16c..81e91cc 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExecutorMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExecutorMutableDelegatedField.kt @@ -4,17 +4,17 @@ import java.util.concurrent.Executor import kotlin.reflect.KProperty class ExecutorMutableDelegatedField<in T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, private val executor: Executor, -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { - override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) { - executor.execute { - mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue) +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { + override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) { + executor.execute { + delegatedField.valueOnSet(thisRef, property, value, oldValue) + } } - } - override fun setValue(thisRef: T, property: KProperty<*>, value: V) { - valueOnSet(thisRef, property, value, getValue()) - mutableDelegatedField.setValue(value) - } + override fun setValue(thisRef: T, property: KProperty<*>, value: V) { + valueOnSet(thisRef, property, value, getValue()) + delegatedField.setValue(value) + } } diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExpirableMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExpirableMutableDelegatedField.kt new file mode 100644 index 0000000..3c13ac3 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ExpirableMutableDelegatedField.kt @@ -0,0 +1,46 @@ +package cn.tursom.core.delegation + +import cn.tursom.core.uncheckedCast +import java.util.concurrent.TimeUnit +import kotlin.reflect.KProperty + +class ExpirableMutableDelegatedField<in T, V : Any>( + override val delegatedField: MutableDelegatedField<T, V>, + val expireMS: Long, +) : MutableDelegatedField<T, V?> by delegatedField.uncheckedCast(), + DecoratorMutableDelegatedField<T, V> { + + @Volatile + private var setTime: Long = 0L + + override fun getValue(thisRef: T, property: KProperty<*>): V? { + return if (System.currentTimeMillis() - setTime < expireMS) { + delegatedField.uncheckedCast<MutableDelegatedField<T, V?>>().getValue(thisRef, property) + } else { + null + } + } + + override fun setValue(thisRef: T, property: KProperty<*>, value: V?) { + if (value != null) { + delegatedField.setValue(value) + setTime = System.currentTimeMillis() + } + } +} + +fun <T, V : Any> MutableDelegatedField<T, V>.expirable( + expireTime: Long, + timeUnit: TimeUnit = TimeUnit.MILLISECONDS, +): MutableDelegatedField<T, V?> { + return ExpirableMutableDelegatedField(this, timeUnit.toMillis(expireTime)) +} + +@JvmName("expirableTV?") +fun <T, V : Any> MutableDelegatedField<T, V?>.expirable( + expireTime: Long, + timeUnit: TimeUnit = TimeUnit.MILLISECONDS, +): MutableDelegatedField<T, V?> { + return ExpirableMutableDelegatedField(uncheckedCast(), timeUnit.toMillis(expireTime)) +} + diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/FilterDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/FilterDelegatedField.kt index a6899b0..2ef9833 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/FilterDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/FilterDelegatedField.kt @@ -1,18 +1,18 @@ package cn.tursom.core.delegation -import cn.tursom.core.cast +import cn.tursom.core.uncheckedCast import kotlin.reflect.KProperty class FilterDelegatedField<in T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, private val filter: T.(old: V, new: V) -> Boolean, -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { companion object Key : DelegatedFieldAttachmentKey<Boolean> private var filterResult = false override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? { - return if (key == Key) filterResult.cast() else super.get(key) + return if (key == Key) filterResult.uncheckedCast() else super.get(key) } override fun setValue(thisRef: T, property: KProperty<*>, value: V) { @@ -20,7 +20,7 @@ class FilterDelegatedField<in T, V>( if (!filterResult) { return } - mutableDelegatedField.setValue(thisRef, property, value) + delegatedField.setValue(thisRef, property, value) } override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) { @@ -28,6 +28,6 @@ class FilterDelegatedField<in T, V>( if (!filterResult) { return } - mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue) + delegatedField.valueOnSet(thisRef, property, value, oldValue) } } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterDelegatedField.kt index 5d94c33..cd8a217 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterDelegatedField.kt @@ -3,8 +3,8 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty class GetterDelegatedField<in T, out V>( - override val delegatedField: DelegatedField<T, V>, - private val getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V, + override val delegatedField: DelegatedField<T, V>, + private val getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V, ) : DelegatedField<T, V> by delegatedField, DecoratorDelegatedField<T, V> { - override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property) + override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property) } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterMutableDelegatedField.kt index b0a4809..31f525c 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/GetterMutableDelegatedField.kt @@ -3,8 +3,8 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty class GetterMutableDelegatedField<in T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, private val getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V, -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { - override fun getValue(thisRef: T, property: KProperty<*>): V = mutableDelegatedField.getter(thisRef, property) +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { + override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property) } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/KPropertyMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/KPropertyMutableDelegatedField.kt index 0c364cd..70515bc 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/KPropertyMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/KPropertyMutableDelegatedField.kt @@ -3,8 +3,8 @@ package cn.tursom.core.delegation import kotlin.reflect.KMutableProperty0 class KPropertyMutableDelegatedField<in T, V>( - val delegation: KMutableProperty0<V>, + val delegation: KMutableProperty0<V>, ) : MutableDelegatedField<T, V> { - override fun getValue(): V = delegation.get() - override fun setValue(value: V) = delegation.set(value) + override fun getValue(): V = delegation.get() + override fun setValue(value: V) = delegation.set(value) } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listenable.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listenable.kt new file mode 100644 index 0000000..51fc5d0 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listenable.kt @@ -0,0 +1,10 @@ +package cn.tursom.core.delegation + +/** + * 标识一个属性可以被指定的 FieldChangeListener 监听 + * 属性的实现者应该实现相应的逻辑 + */ +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS) +annotation class Listenable \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableListener.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableListener.kt new file mode 100644 index 0000000..b9a27d0 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableListener.kt @@ -0,0 +1,6 @@ +package cn.tursom.core.delegation + +interface ListenableListener<out T, V> : Listener<T, V> { + infix fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V> + override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ListenableListener<T, V> +} diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableMutableDelegatedField.kt new file mode 100644 index 0000000..4b99ebd --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ListenableMutableDelegatedField.kt @@ -0,0 +1,61 @@ +package cn.tursom.core.delegation + +import cn.tursom.core.uncheckedCast +import java.util.concurrent.ConcurrentLinkedDeque +import kotlin.reflect.KProperty + +@Listenable +class ListenableMutableDelegatedField<T, V>( + override val delegatedField: MutableDelegatedField<T, V>, +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { + companion object : DelegatedFieldAttachmentKey<Boolean> + + override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? { + return if (key == Companion) true.uncheckedCast() else super.get(key) + } + + private val listenerList = ConcurrentLinkedDeque<T.(old: V, new: V) -> Unit>() + + override fun setValue(thisRef: T, property: KProperty<*>, value: V) { + val oldValue = getValue() + listenerList.forEach { + thisRef.it(oldValue, value) + } + delegatedField.setValue(thisRef, property, value) + } + + override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) { + listenerList.forEach { + thisRef.it(oldValue, value) + } + delegatedField.valueOnSet(thisRef, property, value, oldValue) + } + + fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V> { + var catch: (T.(old: V, new: V, e: Throwable) -> Unit)? = null + var finally: (T.(old: V, new: V) -> Unit)? = null + listenerList.add { old, new -> + try { + listener(old, new) + } catch (e: Throwable) { + catch?.invoke(this, old, new, e) + } finally { + finally?.invoke(this, old, new) + } + } + return object : Listener<T, V> { + override fun cancel() = listenerList.remove(listener) + + override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Listener<T, V> { + catch = handler + return this + } + + override fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V> { + finally = handler + return this + } + + } + } +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listener.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listener.kt new file mode 100644 index 0000000..f2636b3 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/Listener.kt @@ -0,0 +1,7 @@ +package cn.tursom.core.delegation + +interface Listener<out T, V> { + fun cancel(): Boolean + infix fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Listener<T, V> + infix fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V> +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/LockMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/LockMutableDelegatedField.kt index a1a20f0..7b97c3a 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/LockMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/LockMutableDelegatedField.kt @@ -6,23 +6,23 @@ import kotlin.concurrent.withLock import kotlin.reflect.KProperty class LockMutableDelegatedField<in T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, private val lock: Lock = ReentrantLock(), -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { constructor( initValue: V, lock: Lock = ReentrantLock(), ) : this(MutableDelegatedFieldValue(initValue), lock) override fun getValue(thisRef: T, property: KProperty<*>): V = lock.withLock { - mutableDelegatedField.getValue(thisRef, property) + delegatedField.getValue(thisRef, property) } override fun setValue(thisRef: T, property: KProperty<*>, value: V) = lock.withLock { - mutableDelegatedField.setValue(thisRef, property, value) + delegatedField.setValue(thisRef, property, value) } override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) = lock.withLock { - mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue) + delegatedField.valueOnSet(thisRef, property, value, oldValue) } } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/MutableDelegatedFieldValue.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/MutableDelegatedFieldValue.kt index 2af9a52..8e29d30 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/MutableDelegatedFieldValue.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/MutableDelegatedFieldValue.kt @@ -3,7 +3,7 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty open class MutableDelegatedFieldValue<in T, V>( - private var initValue: V + private var initValue: V, ) : MutableDelegatedField<T, V> { override fun getValue(): V = initValue override fun getValue(thisRef: T, property: KProperty<*>): V = initValue diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullDelegatedField.kt index f04f04f..ab767c8 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullDelegatedField.kt @@ -1,7 +1,27 @@ package cn.tursom.core.delegation -import cn.tursom.core.cast +import cn.tursom.core.uncheckedCast +import kotlin.reflect.KProperty class NotNullDelegatedField<in T, out V : Any>( override val delegatedField: DelegatedField<T, V?>, -) : DelegatedField<T, V> by delegatedField.cast(), DecoratorDelegatedField<T, V?> \ No newline at end of file + val ifNull: () -> Nothing = { throw NullPointerException() }, +) : DelegatedField<T, V> by delegatedField.uncheckedCast(), DecoratorDelegatedField<T, V?> { + override fun getValue(): V { + val value = delegatedField.getValue() + if (value == null) { + ifNull() + } else { + return value + } + } + + override fun getValue(thisRef: T, property: KProperty<*>): V { + val value = delegatedField.getValue(thisRef, property) + if (value == null) { + ifNull() + } else { + return value + } + } +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullMutableDelegatedField.kt index 446a773..1494e20 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/NotNullMutableDelegatedField.kt @@ -1,8 +1,28 @@ package cn.tursom.core.delegation -import cn.tursom.core.cast +import cn.tursom.core.uncheckedCast +import kotlin.reflect.KProperty class NotNullMutableDelegatedField<in T, V : Any>( - override val mutableDelegatedField: MutableDelegatedField<T, V?>, -) : MutableDelegatedField<T, V> by mutableDelegatedField.cast(), DecoratorMutableDelegatedField<T, V?> + override val delegatedField: MutableDelegatedField<T, V?>, + val ifNull: () -> Nothing = { throw NullPointerException() }, +) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(), DecoratorMutableDelegatedField<T, V?> { + override fun getValue(): V { + val value = delegatedField.getValue() + if (value == null) { + ifNull() + } else { + return value + } + } + + override fun getValue(thisRef: T, property: KProperty<*>): V { + val value = delegatedField.getValue(thisRef, property) + if (value == null) { + ifNull() + } else { + return value + } + } +} diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReadWriteLockMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReadWriteLockMutableDelegatedField.kt index 028f4d5..c70b6df 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReadWriteLockMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReadWriteLockMutableDelegatedField.kt @@ -7,9 +7,9 @@ import kotlin.concurrent.write import kotlin.reflect.KProperty class ReadWriteLockMutableDelegatedField<in T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, private val readWriteLock: ReadWriteLock = ReentrantReadWriteLock(), -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { constructor( initValue: V, readWriteLock: ReadWriteLock = ReentrantReadWriteLock(), @@ -19,7 +19,7 @@ class ReadWriteLockMutableDelegatedField<in T, V>( val rl = readWriteLock.readLock() rl.lock() try { - return mutableDelegatedField.getValue(thisRef, property) + return delegatedField.getValue(thisRef, property) } finally { rl.unlock() } @@ -27,17 +27,17 @@ class ReadWriteLockMutableDelegatedField<in T, V>( override fun setValue(thisRef: T, property: KProperty<*>, value: V) { if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write { - mutableDelegatedField.setValue(thisRef, property, value) + delegatedField.setValue(thisRef, property, value) } else readWriteLock.writeLock().withLock { - mutableDelegatedField.setValue(thisRef, property, value) + delegatedField.setValue(thisRef, property, value) } } override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) { if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write { - mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue) + delegatedField.valueOnSet(thisRef, property, value, oldValue) } else readWriteLock.writeLock().withLock { - mutableDelegatedField.setValue(thisRef, property, value) + delegatedField.setValue(thisRef, property, value) } } } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReflectionDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReflectionDelegatedField.kt new file mode 100644 index 0000000..6c549d5 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ReflectionDelegatedField.kt @@ -0,0 +1,49 @@ +package cn.tursom.core.delegation + +import cn.tursom.core.getFieldForAll +import cn.tursom.core.uncheckedCast +import java.lang.reflect.Field + +class ReflectionDelegatedField<in T, V>( + private val receiver: T, + private val field: Field, +) : MutableDelegatedField<T, V> { + init { + field.isAccessible = true + } + + override fun getValue(): V = field.get(receiver).uncheckedCast() + + override fun setValue(value: V) { + field.set(receiver, value) + } + + companion object { + fun <T : Any, V> T.superField( + fieldName: String, + ): MutableDelegatedField<T, V> { + return ReflectionDelegatedField(this, this.javaClass.getFieldForAll(fieldName)!!) + } + + fun <T, V> T.field( + field: Field, + ): MutableDelegatedField<T, V> { + return ReflectionDelegatedField(this, field) + } + + fun <T, V> T.field( + field: Field, + type: V, + ): MutableDelegatedField<T, V> { + return ReflectionDelegatedField(this, field) + } + + inline fun <T, V> T.field( + field: Field, + type: () -> V, + ): MutableDelegatedField<T, V> { + return ReflectionDelegatedField(this, field) + } + } +} + diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SetterMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SetterMutableDelegatedField.kt index d80bbab..a1814d1 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SetterMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SetterMutableDelegatedField.kt @@ -3,10 +3,10 @@ package cn.tursom.core.delegation import kotlin.reflect.KProperty class SetterMutableDelegatedField<T, V>( - override val mutableDelegatedField: MutableDelegatedField<T, V>, + override val delegatedField: MutableDelegatedField<T, V>, val setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit, -) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> { +) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> { override fun setValue(thisRef: T, property: KProperty<*>, value: V) { - mutableDelegatedField.setter(thisRef, property, value) + delegatedField.setter(thisRef, property, value) } } diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SimpThreadLocalMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SimpThreadLocalMutableDelegatedField.kt index 5dfdeae..6fab2db 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SimpThreadLocalMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/SimpThreadLocalMutableDelegatedField.kt @@ -1,14 +1,29 @@ package cn.tursom.core.delegation import cn.tursom.core.SimpThreadLocal +import cn.tursom.core.uncheckedCast +import kotlin.reflect.KProperty0 - -class SimpThreadLocalMutableDelegatedField<in T, V>( - private val threadLocal: SimpThreadLocal<V>, - val new: () -> V +class SimpThreadLocalMutableDelegatedField<in T, V : Any>( + private val threadLocal: SimpThreadLocal<V>, ) : MutableDelegatedField<T, V> { - constructor(new: () -> V) : this(SimpThreadLocal(new = new), new) + constructor(new: () -> V) : this(SimpThreadLocal(new = new)) - override fun setValue(value: V) = threadLocal.set(value) - override fun getValue(): V = threadLocal.get() + + override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? { + return if (key == Companion || key == ThreadLocalMutableDelegatedField) { + threadLocal.uncheckedCast() + } else { + super.get(key) + } + } + + override fun setValue(value: V) = threadLocal.set(value) + override fun getValue(): V = threadLocal.get() + + companion object : DelegatedFieldAttachmentKey<SimpThreadLocal<*>> { + fun <T : Any> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>() + fun <T : Any> getKey(property: KProperty0<T>) = + this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>() + } } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ThreadLocalMutableDelegatedField.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ThreadLocalMutableDelegatedField.kt index 8284aba..a036972 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ThreadLocalMutableDelegatedField.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/ThreadLocalMutableDelegatedField.kt @@ -1,8 +1,25 @@ package cn.tursom.core.delegation +import cn.tursom.core.uncheckedCast +import kotlin.reflect.KProperty0 + class ThreadLocalMutableDelegatedField<in T, V>( - private val threadLocal: ThreadLocal<V?> = ThreadLocal() + private val threadLocal: ThreadLocal<V?> = ThreadLocal(), ) : MutableDelegatedField<T, V?> { - override fun setValue(value: V?) = threadLocal.set(value) - override fun getValue(): V? = threadLocal.get() + + override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? { + return if (key == Companion) { + threadLocal.uncheckedCast() + } else { + super.get(key) + } + } + + override fun setValue(value: V?) = threadLocal.set(value) + override fun getValue(): V? = threadLocal.get() + + companion object : DelegatedFieldAttachmentKey<ThreadLocal<*>> { + fun <T> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<ThreadLocal<T>>>() + fun <T> getKey(property: KProperty0<T>) = this.uncheckedCast<DelegatedFieldAttachmentKey<ThreadLocal<T>>>() + } } \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/UnmonitoredFieldException.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/UnmonitoredFieldException.kt new file mode 100644 index 0000000..0eec731 --- /dev/null +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/UnmonitoredFieldException.kt @@ -0,0 +1,9 @@ +package cn.tursom.core.delegation + +class UnmonitoredFieldException : Exception { + constructor() : super() + constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(message, cause, enableSuppression, writableStackTrace) +} \ No newline at end of file diff --git a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/delegations.kt b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/delegations.kt index c0099e7..43a959a 100644 --- a/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/delegations.kt +++ b/ts-core/ts-delegation/src/main/kotlin/cn/tursom/core/delegation/delegations.kt @@ -2,10 +2,8 @@ package cn.tursom.core.delegation -import cn.tursom.core.SimpThreadLocal -import cn.tursom.core.cast -import cn.tursom.core.castOrNull -import cn.tursom.core.receiver +import cn.tursom.core.* +import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.Executor import java.util.concurrent.locks.Lock import java.util.concurrent.locks.ReadWriteLock @@ -19,26 +17,37 @@ import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible fun getDelegate(obj: Any?, field: String): DelegatedField<*, *>? { - obj ?: return null - val kProperty1 = obj.javaClass.kotlin.memberProperties.firstOrNull { it.name == field } - kProperty1?.isAccessible = true - val delegate = kProperty1?.getDelegate(obj) - return delegate.castOrNull() + obj ?: return null + val kProperty1 = obj.javaClass.kotlin.memberProperties.firstOrNull { it.name == field } + kProperty1?.isAccessible = true + val delegate = kProperty1?.getDelegate(obj) + return delegate.castOrNull() } val <V> KProperty0<V>.getOwnerDelegated: DelegatedField<*, V>? - get() = getDelegate(receiver, name).castOrNull() + get() = getDelegate(receiver, name).castOrNull() +/** + * 获取委托过后的值 + * 不会触发getter方法 + */ val <V> KProperty0<V>.getDelegatedValue: V? - get() { - val delegate = getDelegate() ?: getOwnerDelegated - return delegate?.castOrNull<DelegatedField<*, V>>()?.getValue() - } + get() { + val delegate = getDelegate() ?: getOwnerDelegated + return delegate?.castOrNull<DelegatedField<*, V>>()?.getValue() + } + +fun <V> KProperty0<*>.getDelegatedAttachmentValue(key: DelegatedFieldAttachmentKey<V>): V? { + val delegated = getOwnerDelegated ?: return null + return delegated[key] +} + +operator fun <V> KProperty0<*>.get(key: DelegatedFieldAttachmentKey<V>): V? = getDelegatedAttachmentValue(key) fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean { - val delegate = getDelegate() ?: getOwnerDelegated - delegate.castOrNull<MutableDelegatedField<*, V>>()?.setValue(value) ?: return false - return true + val delegate = getDelegate() ?: getOwnerDelegated + delegate.castOrNull<MutableDelegatedField<*, V>>()?.setValue(value) ?: return false + return true } /** @@ -46,50 +55,170 @@ fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean { */ fun <T, V> T.delegated(value: V): MutableDelegatedField<T, V> = MutableDelegatedFieldValue(value) fun <T, V> T.delegated(@Suppress("UNUSED_PARAMETER") target: T, value: V): MutableDelegatedField<T, V> = - MutableDelegatedFieldValue(value) + MutableDelegatedFieldValue(value) val <V> KProperty0<V>.delegated: DelegatedField<Any, V> get() = KPropertyDelegatedField(this) val <V> KMutableProperty0<V>.delegated: MutableDelegatedField<Any, V> get() = KPropertyMutableDelegatedField(this) val <V : Any> KProperty0<V?>.delegatedNotNull get() = delegated.notNull val <V : Any> KMutableProperty0<out V?>.delegatedNotNull: MutableDelegatedField<Any, V> get() = delegated.notNull +fun <V : Any> KProperty0<V?>.delegatedNotNull(ifNull: () -> Nothing) = delegated.notNull(ifNull) +fun <V : Any> KMutableProperty0<out V?>.delegatedNotNull(ifNull: () -> Nothing): MutableDelegatedField<Any, V> = + delegated.notNull(ifNull) val <T, V : Any> DelegatedField<T, V?>.notNull: DelegatedField<T, V> get() = NotNullDelegatedField(this) val <T, V : Any> MutableDelegatedField<T, out V?>.notNull: MutableDelegatedField<T, V> - get() = NotNullMutableDelegatedField(cast()) + get() = NotNullMutableDelegatedField(uncheckedCast()) + +fun <T, V : Any> DelegatedField<T, V?>.notNull(ifNull: () -> Nothing): DelegatedField<T, V> = + NotNullDelegatedField(this, ifNull) + +fun <T, V : Any> MutableDelegatedField<T, out V?>.notNull(ifNull: () -> Nothing): MutableDelegatedField<T, V> = + NotNullMutableDelegatedField(uncheckedCast(), ifNull) val <T, V> MutableDelegatedField<T, V>.locked: MutableDelegatedField<T, V> get() = LockMutableDelegatedField(this) fun <T, V> MutableDelegatedField<T, V>.locked(lock: Lock = ReentrantLock()): MutableDelegatedField<T, V> = - LockMutableDelegatedField(this, lock) + LockMutableDelegatedField(this, lock) val <T, V> MutableDelegatedField<T, V>.readWriteLocked: MutableDelegatedField<T, V> - get() = ReadWriteLockMutableDelegatedField(this) + get() = ReadWriteLockMutableDelegatedField(this) fun <T, V> MutableDelegatedField<T, V>.readWriteLocked(readWriteLock: ReadWriteLock = ReentrantReadWriteLock()): MutableDelegatedField<T, V> = - ReadWriteLockMutableDelegatedField(this, readWriteLock) + ReadWriteLockMutableDelegatedField(this, readWriteLock) + + +fun <T, V> ThreadLocal<V?>.delegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField(this) +fun <T, V> T.delegated( + threadLocal: ThreadLocal<V?>, +): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField(threadLocal) fun <T, V> T.threadLocalDelegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField() -fun <T, V> T.threadLocalDelegated(type: Class<V>): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField() -fun <T, V : Any> T.threadLocalDelegated(type: KClass<V>): MutableDelegatedField<T, V?> = - ThreadLocalMutableDelegatedField() +fun <T, V> T.threadLocalDelegated(type: V?): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField() +fun <T, V> T.threadLocalDelegated(type: Class<out V?>): MutableDelegatedField<T, V?> = + ThreadLocalMutableDelegatedField() -fun <T, V> T.threadLocalDelegated(new: () -> V): MutableDelegatedField<T, V> = SimpThreadLocalMutableDelegatedField(new) -fun <T, V> T.threadLocalDelegated(simpThreadLocal: SimpThreadLocal<V>, new: () -> V): MutableDelegatedField<T, V> = - SimpThreadLocalMutableDelegatedField(simpThreadLocal, new) +fun <T, V : Any> T.threadLocalDelegated(type: KClass<V>): MutableDelegatedField<T, V?> = + ThreadLocalMutableDelegatedField() + +fun <T, V : Any> SimpThreadLocal<V>.delegated(): MutableDelegatedField<T, V> = + SimpThreadLocalMutableDelegatedField(this) + +fun <T, V : Any> T.threadLocalDelegated( + threadLocal: ThreadLocal<V?> = ThreadLocal(), + new: () -> V, +): MutableDelegatedField<T, V> = SimpThreadLocalMutableDelegatedField(SimpThreadLocal(threadLocal, new)) +//fun <T, V> T.threadLocalDelegated(simpThreadLocal: SimpThreadLocal<V>): MutableDelegatedField<T, V> = +// SimpThreadLocalMutableDelegatedField(simpThreadLocal) fun <T, V> MutableDelegatedField<T, V>.filter(filter: T.(old: V, new: V) -> Boolean): MutableDelegatedField<T, V> = - FilterDelegatedField(this, filter) + FilterDelegatedField(this, filter) fun <T, V> DelegatedField<T, V>.setter(setter: DelegatedField<T, V>.(value: V) -> Unit): DelegatedField<T, V> = - SetterDelegatedField(this, setter) + SetterDelegatedField(this, setter) fun <T, V> MutableDelegatedField<T, V>.setter(setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit): MutableDelegatedField<T, V> = - SetterMutableDelegatedField(this, setter) + SetterMutableDelegatedField(this, setter) fun <T, V> DelegatedField<T, V>.getter(getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): DelegatedField<T, V> = - GetterDelegatedField(this, getter) + GetterDelegatedField(this, getter) fun <T, V> MutableDelegatedField<T, V>.getter(getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): MutableDelegatedField<T, V> = - GetterMutableDelegatedField(this, getter) + GetterMutableDelegatedField(this, getter) fun <T, V> MutableDelegatedField<T, V>.withExecutor(executor: Executor): MutableDelegatedField<T, V> = - ExecutorMutableDelegatedField(this, executor) + ExecutorMutableDelegatedField(this, executor) + +@Listenable +fun <V> KMutableProperty0<V>.listenable(): MutableDelegatedField<Any, V> { + isAccessible = true + val delegate = getDelegate() + return if (delegate is MutableDelegatedField<*, *> && delegate[ListenableMutableDelegatedField] == true) { + @OptIn(UncheckedCast::class) + delegate.cast() + } else { + @OptIn(UncheckedCast::class) + (ListenableMutableDelegatedField(KPropertyMutableDelegatedField(cast()))) + } +} + +@Listenable +fun <V> listenable(initValue: V): MutableDelegatedField<Any, V> = ListenableMutableDelegatedField( + MutableDelegatedFieldValue(initValue) +) + +@Listenable +fun <T, V> MutableDelegatedField<T, V>.listenable(): MutableDelegatedField<T, V> = + ListenableMutableDelegatedField(this) + +@JvmName("listenable1") +@Listenable +fun <T, V> listenable(delegatedField: MutableDelegatedField<T, V>): MutableDelegatedField<T, V> = + ListenableMutableDelegatedField(delegatedField) + + +infix operator fun <T, V> ListenableListener<T, V>.plus(listener: T.(old: V, new: V) -> Unit): Listener<T, V> = + addListener(listener) + +@OptIn(Listenable::class) +fun <V> KProperty0<V>.getListenableMutableDelegatedField(): ListenableMutableDelegatedField<Any, V>? { + isAccessible = true + var delegate = getDelegate() ?: getDelegate(receiver, name) + if (delegate is DelegatedField<*, *>) { + while (true) { + if (delegate is ListenableMutableDelegatedField<*, *>) { + @OptIn(UncheckedCast::class) + return delegate.cast() + } + if (delegate is DecoratorDelegatedField<*, *>) { + delegate = delegate.delegatedField + } else { + break + } + } + } else if (delegate is KProperty0<*> && delegate != this) { + @OptIn(UncheckedCast::class) + return delegate.cast<KProperty0<V>>().getListenableMutableDelegatedField() + } + return null +} + +inline fun <T, V> T.addChangeListener( + property: T.() -> KProperty0<V>, +): ListenableListener<T, V> { + val kProperty0 = property() + + @OptIn(Listenable::class, UncheckedCast::class) + val delegatedField = kProperty0 + .getListenableMutableDelegatedField() + .cast<ListenableMutableDelegatedField<T, V>?>() + ?: throw UnmonitoredFieldException(kProperty0.toString()) + return object : ListenableListener<T, V> { + private val selfList = ConcurrentLinkedQueue<Listener<T, V>>() + override fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V> { + @OptIn(Listenable::class) + val listener1 = delegatedField.addListener(listener) + selfList.add(listener1) + return listener1 + } + + override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ListenableListener<T, V> { + selfList.forEach { + it.catch(handler) + } + return this + } + + override fun cancel(): Boolean { + selfList.forEach { + it.cancel() + } + return true + } + + override fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V> { + selfList.forEach { + it.finally(handler) + } + return this + } + } +}