kotlin.script.experimental.util.propertiesCollection.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-main-kts Show documentation
Show all versions of kotlin-main-kts Show documentation
Kotlin "main" script definition
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package kotlin.script.experimental.util
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.io.Serializable
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.script.experimental.api.KotlinType
open class PropertiesCollection(protected var properties: Map, Any?> = emptyMap()) : Serializable {
open class Key(
val name: String,
@Transient val getDefaultValue: PropertiesCollection.() -> T?
) : Serializable {
constructor(name: String, defaultValue: T? = null) : this(name, { defaultValue })
override fun equals(other: Any?): Boolean = if (other is Key<*>) name == other.name else false
override fun hashCode(): Int = name.hashCode()
override fun toString(): String = "Key($name)"
companion object {
@JvmStatic
private val serialVersionUID = 0L
}
}
class TransientKey(
name: String,
getDefaultValue: PropertiesCollection.() -> T?
) : Key(name, getDefaultValue)
class CopiedKey(
source: Key,
getSourceProperties: PropertiesCollection.() -> PropertiesCollection?
) : Key(
source.name,
{
val sourceProperties = getSourceProperties()
if (sourceProperties == null) source.getDefaultValue(this)
else sourceProperties.get(source)
}
)
class PropertyKeyDelegate(private val getDefaultValue: PropertiesCollection.() -> T?, val isTransient: Boolean = false) {
constructor(defaultValue: T?, isTransient: Boolean = false) : this({ defaultValue }, isTransient)
operator fun getValue(thisRef: Any?, property: KProperty<*>): Key =
if (isTransient) TransientKey(property.name, getDefaultValue)
else Key(property.name, getDefaultValue)
}
class PropertyKeyCopyDelegate(
val source: Key, val getSourceProperties: PropertiesCollection.() -> PropertiesCollection? = { null }
) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Key = CopiedKey(source, getSourceProperties)
}
@Suppress("UNCHECKED_CAST")
operator fun get(key: Key): T? =
(properties[key] ?: if (properties.containsKey(key)) null else key.getDefaultValue(this)) as? T
@Suppress("UNCHECKED_CAST")
fun getNoDefault(key: Key): T? =
properties[key]?.let { it as T }
fun containsKey(key: Key): Boolean =
properties.containsKey(key)
fun entries(): Set, Any?>> = properties.entries
val notTransientData: Map, Any?>
get() = properties.filter { (key, value) -> key !is TransientKey<*> && value is Serializable }
fun isEmpty(): Boolean = properties.isEmpty()
override fun equals(other: Any?): Boolean =
(other as? PropertiesCollection)?.let { it.properties == properties } == true
override fun hashCode(): Int = properties.hashCode()
private fun writeObject(outputStream: ObjectOutputStream) {
outputStream.writeObject(notTransientData)
}
private fun readObject(inputStream: ObjectInputStream) {
@Suppress("UNCHECKED_CAST")
properties = inputStream.readObject() as Map, Any?>
}
companion object {
fun key(defaultValue: T? = null, isTransient: Boolean = false): PropertyKeyDelegate =
PropertyKeyDelegate(defaultValue, isTransient)
fun key(getDefaultValue: PropertiesCollection.() -> T?, isTransient: Boolean = false): PropertyKeyDelegate =
PropertyKeyDelegate(getDefaultValue, isTransient)
// fun keyCopy(source: Key): PropertyKeyCopyDelegate = PropertyKeyCopyDelegate(source)
fun keyCopy(
source: Key, getSourceProperties: PropertiesCollection.() -> PropertiesCollection? = { null }
): PropertyKeyCopyDelegate =
PropertyKeyCopyDelegate(source, getSourceProperties)
@JvmStatic
private val serialVersionUID = 1L
}
// properties builder base class (DSL for building properties collection)
open class Builder(baseProperties: Iterable = emptyList()) {
val data: MutableMap, Any?> = LinkedHashMap, Any?>().apply {
baseProperties.forEach { putAll(it.properties) }
}
// generic for all properties
operator fun Key.invoke(v: T) {
data[this] = v
}
fun Key.put(v: T) {
data[this] = v
}
fun Key.putIfNotNull(v: T?) {
if (v != null) {
data[this] = v
}
}
fun Key.replaceOnlyDefault(v: T?) {
if (!data.containsKey(this) || data[this] == this.getDefaultValue(PropertiesCollection(data))) {
data[this] = v
}
}
fun Key.update(body: (T?) -> T?) {
putIfNotNull(body(data[this]?.let {
@Suppress("UNCHECKED_CAST")
it as T
}))
}
// generic for lists
fun Key>.putIfAny(vals: Iterable?) {
if (vals?.any() == true) {
data[this] = if (vals is List) vals else vals.toList()
}
}
operator fun Key>.invoke(vararg vals: T) {
append(vals.asIterable())
}
// generic for maps:
@JvmName("putIfAny_map")
fun Key>.putIfAny(vals: Iterable>?) {
if (vals?.any() == true) {
data[this] = vals.toMap()
}
}
fun Key>.putIfAny(vals: Map?) {
if (vals?.isNotEmpty() == true) {
data[this] = vals
}
}
operator fun Key