1+ package github.kasuminova.mmce.common.serialize
2+
3+ import github.kasuminova.mmce.common.serialize.json.JsonRawDataStructure
4+ import github.kasuminova.mmce.common.serialize.raw.RawDataStructure
5+ import kotlinx.serialization.json.JsonObject
6+
7+ @Suppress(" UNCHECKED_CAST" )
8+ abstract class DataStructure {
9+
10+ val columns: MutableList <DataValue <* >> = mutableListOf ()
11+
12+ fun loadFrom (json : JsonObject ) = loadFrom(JsonRawDataStructure (json))
13+
14+ fun loadFrom (raw : RawDataStructure ) {
15+ for (column in this .columns) {
16+ try {
17+ (column as DataValueImpl ).solve(raw)
18+ } catch (e: Throwable ) {
19+ throw IllegalArgumentException (" Failed to parse column '${column.name} '" , e)
20+ }
21+ }
22+ }
23+
24+ protected fun raw (name : String ): DataValue <Any ?> = DataValueImpl <Any ?>(
25+ name = name,
26+ nullable = true ,
27+ deserializer = AnyToAnyDeserializer as DataValueDeserializer <Any , Any ?>,
28+ defProvider = { null }
29+ ).also { columns + = it }
30+
31+ protected fun byte (name : String ): DataValue <Byte > = raw(name)
32+ .notnull()
33+ .map { value -> (value as ? Number )?.toByte() ? : value.toString().toByte() }
34+ .def { 0 }
35+
36+ protected fun short (name : String ): DataValue <Short > = raw(name)
37+ .notnull()
38+ .map { value -> (value as ? Number )?.toShort() ? : value.toString().toShort() }
39+ .def { 0 }
40+
41+ protected fun integer (name : String ): DataValue <Int > = raw(name)
42+ .notnull()
43+ .map { value -> (value as ? Number )?.toInt() ? : value.toString().toInt() }
44+ .def { 0 }
45+
46+ protected fun long (name : String ): DataValue <Long > = raw(name)
47+ .notnull()
48+ .map { value -> (value as ? Number )?.toLong() ? : value.toString().toLong() }
49+ .def { 0L }
50+
51+ protected fun float (name : String ): DataValue <Float > = raw(name)
52+ .notnull()
53+ .map { value -> (value as ? Number )?.toFloat() ? : value.toString().toFloat() }
54+ .def { 0f }
55+
56+ protected fun double (name : String ): DataValue <Double > = raw(name)
57+ .notnull()
58+ .map { value -> (value as ? Number )?.toDouble() ? : value.toString().toDouble() }
59+ .def { 0.0 }
60+
61+ protected fun boolean (name : String ): DataValue <Boolean > = raw(name)
62+ .notnull()
63+ .map { value -> (value as ? Boolean ) ? : value.toString().toBoolean() }
64+ .def { false }
65+
66+ protected fun string (name : String ): DataValue <String > = raw(name)
67+ .notnull()
68+ .map { value -> value.toString() }
69+ .def { " " }
70+
71+ protected fun <T > list (name : String , mapping : (Any ) -> T ) = raw(name)
72+ .notnull()
73+ .map {
74+ if (it is List <* >) {
75+ it.map { e -> mapping(e!! ) }
76+ } else {
77+ emptyList()
78+ }
79+ }
80+
81+ protected fun subData (name : String ): DataValue <RawDataStructure ?> = raw(name)
82+ .nullable()
83+ .map { value -> value as ? RawDataStructure }
84+
85+ protected fun subStructure (name : String , structure : DataStructure ) = raw(name)
86+ .nullable()
87+ .map { value -> value as ? RawDataStructure }
88+ .map { raw ->
89+ structure.also { structure ->
90+ if (raw != null ) {
91+ structure.loadFrom(raw)
92+ }
93+ }
94+ }
95+
96+ protected fun multipleStructure (name : String , provider : () -> DataStructure ) = raw(name)
97+ .nullable()
98+ .map { value -> value as ? RawDataStructure }
99+ .map { raw ->
100+ raw?.getStructure(name)?.let { structure ->
101+ structure.keySet().associateWith { key -> provider().also { data -> data.loadFrom(structure.getStructure(key)!! ) } }
102+ }
103+ }
104+
105+ protected fun <E > enum (name : String , values : Array <E >): DataValue <E > where E : Enum <E > = raw(name)
106+ .notnull()
107+ .map { value ->
108+ val str = value.toString()
109+ values.firstOrNull { it.name == str }
110+ ? : throw IllegalArgumentException (" Value '$str ' is not valid for enum '${values.firstOrNull()?.javaClass?.name} '" )
111+ }
112+
113+ }
0 commit comments