Более функциональный подход к typeadapter
This commit is contained in:
parent
53c4c3fa11
commit
366e59cf14
@ -33,7 +33,7 @@ data class MaterialModifier(
|
|||||||
.auto(MaterialModifier::grass)
|
.auto(MaterialModifier::grass)
|
||||||
.list(MaterialModifier::miningSounds)
|
.list(MaterialModifier::miningSounds)
|
||||||
.auto(MaterialModifier::miningParticle)
|
.auto(MaterialModifier::miningParticle)
|
||||||
.plain(MaterialModifier::renderTemplate, RenderTemplate.CACHE)
|
.add(MaterialModifier::renderTemplate, RenderTemplate.CACHE)
|
||||||
.auto(MaterialModifier::renderParameters)
|
.auto(MaterialModifier::renderParameters)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ data class TileDefinition(
|
|||||||
TileDefinition::health,
|
TileDefinition::health,
|
||||||
TileDefinition::category
|
TileDefinition::category
|
||||||
)
|
)
|
||||||
.plain(TileDefinition::renderTemplate, RenderTemplate.CACHE)
|
.add(TileDefinition::renderTemplate, RenderTemplate.CACHE)
|
||||||
.auto(
|
.auto(
|
||||||
TileDefinition::renderParameters,
|
TileDefinition::renderParameters,
|
||||||
)
|
)
|
||||||
|
41
src/main/kotlin/ru/dbotthepony/kstarbound/io/json/Ext.kt
Normal file
41
src/main/kotlin/ru/dbotthepony/kstarbound/io/json/Ext.kt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
|
||||||
|
fun <T> TypeAdapter<T>.transformRead(transformer: (T) -> T): TypeAdapter<T> {
|
||||||
|
return object : TypeAdapter<T>() {
|
||||||
|
override fun write(out: JsonWriter, value: T) {
|
||||||
|
return this@transformRead.write(out, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): T {
|
||||||
|
return transformer(this@transformRead.read(`in`))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> TypeAdapter<T>.transformWrite(transformer: (T) -> T): TypeAdapter<T> {
|
||||||
|
return object : TypeAdapter<T>() {
|
||||||
|
override fun write(out: JsonWriter, value: T) {
|
||||||
|
return this@transformWrite.write(out, transformer(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): T {
|
||||||
|
return this@transformWrite.read(`in`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> TypeAdapter<T>.transform(transformRead: (T) -> T, transformWrite: (T) -> T): TypeAdapter<T> {
|
||||||
|
return object : TypeAdapter<T>() {
|
||||||
|
override fun write(out: JsonWriter, value: T) {
|
||||||
|
return this@transform.write(out, transformWrite(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(`in`: JsonReader): T {
|
||||||
|
return transformRead(this@transform.read(`in`))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -377,7 +377,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
/**
|
/**
|
||||||
* Добавляет поле с определённым адаптером
|
* Добавляет поле с определённым адаптером
|
||||||
*/
|
*/
|
||||||
fun <V> plain(field: KProperty1<T, V>, adapter: TypeAdapter<V>): Builder<T> {
|
fun <V> add(field: KProperty1<T, V>, adapter: TypeAdapter<V>): Builder<T> {
|
||||||
types.add(PackedProperty(field, adapter))
|
types.add(PackedProperty(field, adapter))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@ -410,7 +410,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
* Список неизменяем (создаётся объект [ImmutableList])
|
* Список неизменяем (создаётся объект [ImmutableList])
|
||||||
*/
|
*/
|
||||||
fun <V : Any> list(field: KProperty1<T, List<V>?>, type: Class<V>, transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
fun <V : Any> list(field: KProperty1<T, List<V>?>, type: Class<V>, transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
||||||
types.add(PackedProperty(field, ListAdapter(type), transformer = transformer))
|
types.add(PackedProperty(field, ListAdapter(type).nullSafe(), transformer = transformer))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
* Список неизменяем (создаётся объект [ImmutableList])
|
* Список неизменяем (создаётся объект [ImmutableList])
|
||||||
*/
|
*/
|
||||||
inline fun <reified V : Any> list(field: KProperty1<T, List<V>?>, noinline transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
inline fun <reified V : Any> list(field: KProperty1<T, List<V>?>, noinline transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
||||||
return this.list(field, V::class.java, transformer)
|
return add(field, ListAdapter(V::class.java).nullSafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,7 +453,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||||
*/
|
*/
|
||||||
fun <K : Any, V : Any> map(field: KProperty1<T, Map<K, V>?>, keyType: KClass<K>, valueType: KClass<V>): Builder<T> {
|
fun <K : Any, V : Any> map(field: KProperty1<T, Map<K, V>?>, keyType: KClass<K>, valueType: KClass<V>): Builder<T> {
|
||||||
types.add(PackedProperty(field, MapAdapter(keyType.java, valueType.java)))
|
types.add(PackedProperty(field, MapAdapter(keyType.java, valueType.java).nullSafe()))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||||
*/
|
*/
|
||||||
fun <V> map(field: KProperty1<T, Map<String, V>?>, valueType: Class<V>): Builder<T> {
|
fun <V> map(field: KProperty1<T, Map<String, V>?>, valueType: Class<V>): Builder<T> {
|
||||||
types.add(PackedProperty(field, StringMapAdapter(valueType)))
|
types.add(PackedProperty(field, String2ObjectAdapter(valueType).nullSafe()))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +473,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
|||||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||||
*/
|
*/
|
||||||
fun <V : Any> map(field: KProperty1<T, Map<String, V>?>, valueType: KClass<V>): Builder<T> {
|
fun <V : Any> map(field: KProperty1<T, Map<String, V>?>, valueType: KClass<V>): Builder<T> {
|
||||||
types.add(PackedProperty(field, StringMapAdapter(valueType.java)))
|
types.add(PackedProperty(field, String2ObjectAdapter(valueType.java).nullSafe()))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,18 +8,18 @@ import com.google.gson.stream.JsonToken
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
|
||||||
class ListAdapter<T>(private val type: Class<T>) : TypeAdapter<List<T>?>() {
|
fun <T : Any> TypeAdapter<T>.asList(): TypeAdapter<List<T>> {
|
||||||
private val resolvedBound by lazy { Starbound.getTypeAdapter(type) }
|
return ListAdapter(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: List<T>?) {
|
class ListAdapter<T : Any>(val elementAdapter: TypeAdapter<T>, val valueTransformer: (T) -> T = { it }) : TypeAdapter<List<T>>() {
|
||||||
|
constructor(type: Class<T>) : this(LazyTypeProvider(type))
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: List<T>) {
|
||||||
out.beginArray()
|
out.beginArray()
|
||||||
|
|
||||||
if (value != null) {
|
for (v in value) {
|
||||||
val resolvedBound = resolvedBound
|
elementAdapter.write(out, v)
|
||||||
|
|
||||||
for (v in value) {
|
|
||||||
resolvedBound.write(out, v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.endArray()
|
out.endArray()
|
||||||
@ -29,15 +29,14 @@ class ListAdapter<T>(private val type: Class<T>) : TypeAdapter<List<T>?>() {
|
|||||||
reader.beginArray()
|
reader.beginArray()
|
||||||
|
|
||||||
val builder = ImmutableList.builder<T>()
|
val builder = ImmutableList.builder<T>()
|
||||||
val resolvedBound = resolvedBound
|
|
||||||
|
|
||||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||||
val readObject = resolvedBound.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
val readObject = elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
||||||
builder.add(readObject as T)
|
builder.add(valueTransformer(readObject))
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.endArray()
|
reader.endArray()
|
||||||
|
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,17 @@ import com.google.gson.stream.JsonToken
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
|
||||||
class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Class<V>) : TypeAdapter<Map<K, V>?>() {
|
class MapAdapter<K, V>(val keyAdapter: TypeAdapter<K>, val valueAdapter: TypeAdapter<V>) : TypeAdapter<Map<K, V>>() {
|
||||||
private val resolvedKey by lazy { Starbound.getTypeAdapter(keyType) }
|
constructor(keyType: Class<K>, valueType: Class<V>) : this(LazyTypeProvider(keyType), LazyTypeProvider(valueType))
|
||||||
private val resolvedValue by lazy { Starbound.getTypeAdapter(valueType) }
|
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: Map<K, V>?) {
|
override fun write(out: JsonWriter, value: Map<K, V>) {
|
||||||
out.beginArray()
|
out.beginArray()
|
||||||
|
|
||||||
if (value != null) {
|
for ((k, v) in value) {
|
||||||
val resolvedKey = resolvedKey
|
out.beginArray()
|
||||||
val resolvedValue = resolvedValue
|
keyAdapter.write(out, k)
|
||||||
|
valueAdapter.write(out, v)
|
||||||
for ((k, v) in value) {
|
out.endArray()
|
||||||
out.beginArray()
|
|
||||||
resolvedKey.write(out, k)
|
|
||||||
resolvedValue.write(out, v)
|
|
||||||
out.endArray()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.endArray()
|
out.endArray()
|
||||||
@ -34,12 +28,9 @@ class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Cla
|
|||||||
|
|
||||||
val builder = ImmutableMap.builder<K, V>()
|
val builder = ImmutableMap.builder<K, V>()
|
||||||
|
|
||||||
val resolvedKey = resolvedKey
|
|
||||||
val resolvedValue = resolvedValue
|
|
||||||
|
|
||||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||||
reader.beginArray()
|
reader.beginArray()
|
||||||
builder.put(resolvedKey.read(reader), resolvedValue.read(reader))
|
builder.put(keyAdapter.read(reader), valueAdapter.read(reader))
|
||||||
reader.endArray()
|
reader.endArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,4 +38,4 @@ class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Cla
|
|||||||
|
|
||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package ru.dbotthepony.kstarbound.io.json
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.gson.TypeAdapter
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import com.google.gson.stream.JsonToken
|
||||||
|
import com.google.gson.stream.JsonWriter
|
||||||
|
import ru.dbotthepony.kstarbound.Starbound
|
||||||
|
|
||||||
|
fun <T> TypeAdapter<T>.asJsonObject(): TypeAdapter<Map<String, T>> {
|
||||||
|
return String2ObjectAdapter(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class String2ObjectAdapter<T>(val adapter: TypeAdapter<T>) : TypeAdapter<Map<String, T>>() {
|
||||||
|
constructor(type: Class<T>) : this(LazyTypeProvider(type))
|
||||||
|
|
||||||
|
override fun write(out: JsonWriter, value: Map<String, T>) {
|
||||||
|
out.beginObject()
|
||||||
|
|
||||||
|
for ((k, v) in value) {
|
||||||
|
out.name(k)
|
||||||
|
adapter.write(out, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endObject()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(reader: JsonReader): Map<String, T> {
|
||||||
|
val builder = ImmutableMap.builder<String, T>()
|
||||||
|
|
||||||
|
reader.beginObject()
|
||||||
|
|
||||||
|
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||||
|
builder.put(Starbound.assetStringInterner.intern(reader.nextName()), adapter.read(reader))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject()
|
||||||
|
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
package ru.dbotthepony.kstarbound.io.json
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap
|
|
||||||
import com.google.gson.TypeAdapter
|
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import com.google.gson.stream.JsonToken
|
|
||||||
import com.google.gson.stream.JsonWriter
|
|
||||||
import ru.dbotthepony.kstarbound.Starbound
|
|
||||||
|
|
||||||
class StringMapAdapter<V>(private val type: Class<V>) : TypeAdapter<Map<String, V>?>() {
|
|
||||||
private val resolvedBound by lazy { Starbound.getTypeAdapter(type) }
|
|
||||||
|
|
||||||
override fun write(out: JsonWriter, value: Map<String, V>?) {
|
|
||||||
val resolvedBound = resolvedBound
|
|
||||||
|
|
||||||
out.beginObject()
|
|
||||||
|
|
||||||
if (value != null) {
|
|
||||||
for ((k, v) in value) {
|
|
||||||
out.name(k)
|
|
||||||
resolvedBound.write(out, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out.endObject()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(reader: JsonReader): Map<String, V> {
|
|
||||||
val builder = ImmutableMap.builder<String, V>()
|
|
||||||
|
|
||||||
reader.beginObject()
|
|
||||||
|
|
||||||
val resolvedBound = resolvedBound
|
|
||||||
|
|
||||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
|
||||||
builder.put(Starbound.assetStringInterner.intern(reader.nextName()), resolvedBound.read(reader))
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.endObject()
|
|
||||||
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user