64 lines
2.1 KiB
Kotlin
64 lines
2.1 KiB
Kotlin
package ru.dbotthepony.kstarbound.json.builder
|
|
|
|
import com.google.gson.Gson
|
|
import com.google.gson.TypeAdapter
|
|
import com.google.gson.reflect.TypeToken
|
|
import ru.dbotthepony.kstarbound.util.KOptional
|
|
import kotlin.properties.Delegates
|
|
import kotlin.reflect.KMutableProperty1
|
|
import kotlin.reflect.KProperty1
|
|
import kotlin.reflect.KType
|
|
import kotlin.reflect.javaType
|
|
|
|
open class ReferencedProperty<T : Any, V>(
|
|
property: KProperty1<T, V>,
|
|
val isFlat: Boolean,
|
|
val mustBePresent: Boolean? = null,
|
|
val isIgnored: Boolean = false,
|
|
isMarkedNullable: Boolean? = null,
|
|
) {
|
|
@Suppress("CanBePrimaryConstructorProperty")
|
|
open val property: KProperty1<T, V> = property
|
|
|
|
val name: String get() = property.name
|
|
var adapter: TypeAdapter<V> by Delegates.notNull()
|
|
private set
|
|
|
|
val type: KType = property.returnType
|
|
val isMarkedNullable: Boolean = isMarkedNullable?.also {
|
|
if (it && !type.isMarkedNullable) throw IllegalArgumentException("Can't declare non-null property as nullable")
|
|
} ?: type.isMarkedNullable
|
|
|
|
operator fun component1() = property
|
|
operator fun component2() = adapter
|
|
|
|
private var isResolved = false
|
|
|
|
@OptIn(ExperimentalStdlibApi::class)
|
|
@Suppress("DEPRECATION")
|
|
fun resolve(gson: Gson) {
|
|
if (!isResolved) {
|
|
isResolved = true
|
|
val token = TypeToken.get(type.javaType)
|
|
|
|
if (token.rawType === KOptional::class.java && type.arguments.size == 1) {
|
|
val subtype = type.arguments[0]
|
|
|
|
if (subtype.type!!.isMarkedNullable) {
|
|
adapter = gson.getAdapter(TypeToken.getParameterized(KOptional.Nullable::class.java, subtype.type!!.javaType)) as TypeAdapter<V>
|
|
} else {
|
|
adapter = gson.getAdapter(TypeToken.getParameterized(KOptional.NotNull::class.java, subtype.type!!.javaType)) as TypeAdapter<V>
|
|
}
|
|
} else {
|
|
adapter = gson.getAdapter(token) as TypeAdapter<V>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class ReferencedMutableProperty<T : Any, V>(override val property: KMutableProperty1<T, V>, isFlat: Boolean, mustBePresent: Boolean?) : ReferencedProperty<T, V>(property, isFlat, mustBePresent) {
|
|
fun set(instance: T, value: Any?) {
|
|
(this.property as KMutableProperty1<T, Any?>).set(instance, value)
|
|
}
|
|
}
|