mirror of
https://github.com/InsanusMokrassar/SDI.git
synced 2025-09-15 21:19:16 +00:00
@@ -1,5 +1,11 @@
|
|||||||
# SDI changelogs
|
# SDI changelogs
|
||||||
|
|
||||||
|
## 0.1.2
|
||||||
|
|
||||||
|
* All reflection support methods are internal
|
||||||
|
* Added `loadModule` functions for more useful working with modules loading
|
||||||
|
* `Module` now is not serializable and can be created only via `loadModule` functions (at least, for some time)
|
||||||
|
|
||||||
## 0.1.1
|
## 0.1.1
|
||||||
|
|
||||||
* Added opportunity to create objects inside of config:
|
* Added opportunity to create objects inside of config:
|
||||||
|
@@ -36,7 +36,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
api kotlin('reflect')
|
||||||
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlin_serialisation_runtime_version"
|
api "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$kotlin_serialisation_runtime_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
package com.insanusmokrassar.sdi
|
||||||
|
|
||||||
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun Json.loadModule(json: String): Module = parse(ModuleDeserializerStrategy, json)
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun loadModule(json: String): Module = Json.nonstrict.loadModule(json)
|
5
src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt
Normal file
5
src/commonMain/kotlin/com/insanusmokrassar/sdi/Module.kt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package com.insanusmokrassar.sdi
|
||||||
|
|
||||||
|
import kotlinx.serialization.ContextualSerialization
|
||||||
|
|
||||||
|
class Module internal constructor(base: Map<String, @ContextualSerialization Any>) : Map<String, Any> by base
|
@@ -1,19 +1,13 @@
|
|||||||
package com.insanusmokrassar.sdi
|
package com.insanusmokrassar.sdi
|
||||||
|
|
||||||
import com.insanusmokrassar.sdi.utils.*
|
import com.insanusmokrassar.sdi.utils.createModuleBasedOnConfigRoot
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.internal.*
|
import kotlinx.serialization.internal.HashMapSerializer
|
||||||
|
import kotlinx.serialization.internal.StringSerializer
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import kotlinx.serialization.modules.*
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
@ImplicitReflectionSerializer
|
||||||
@Serializable(ModuleSerializer::class)
|
internal object ModuleDeserializerStrategy : DeserializationStrategy<Module> {
|
||||||
class Module(base: Map<String, @ContextualSerialization Any>) : Map<String, Any> by base
|
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
|
||||||
@Serializer(Module::class)
|
|
||||||
internal object ModuleSerializer : KSerializer<Module> {
|
|
||||||
private val internalSerializer = HashMapSerializer(StringSerializer, ContextSerializer(Any::class))
|
private val internalSerializer = HashMapSerializer(StringSerializer, ContextSerializer(Any::class))
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() = internalSerializer.descriptor
|
get() = internalSerializer.descriptor
|
||||||
@@ -28,7 +22,5 @@ internal object ModuleSerializer : KSerializer<Module> {
|
|||||||
return Module(map)
|
return Module(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, obj: Module) {
|
override fun patch(decoder: Decoder, old: Module): Module = throw UpdateNotSupportedException("Module")
|
||||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi.utils
|
|||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import kotlinx.serialization.modules.*
|
import kotlinx.serialization.modules.SerializerAlreadyRegisteredException
|
||||||
|
import kotlinx.serialization.modules.SerializersModuleBuilder
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
@ImplicitReflectionSerializer
|
||||||
@@ -13,7 +14,7 @@ internal class DependencyResolver<T : Any>(
|
|||||||
private val dependencyGetter: (String) -> Any
|
private val dependencyGetter: (String) -> Any
|
||||||
) : KSerializer<T> {
|
) : KSerializer<T> {
|
||||||
private val originalSerializer: KSerializer<T> = try {
|
private val originalSerializer: KSerializer<T> = try {
|
||||||
resolveSerializerByKClass(kClass)
|
kClass.serializer()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
PolymorphicSerializer(kClass)
|
PolymorphicSerializer(kClass)
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
package com.insanusmokrassar.sdi.utils
|
package com.insanusmokrassar.sdi.utils
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import kotlinx.serialization.modules.*
|
import kotlinx.serialization.modules.SerializerAlreadyRegisteredException
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
|
|
||||||
private typealias PackageOrOtherDependencyNamePair = Pair<String?, String?>
|
private typealias PackageOrOtherDependencyNamePair = Pair<String?, String?>
|
||||||
|
|
||||||
@@ -63,25 +64,26 @@ internal fun createModuleBasedOnConfigRoot(jsonObject: JsonObject): Json {
|
|||||||
key to packageName
|
key to packageName
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|
||||||
return Json(
|
val context = SerializersModule {
|
||||||
configuration = JsonConfiguration(useArrayPolymorphism = true),
|
keysToPackages.values.forEach {
|
||||||
context = SerializersModule {
|
val kclass = resolveKClassByPackageName(it)
|
||||||
keysToPackages.values.forEach {
|
|
||||||
val kclass = resolveKClassByPackageName(it)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DependencyResolver(
|
DependencyResolver(
|
||||||
this,
|
this,
|
||||||
kclass,
|
kclass,
|
||||||
{ jsonStringFormat }
|
{ jsonStringFormat }
|
||||||
) {
|
) {
|
||||||
caches.getValue(it).invoke()
|
caches.getValue(it).invoke()
|
||||||
}
|
|
||||||
} catch (e: SerializerAlreadyRegisteredException) {
|
|
||||||
// here we are thinking that already registered
|
|
||||||
}
|
}
|
||||||
|
} catch (e: SerializerAlreadyRegisteredException) {
|
||||||
|
// here we are thinking that already registered
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return Json(
|
||||||
|
configuration = JsonConfiguration(useArrayPolymorphism = true),
|
||||||
|
context = context
|
||||||
).also {
|
).also {
|
||||||
jsonStringFormat = it
|
jsonStringFormat = it
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,22 @@
|
|||||||
package com.insanusmokrassar.sdi.utils
|
package com.insanusmokrassar.sdi.utils
|
||||||
|
|
||||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
|
||||||
|
internal expect fun resolveKClassByPackageName(packageName: String): KClass<*>
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
@ImplicitReflectionSerializer
|
||||||
expect fun resolveSerializerByPackageName(packageName: String): KSerializer<*>
|
internal fun <T : Any> resolveSerializerByKClass(kClass: KClass<T>): KSerializer<T> = kClass.serializer()
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
@ImplicitReflectionSerializer
|
||||||
expect fun <T : Any> resolveSerializerByKClass(kClass: KClass<T>): KSerializer<T>
|
internal fun resolveSerializerByPackageName(packageName: String): KSerializer<*> = resolveSerializerByKClass(
|
||||||
|
resolveKClassByPackageName(packageName)
|
||||||
|
)
|
||||||
|
|
||||||
expect fun resolveKClassByPackageName(packageName: String): KClass<*>
|
internal val KClass<*>.allSubclasses: Set<KClass<*>>
|
||||||
|
|
||||||
expect val KClass<*>.currentSupertypes: List<KType>
|
|
||||||
|
|
||||||
val KClass<*>.allSubclasses: Set<KClass<*>>
|
|
||||||
get() {
|
get() {
|
||||||
val subclasses = mutableSetOf<KClass<*>>()
|
val subclasses = mutableSetOf<KClass<*>>()
|
||||||
val leftToVisit = currentSupertypes.mapNotNull { it.classifier as? KClass<*> }.toMutableList()
|
val leftToVisit = supertypes.mapNotNull { it.classifier as? KClass<*> }.toMutableList()
|
||||||
while (leftToVisit.isNotEmpty()) {
|
while (leftToVisit.isNotEmpty()) {
|
||||||
val top = leftToVisit.removeAt(0)
|
val top = leftToVisit.removeAt(0)
|
||||||
if (subclasses.add(top)) {
|
if (subclasses.add(top)) {
|
||||||
|
@@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi
|
|||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlin.test.*
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
interface List_ParentalAPI {
|
interface List_ParentalAPI {
|
||||||
val services: List<List_ChildAPI>
|
val services: List<List_ChildAPI>
|
||||||
@@ -44,7 +45,7 @@ class ListTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val module = Json.plain.parse(Module.serializer(), input)
|
val module = loadModule(input)
|
||||||
(module[controllerName] as List_ParentalAPI)
|
(module[controllerName] as List_ParentalAPI)
|
||||||
val controller = (module[controllerName] as List_Parent)
|
val controller = (module[controllerName] as List_Parent)
|
||||||
controller.services.forEachIndexed { i, service ->
|
controller.services.forEachIndexed { i, service ->
|
||||||
|
@@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi
|
|||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlin.test.*
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
interface SimpleCustomObject_ControllerAPI {
|
interface SimpleCustomObject_ControllerAPI {
|
||||||
fun showUp()
|
fun showUp()
|
||||||
@@ -78,7 +79,7 @@ class SimpleCustomObjectTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val module = Json.plain.parse(Module.serializer(), input)
|
val module = loadModule(input)
|
||||||
|
|
||||||
(module[controllerName] as SimpleCustomObject_ControllerAPI)
|
(module[controllerName] as SimpleCustomObject_ControllerAPI)
|
||||||
val controller = (module["controller"] as SimpleCustomObject_Controller)
|
val controller = (module["controller"] as SimpleCustomObject_Controller)
|
||||||
|
@@ -2,7 +2,8 @@ package com.insanusmokrassar.sdi
|
|||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlin.test.*
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
interface Simple_ControllerAPI {
|
interface Simple_ControllerAPI {
|
||||||
fun showUp()
|
fun showUp()
|
||||||
@@ -42,7 +43,7 @@ class SimpleTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val module = Json.plain.parse(Module.serializer(), input)
|
val module = loadModule(input)
|
||||||
(module[controllerName] as Simple_ControllerAPI)
|
(module[controllerName] as Simple_ControllerAPI)
|
||||||
val controller = (module["controller"] as Simple_Controller)
|
val controller = (module["controller"] as Simple_Controller)
|
||||||
assertEquals(names.toList(), controller.service.names)
|
assertEquals(names.toList(), controller.service.names)
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
package com.insanusmokrassar.sdi
|
||||||
|
|
||||||
|
import kotlinx.io.InputStream
|
||||||
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun Json.loadModule(stream: InputStream) = loadModule(stream.reader().readText())
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun loadModule(stream: InputStream) = Json.nonstrict.loadModule(stream.reader().readText())
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun Json.loadModule(file: File) = loadModule(file.inputStream())
|
||||||
|
|
||||||
|
@ImplicitReflectionSerializer
|
||||||
|
fun loadModule(file: File) = Json.nonstrict.loadModule(file.inputStream())
|
@@ -1,7 +0,0 @@
|
|||||||
package com.insanusmokrassar.sdi.utils
|
|
||||||
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.KType
|
|
||||||
|
|
||||||
actual val KClass<*>.currentSupertypes: List<KType>
|
|
||||||
get() = this.supertypes
|
|
@@ -0,0 +1,5 @@
|
|||||||
|
package com.insanusmokrassar.sdi.utils
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
actual fun resolveKClassByPackageName(packageName: String): KClass<*> = Class.forName(packageName).kotlin
|
@@ -1,12 +0,0 @@
|
|||||||
package com.insanusmokrassar.sdi.utils
|
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
|
||||||
actual fun resolveSerializerByPackageName(packageName: String): KSerializer<*> = Class.forName(packageName).kotlin.serializer()
|
|
||||||
|
|
||||||
@ImplicitReflectionSerializer
|
|
||||||
actual fun <T : Any> resolveSerializerByKClass(kClass: KClass<T>): KSerializer<T> = kClass.serializer()
|
|
||||||
|
|
||||||
actual fun resolveKClassByPackageName(packageName: String): KClass<*> = Class.forName(packageName).kotlin
|
|
Reference in New Issue
Block a user