Покидаемся исключениями?

This commit is contained in:
DBotThePony 2022-12-31 13:20:03 +07:00
parent bfae6877c9
commit a27cba5e0f
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -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))
}