Покидаемся исключениями?
This commit is contained in:
parent
bfae6877c9
commit
a27cba5e0f
@ -10,6 +10,7 @@ import com.google.gson.stream.JsonWriter
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kstarbound.util.NotNullVar
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
@ -37,7 +38,7 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
/**
|
||||
* Свойства объекта [T], которые можно выставлять
|
||||
*/
|
||||
val properties: ImmutableMap<String, WrappedProperty<T, Any?>>,
|
||||
val properties: ImmutableMap<String, WrappedProperty<T, *>>,
|
||||
|
||||
/**
|
||||
* Ключи, которые необходимо игнорировать при чтении JSON
|
||||
@ -51,7 +52,7 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
}
|
||||
|
||||
override fun read(reader: JsonReader): T {
|
||||
val missing = ObjectArraySet<WrappedProperty<T, Any?>>()
|
||||
val missing = ObjectArraySet<WrappedProperty<T, *>>()
|
||||
missing.addAll(properties.values)
|
||||
|
||||
reader.beginObject()
|
||||
@ -73,17 +74,17 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
val peek = reader.peek()
|
||||
|
||||
if (!property.returnType.isMarkedNullable && peek == JsonToken.NULL) {
|
||||
throw NullPointerException("Property ${property.property.name} of ${instance::class.qualifiedName} does not accept nulls")
|
||||
throw NullPointerException("Property ${property.name} of ${instance::class.qualifiedName} does not accept nulls")
|
||||
} else if (peek == JsonToken.NULL) {
|
||||
property.property.set(instance, null)
|
||||
property.set(instance, null)
|
||||
reader.nextNull()
|
||||
} else {
|
||||
val readValue = property.adapter.read(reader)
|
||||
property.property.set(instance, readValue)
|
||||
property.set(instance, readValue)
|
||||
check(missing.remove(property))
|
||||
}
|
||||
} catch(err: Throwable) {
|
||||
throw JsonSyntaxException("Reading property ${property.property.name} of ${instance::class.qualifiedName} near ${reader.path}", err)
|
||||
throw JsonSyntaxException("Reading property ${property.name} of ${instance::class.qualifiedName} near ${reader.path}", err)
|
||||
}
|
||||
} else {
|
||||
if (!loggedMisses.contains(name)) {
|
||||
@ -98,8 +99,24 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
reader.endObject()
|
||||
|
||||
for (property in missing) {
|
||||
if (property.mustBePresent == null) {
|
||||
// null - проверяем, есть ли делегат
|
||||
if (property.mustBePresent == true) {
|
||||
throw JsonSyntaxException("${instance::class.qualifiedName} demands for ${property.name} to be present, however, it is missing")
|
||||
} else if (property.mustBePresent == null) {
|
||||
if (property.returnType.isMarkedNullable) {
|
||||
continue
|
||||
}
|
||||
|
||||
val delegate = property.property.getDelegate(instance)
|
||||
|
||||
if (delegate is NotNullVar<*> && !delegate.isInitialized) {
|
||||
throw JsonSyntaxException("${property.name} in ${instance::class.qualifiedName} can not be null, but it is missing from JSON structure")
|
||||
} else {
|
||||
try {
|
||||
property.property.get(instance)
|
||||
} catch (err: Throwable) {
|
||||
throw JsonSyntaxException("${property.name} in ${instance::class.qualifiedName} does not like it being missing from JSON structure", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,10 +126,21 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
data class WrappedProperty<T, V : Any?>(
|
||||
val property: KMutableProperty1<T, V>,
|
||||
val adapter: TypeAdapter<V>,
|
||||
/**
|
||||
* @see PropertyConfigurator.mustBePresent
|
||||
*/
|
||||
val mustBePresent: Boolean?,
|
||||
) {
|
||||
inline val name get() = property.name
|
||||
// кеш
|
||||
val returnType = property.returnType
|
||||
|
||||
// так как дженерики тут немного слабенькие
|
||||
// Так что вот так...
|
||||
@Suppress("unchecked_cast")
|
||||
fun set(receiver: T, value: Any?) {
|
||||
property.set(receiver, value as V)
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyConfigurator<T, V : Any?>(
|
||||
@ -121,6 +149,10 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
) {
|
||||
/**
|
||||
* Обязана ли присутствовать эта переменная внутри JSON структуры.
|
||||
*
|
||||
* * `true` - всегда кидать исключения
|
||||
* * `false` - никогда не кидать исключения
|
||||
* * `null` - кидать исключения на усмотрение реализации (по умолчанию)
|
||||
*/
|
||||
var mustBePresent: Boolean? = null
|
||||
}
|
||||
@ -165,7 +197,7 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
throw IllegalArgumentException("${property.name} is a Map, please use autoMap() method instead")
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
@Suppress("unchecked_cast") // classifier.java не имеет обозначенного типа
|
||||
return add(property, LazyTypeProvider(classifier.java) as TypeAdapter<V>, configurator)
|
||||
}
|
||||
|
||||
@ -178,12 +210,11 @@ class BuilderAdapter<T : Any> private constructor(
|
||||
return this
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
fun build(): BuilderAdapter<T> {
|
||||
val map = ImmutableMap.Builder<String, WrappedProperty<T, Any?>>()
|
||||
val map = ImmutableMap.Builder<String, WrappedProperty<T, *>>()
|
||||
|
||||
for (property in properties)
|
||||
map.put(property.property.name, property as WrappedProperty<T, Any?>)
|
||||
map.put(property.property.name, property)
|
||||
|
||||
return BuilderAdapter(factory, map.build(), ImmutableSet.copyOf(ignoreKeys))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user