Delegate properties stdlib, take 2.

This commit is contained in:
Maxim Shafirov
2013-05-30 17:54:27 +04:00
parent a954508284
commit 58914cdf33
7 changed files with 236 additions and 256 deletions
@@ -0,0 +1,175 @@
package kotlin.properties
public trait ReadOnlyProperty<in R, out T> {
public fun get(thisRef: R, desc: PropertyMetadata): T
}
public trait ReadWriteProperty<in R, T> {
public fun get(thisRef: R, desc: PropertyMetadata): T
public fun set(thisRef: R, desc: PropertyMetadata, value: T)
}
public object Delegates {
public fun notNull<T: Any>(): ReadWriteProperty<Any?, T> = NotNullVar()
public fun lazy<T>(initializer: () -> T): ReadOnlyProperty<Any?, T> = LazyVal(initializer)
public fun blockingLazy<T>(lock: Any? = null, initializer: () -> T): ReadOnlyProperty<Any?, T> = BlockingLazyVal(lock, initializer)
public fun observable<T>(initial: T, onChange: (desc: PropertyMetadata, oldValue: T, newValue: T) -> Unit): ReadWriteProperty<Any?, T> {
return ObservableProperty<T>(initial) { (desc, old, new) ->
onChange(desc, old, new)
true
}
}
public fun vetoable<T>(initial: T, onChange: (desc: PropertyMetadata, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty<Any?, T> {
return ObservableProperty<T>(initial, onChange)
}
public fun mapVar<T>(map: MutableMap<in String, Any?>,
default: (thisRef: Any?, desc: String) -> T = defaultValueProvider): ReadWriteProperty<Any?, T> {
return FixedMapVar<Any?, String, T>(map, defaultKeyProvider, default)
}
public fun mapVal<T>(map: Map<in String, Any?>,
default: (thisRef: Any?, desc: String) -> T = defaultValueProvider): ReadOnlyProperty<Any?, T> {
return FixedMapVal<Any?, String, T>(map, defaultKeyProvider, default)
}
}
private class NotNullVar<T: Any>() : ReadWriteProperty<Any?, T> {
private var value: T? = null
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value ?: throw IllegalStateException("Property ${desc.name} should be initialized before get")
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
}
}
class ObservableProperty<T>(initialValue: T, val onChange: (name: jet.PropertyMetadata, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty<Any?, T> {
private var value = initialValue
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
if (onChange(desc, this.value, value)) {
this.value = value
}
}
}
private val NULL_VALUE: Any = Any()
private fun escape(value: Any?): Any {
return value ?: NULL_VALUE
}
private fun unescape(value: Any?): Any? {
return if (value == NULL_VALUE) null else value
}
private class LazyVal<T>(private val initializer: () -> T) : ReadOnlyProperty<Any?, T> {
private var value: Any? = null
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
if (value == null) {
value = escape(initializer())
}
return unescape(value) as T
}
}
private class BlockingLazyVal<T>(lock: Any?, private val initializer: () -> T) : ReadOnlyProperty<Any?, T> {
private val lock = lock ?: this
private volatile var value: Any? = null
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
val _v1 = value
if (_v1 != null) {
return unescape(_v1) as T
}
return synchronized(lock) {
val _v2 = value
if (_v2 != null) {
unescape(_v2) as T
}
else {
val typedValue = initializer()
value = escape(typedValue)
typedValue
}
}
}
}
public class KeyMissingException(message: String): RuntimeException(message)
public abstract class MapVal<T, in K, out V>() : ReadOnlyProperty<T, V> {
protected abstract fun map(ref: T): Map<in K, Any?>
protected abstract fun key(desc: PropertyMetadata): K
protected open fun default(ref: T, desc: PropertyMetadata): V {
throw KeyMissingException("Key $desc is missing in $ref")
}
public override fun get(thisRef: T, desc: PropertyMetadata) : V {
val map = map(thisRef)
val key = key(desc)
if (!map.containsKey(key)) {
return default(thisRef, desc)
}
return map[key] as V
}
}
public abstract class MapVar<T, in K, V>() : MapVal<T, K, V>(), ReadWriteProperty<T, V> {
protected abstract override fun map(ref: T): MutableMap<in K, Any?>
public override fun set(thisRef: T, desc: PropertyMetadata, value: V) {
val map = map(thisRef)
map.put(key(desc), value)
}
}
private val defaultKeyProvider:(PropertyMetadata) -> String = {it.name}
private val defaultValueProvider:(Any?, Any?) -> Nothing = {(thisRef, key) -> throw KeyMissingException("$key is missing from $thisRef")}
public open class FixedMapVal<T, in K, out V>(private val map: Map<in K, Any?>,
private val key: (PropertyMetadata) -> K,
private val default: (ref: T, key: K) -> V = defaultValueProvider) : MapVal<T, K, V>() {
protected override fun map(ref: T): Map<in K, Any?> {
return map
}
protected override fun key(desc: PropertyMetadata): K {
return (key)(desc)
}
protected override fun default(ref: T, desc: PropertyMetadata): V {
return (default)(ref, key(desc))
}
}
public open class FixedMapVar<T, in K, V>(private val map: MutableMap<in K, Any?>,
private val key: (PropertyMetadata) -> K,
private val default: (ref: T, key: K) -> V = defaultValueProvider) : MapVar<T, K, V>() {
protected override fun map(ref: T): MutableMap<in K, Any?> {
return map
}
protected override fun key(desc: PropertyMetadata): K {
return (key)(desc)
}
protected override fun default(ref: T, desc: PropertyMetadata): V {
return (default)(ref, key(desc))
}
}
@@ -2,7 +2,6 @@ package kotlin.properties
import java.util.HashMap
import java.util.ArrayList
import kotlin.properties.delegation.ObservableProperty
public class ChangeEvent(val source: Any, val name: String, val oldValue: Any?, val newValue: Any?) {
var propogationId: Any? = null
@@ -65,8 +64,8 @@ public abstract class ChangeSupport {
}
}
protected fun property<T>(init: T): ObservableProperty<T> {
return ObservableProperty(init) { name, oldValue, newValue -> changeProperty(name, oldValue, newValue) }
protected fun property<T>(init: T): ReadWriteProperty<Any?, T> {
return Delegates.observable(init) { desc, oldValue, newValue -> changeProperty(desc.name, oldValue, newValue) }
}
public fun onPropertyChange(fn: (ChangeEvent) -> Unit) {
@@ -1,118 +0,0 @@
package kotlin.properties.delegation
import kotlin.properties.ChangeSupport
public class NotNullVar<T: Any> {
private var value: T? = null
public fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value ?: throw IllegalStateException("Property ${desc.name} should be initialized before get")
}
public fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
}
}
public class SynchronizedVar<T>(private val initValue: T, private val lock: Any) {
private var value: T = initValue
public fun get(thisRef: Any?, desc: PropertyMetadata): T {
return synchronized(lock) { value }
}
public fun set(thisRef: Any?, desc: PropertyMetadata, newValue: T) {
synchronized(lock) {
value = newValue
}
}
}
class ObservableProperty<T>(initialValue: T, val changeSupport: (name: String, oldValue: T, newValue: T) -> Unit) {
private var value = initialValue
public fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public fun set(thisRef: Any?, desc: PropertyMetadata, newValue: T) {
changeSupport(desc.name, value, newValue)
value = newValue
}
}
public class KeyMissingException(message: String): RuntimeException(message)
public abstract class MapVal<T, V> {
public abstract fun getMap(thisRef: T): Map<*, *>
public abstract fun getKey(desc: PropertyMetadata): Any?
public open fun getDefaultValue(desc: PropertyMetadata, key: Any?): V {
throw KeyMissingException("Key $key is missing")
}
public fun get(thisRef: T, desc: PropertyMetadata): V {
val key = getKey(desc)
val map = getMap(thisRef)
if (!map.containsKey(key)) {
return getDefaultValue(desc, key)
}
return map[key] as V
}
}
public abstract class MapVar<T, V>: MapVal<T, V>() {
public fun set(thisRef: T, desc: PropertyMetadata, newValue: V) {
val map = getMap(thisRef) as MutableMap<Any?, Any?>
map[getKey(desc)] = newValue
}
}
public fun <V> Map<String, *>.readOnlyProperty(default: (() -> V)? = null): MapVal<Any?, V> {
return object: MapVal<Any?, V>() {
override fun getMap(thisRef: Any?) = this@readOnlyProperty
override fun getKey(desc: PropertyMetadata) = desc.name
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
public fun <V> Map<*, *>.readOnlyProperty(default: (() -> V)? = null, key: Any?): MapVal<Any?, V> {
return object: MapVal<Any?, V>() {
override fun getMap(thisRef: Any?) = this@readOnlyProperty
override fun getKey(desc: PropertyMetadata) = key
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
public fun <V> Map<*, *>.readOnlyProperty(default: (() -> V)? = null, key: (desc: PropertyMetadata) -> Any?): MapVal<Any?, V> {
return object: MapVal<Any?, V>() {
override fun getMap(thisRef: Any?) = this@readOnlyProperty
override fun getKey(desc: PropertyMetadata) = key(desc)
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
public fun <V> MutableMap<String, *>.property(default: (() -> V)? = null): MapVar<Any?, V> {
return object: MapVar<Any?, V>() {
override fun getMap(thisRef: Any?) = this@property
override fun getKey(desc: PropertyMetadata) = desc.name
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
public fun <V> MutableMap<*, *>.property(default: (() -> V)? = null, key: Any?): MapVar<Any?, V> {
return object: MapVar<Any?, V>() {
override fun getMap(thisRef: Any?) = this@property
override fun getKey(desc: PropertyMetadata) = key
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
public fun <V> MutableMap<*, *>.property(default: (() -> V)? = null, key: (desc: PropertyMetadata) -> Any?): MapVar<Any?, V> {
return object: MapVar<Any?, V>() {
override fun getMap(thisRef: Any?) = this@property
override fun getKey(desc: PropertyMetadata) = key(desc)
override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = if (default == null) super.getDefaultValue(desc, key) else default()
}
}
@@ -1,75 +0,0 @@
package kotlin.properties.delegation.lazy
private val NULL_VALUE: Any = Any()
private fun <T> escape(value: T): Any {
return if (value == null) NULL_VALUE else value
}
private fun <T: Any> unescape(value: Any): T? {
return if (value == NULL_VALUE) null else value as T
}
public open class LazyVal<T: Any>(initializer: () -> T): NullableLazyVal<T>(initializer) {
override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return super.get(thisRef, desc)!!
}
}
public open class NullableLazyVal<T: Any>(private val initializer: () -> T?) {
private var value: Any? = null
public open fun get(thisRef: Any?, desc: PropertyMetadata): T? {
if (value == null) {
value = escape(initializer())
}
return unescape(value!!)
}
}
public open class VolatileLazyVal<T: Any>(initializer: () -> T): VolatileNullableLazyVal<T>(initializer) {
override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return super.get(thisRef, desc)!!
}
}
public open class VolatileNullableLazyVal<T: Any>(private val initializer: () -> T?) {
private volatile var value: Any? = null
public open fun get(thisRef: Any?, desc: PropertyMetadata): T? {
if (value == null) {
value = escape(initializer())
}
return unescape(value!!)
}
}
public open class AtomicLazyVal<T: Any>(lock: Any? = null, initializer: () -> T): AtomicNullableLazyVal<T>(lock, initializer) {
override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return super.get(thisRef, desc)!!
}
}
public open class AtomicNullableLazyVal<T: Any>(lock: Any? = null, private val initializer: () -> T?) {
private val lock = lock ?: this
private volatile var value: Any? = null
public open fun get(thisRef: Any?, desc: PropertyMetadata): T? {
val _v1 = value
if (_v1 != null) {
return unescape(_v1)
}
return synchronized(lock) {
val _v2 = value
if (_v2 != null) {
unescape<T>(_v2)
}
else {
val typedValue = initializer()
value = escape(typedValue)
typedValue
}
}
}
}