mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-10-30 19:50:31 +00:00 
			
		
		
		
	Compare commits
	
		
			51 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4338fd46f2 | |||
| 36974f5b49 | |||
| d48f767408 | |||
| bd2558e852 | |||
| 9f7c963cd5 | |||
| 2db0eadbfe | |||
| 580c7b8842 | |||
| 88fba347ea | |||
| c8c5255e62 | |||
| 01a1a2760a | |||
| 6d34df8d48 | |||
| b124ea65e1 | |||
| f3214347a9 | |||
| 6b8724b59f | |||
| ac3e378edf | |||
| 5d31fd1c91 | |||
| 046fe1ec08 | |||
| 721873c843 | |||
| f6ffbfc10a | |||
| 4e91649e0a | |||
| 4f7f8abec4 | |||
| 6370562dbc | |||
| 94e2e67522 | |||
| 1d8330015d | |||
| e5017b0258 | |||
| cd412ca31b | |||
| d2b6473095 | |||
| ab42507275 | |||
| dcef844e20 | |||
| 3244708c1b | |||
| 73ac1f1741 | |||
| f104e9f352 | |||
| 393c9a7d06 | |||
| ea497ea488 | |||
|  | 5add89cad0 | ||
| 2db447d2ef | |||
| 31c83813e6 | |||
| 27483a282d | |||
| 48b816aa22 | |||
| 0065f94f52 | |||
| ccc0002eb2 | |||
| 15a2eee141 | |||
| b9faac71e5 | |||
| 0a4465de33 | |||
| f9dfd09628 | |||
| 8638d7afce | |||
| 8311793a43 | |||
| 0d552cfcd2 | |||
| 4b0f20dbd1 | |||
| cf531c949d | |||
| ba5c5f17d5 | 
							
								
								
									
										89
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,94 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## 0.20.47 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Exposed`: `0.49.0` -> `0.50.0` | ||||
|  | ||||
| ## 0.20.46 | ||||
|  | ||||
| * `Common`: | ||||
|     * Now this repo depends on `klock` | ||||
|     * Add new object-serializer `DateTimeSerializer` for `klock` serializer | ||||
|  | ||||
| ## 0.20.45 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Android Core KTX`: `1.12.0` -> `1.13.0` | ||||
|  | ||||
| ## 0.20.44 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Compose`: `1.6.1` -> `1.6.2` | ||||
|     * `Koin`: `3.5.4` -> `3.5.6` | ||||
|  | ||||
| ## 0.20.43 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Ktor`: `2.3.9` -> `2.3.10` | ||||
|     * `Koin`: `3.5.3` -> `3.5.4` | ||||
|  | ||||
| ## 0.20.42 | ||||
|  | ||||
| * `Repos`: | ||||
|     * `Generator`: | ||||
|         * Improvements | ||||
|  | ||||
| ## 0.20.41 | ||||
|  | ||||
| * `Repos`: | ||||
|     * `Exposed`: | ||||
|         * `AbstractExposedKeyValueRepo`, `ExposedKeyValueRepo`, `AbstractExposedKeyValuesRepo`, `ExposedKeyValuesRepo` got opportunity to setup some part of their flows | ||||
|  | ||||
| ## 0.20.40 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `KSLog`: `1.3.2` -> `1.3.3` | ||||
|     * `Exposed`: `0.48.0` -> `0.49.0` | ||||
|     * `UUID`: `0.8.2` -> `0.8.4` | ||||
|  | ||||
| ## 0.20.39 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Kotlin`: `1.9.22` -> `1.9.23` | ||||
|     * `Korlibs`: `5.3.2` -> `5.4.0` | ||||
|     * `Okio`: `3.8.0` -> `3.9.0` | ||||
|     * `Compose`: `1.6.0` -> `1.6.1` | ||||
|     * `ComposeMaterial3`: `1.2.0` -> `1.2.1` | ||||
|  | ||||
| ## 0.20.38 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Ktor`: `2.3.8` -> `2.3.9` | ||||
|  | ||||
| ## 0.20.37 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Compose`: `1.5.12` -> `1.6.0` | ||||
|     * `Exposed`: `0.47.0` -> `0.48.0` | ||||
|  | ||||
| ## 0.20.36 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Serialization`: `1.6.2` -> `1.6.3` | ||||
|     * `Korlibs`: `5.3.1` -> `5.3.2` | ||||
| * `Repos`: | ||||
|     * `Cache`: | ||||
|         * Improve work and functionality of `actualizeAll` and subsequent functions | ||||
|         * All internal repos `invalidate`/`actualizeAll` now use common `actualizeAll` functions | ||||
|  | ||||
| ## 0.20.35 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Coroutines`: `1.7.3` -> `1.8.0` | ||||
|     * `Material3`: `1.1.2` -> `1.2.0` | ||||
|  | ||||
| ## 0.20.34 | ||||
|  | ||||
| * `Repos`: | ||||
|     * `Common`: | ||||
|         * Improve default `set` realization of `KeyValuesRepo` | ||||
|  | ||||
| ## 0.20.33 | ||||
|  | ||||
| * `Colors` | ||||
|   | ||||
| @@ -8,6 +8,11 @@ apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64ProjectPresetPath" | ||||
|  | ||||
| kotlin { | ||||
|     sourceSets { | ||||
|         commonMain { | ||||
|             dependencies { | ||||
|                 api libs.klock | ||||
|             } | ||||
|         } | ||||
|         jvmMain { | ||||
|             dependencies { | ||||
|                 api project(":micro_utils.coroutines") | ||||
|   | ||||
| @@ -0,0 +1,23 @@ | ||||
| package dev.inmo.micro_utils.common | ||||
|  | ||||
| import korlibs.time.DateTime | ||||
| import kotlinx.serialization.KSerializer | ||||
| import kotlinx.serialization.Serializer | ||||
| import kotlinx.serialization.builtins.serializer | ||||
| import kotlinx.serialization.descriptors.SerialDescriptor | ||||
| import kotlinx.serialization.encoding.Decoder | ||||
| import kotlinx.serialization.encoding.Encoder | ||||
|  | ||||
| @Serializer(DateTime::class) | ||||
| object DateTimeSerializer : KSerializer<DateTime> { | ||||
|     override val descriptor: SerialDescriptor | ||||
|         get() = Double.serializer().descriptor | ||||
|  | ||||
|     override fun deserialize(decoder: Decoder): DateTime { | ||||
|         return DateTime(decoder.decodeDouble()) | ||||
|     } | ||||
|  | ||||
|     override fun serialize(encoder: Encoder, value: DateTime) { | ||||
|         encoder.encodeDouble(value.unixMillis) | ||||
|     } | ||||
| } | ||||
| @@ -15,5 +15,5 @@ crypto_js_version=4.1.1 | ||||
| # Project data | ||||
|  | ||||
| group=dev.inmo | ||||
| version=0.20.33 | ||||
| android_code_version=239 | ||||
| version=0.20.47 | ||||
| android_code_version=253 | ||||
|   | ||||
| @@ -1,41 +1,41 @@ | ||||
| [versions] | ||||
|  | ||||
| kt = "1.9.22" | ||||
| kt-serialization = "1.6.2" | ||||
| kt-coroutines = "1.7.3" | ||||
| kt = "1.9.23" | ||||
| kt-serialization = "1.6.3" | ||||
| kt-coroutines = "1.8.0" | ||||
|  | ||||
| kslog = "1.3.2" | ||||
| kslog = "1.3.3" | ||||
|  | ||||
| jb-compose = "1.5.12" | ||||
| jb-exposed = "0.47.0" | ||||
| jb-dokka = "1.9.10" | ||||
| jb-compose = "1.6.2" | ||||
| jb-exposed = "0.50.0" | ||||
| jb-dokka = "1.9.20" | ||||
|  | ||||
| korlibs = "5.3.1" | ||||
| uuid = "0.8.2" | ||||
| korlibs = "5.4.0" | ||||
| uuid = "0.8.4" | ||||
|  | ||||
| ktor = "2.3.8" | ||||
| ktor = "2.3.10" | ||||
|  | ||||
| gh-release = "2.5.2" | ||||
|  | ||||
| koin = "3.5.3" | ||||
| koin = "3.5.6" | ||||
|  | ||||
| okio = "3.8.0" | ||||
| okio = "3.9.0" | ||||
|  | ||||
| ksp = "1.9.22-1.0.17" | ||||
| ksp = "1.9.23-1.0.20" | ||||
| kotlin-poet = "1.16.0" | ||||
|  | ||||
| versions = "0.51.0" | ||||
|  | ||||
| android-gradle = "8.2.2" | ||||
| android-gradle = "8.4.0" | ||||
| dexcount = "4.0.0" | ||||
|  | ||||
| android-coreKtx = "1.12.0" | ||||
| android-coreKtx = "1.13.0" | ||||
| android-recyclerView = "1.3.2" | ||||
| android-appCompat = "1.6.1" | ||||
| android-fragment = "1.6.2" | ||||
| android-espresso = "3.5.1" | ||||
| android-test = "1.1.5" | ||||
| android-compose-material3 = "1.1.2" | ||||
| android-compose-material3 = "1.2.1" | ||||
|  | ||||
| android-props-minSdk = "21" | ||||
| android-props-compileSdk = "34" | ||||
|   | ||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
|   | ||||
| @@ -12,7 +12,6 @@ kotlin { | ||||
|             dependencies { | ||||
|                 api internalProject("micro_utils.common") | ||||
|                 api libs.kt.serialization.cbor | ||||
|                 api libs.klock | ||||
|                 api libs.uuid | ||||
|                 api libs.ktor.io | ||||
|             } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.withReadAcquire | ||||
| import dev.inmo.micro_utils.coroutines.withWriteLock | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| @@ -29,7 +30,7 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>( | ||||
|             kvCache.getAll() | ||||
|         }.takeIf { it.size.toLong() == count() } ?: parentRepo.getAll().also { | ||||
|             locker.withWriteLock { | ||||
|                 kvCache.actualizeAll(true) { it } | ||||
|                 kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -148,7 +149,9 @@ open class CRUDCacheRepo<ObjectType, IdType, InputValueType>( | ||||
|     locker, | ||||
|     idGetter | ||||
| ), | ||||
|     CRUDRepo<ObjectType, IdType, InputValueType> | ||||
|     CRUDRepo<ObjectType, IdType, InputValueType> { | ||||
|     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||
| } | ||||
|  | ||||
| fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached( | ||||
|     kvCache: KVCache<IdType, ObjectType>, | ||||
|   | ||||
| @@ -1,5 +1,11 @@ | ||||
| package dev.inmo.micro_utils.repos.cache | ||||
|  | ||||
| interface CacheRepo { | ||||
| interface InvalidatableRepo { | ||||
|     /** | ||||
|      * Invalidates its internal data. It __may__ lead to autoreload of data. In case when repo makes autoreload, | ||||
|      * it must do loading of data __before__ clear | ||||
|      */ | ||||
|     suspend fun invalidate() | ||||
| } | ||||
|  | ||||
| typealias CacheRepo = InvalidatableRepo | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | ||||
| import dev.inmo.micro_utils.pagination.* | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.flow.* | ||||
| @@ -48,9 +49,7 @@ open class ReadKeyValueCacheRepo<Key,Value>( | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override suspend fun invalidate() = locker.withWriteLock { | ||||
|         kvCache.clear() | ||||
|     } | ||||
|     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||
| } | ||||
|  | ||||
| fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached( | ||||
| @@ -75,10 +74,6 @@ open class KeyValueCacheRepo<Key,Value>( | ||||
|         } | ||||
|     }.launchIn(scope) | ||||
|  | ||||
|     override suspend fun invalidate() = locker.withWriteLock { | ||||
|         kvCache.clear() | ||||
|     } | ||||
|  | ||||
|     override suspend fun clear() { | ||||
|         parentRepo.clear() | ||||
|         locker.withWriteLock { | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.pagination.* | ||||
| import dev.inmo.micro_utils.pagination.utils.* | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.cache.KVCache | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.flow.* | ||||
| @@ -47,9 +48,7 @@ open class ReadKeyValuesCacheRepo<Key,Value>( | ||||
|         kvCache.contains(k) | ||||
|     } || parentRepo.contains(k) | ||||
|  | ||||
|     override suspend fun invalidate() = locker.withWriteLock { | ||||
|         kvCache.clear() | ||||
|     } | ||||
|     override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) | ||||
| } | ||||
|  | ||||
| fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached( | ||||
| @@ -84,10 +83,6 @@ open class KeyValuesCacheRepo<Key,Value>( | ||||
|             kvCache.unset(it) | ||||
|         } | ||||
|     }.launchIn(scope) | ||||
|  | ||||
|     override suspend fun invalidate() = locker.withWriteLock { | ||||
|         kvCache.clear() | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun <Key, Value> KeyValuesRepo<Key, Value>.cached( | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadCRUDRepo | ||||
| import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.set | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.delay | ||||
| @@ -56,7 +57,7 @@ open class AutoRecacheReadCRUDRepo<RegisteredObject, Id>( | ||||
|     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { | ||||
|         originalRepo.getAll() | ||||
|     }.onSuccess { | ||||
|         kvCache.actualizeAll(clear = true) { it } | ||||
|         kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||
|     }.getOrElse { | ||||
|         kvCache.getAll() | ||||
|     } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo | ||||
| import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.set | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.delay | ||||
| @@ -56,7 +57,7 @@ open class AutoRecacheReadKeyValueRepo<Id, RegisteredObject>( | ||||
|     override suspend fun getAll(): Map<Id, RegisteredObject> = actionWrapper.wrap { | ||||
|         originalRepo.getAll() | ||||
|     }.onSuccess { | ||||
|         kvCache.actualizeAll(clear = true) { it } | ||||
|         kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } | ||||
|     }.getOrElse { | ||||
|         kvCache.getAll() | ||||
|     } | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import dev.inmo.micro_utils.pagination.Pagination | ||||
| import dev.inmo.micro_utils.pagination.PaginationResult | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.* | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| @@ -42,7 +43,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>( | ||||
|     ) | ||||
|  | ||||
|     protected open suspend fun actualizeAll() { | ||||
|         locker.withWriteLock { kvCache.actualizeAll(parentRepo) } | ||||
|         kvCache.actualizeAll(parentRepo, locker = locker) | ||||
|     } | ||||
|  | ||||
|     override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize( | ||||
| @@ -72,7 +73,7 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>( | ||||
|     override suspend fun getAll(): Map<IdType, ObjectType> = doOrTakeAndActualizeWithWriteLock( | ||||
|         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, | ||||
|         { getAll() }, | ||||
|         { kvCache.actualizeAll(clear = true) { it } } | ||||
|         { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } | ||||
|     ) | ||||
|  | ||||
|     override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualizeWithWriteLock( | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | ||||
| import dev.inmo.micro_utils.pagination.Pagination | ||||
| import dev.inmo.micro_utils.pagination.PaginationResult | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import dev.inmo.micro_utils.repos.pagination.getAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.flow.* | ||||
| @@ -41,10 +41,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>( | ||||
|         actualize = { locker.withWriteLock { actualize(it) } } | ||||
|     ) | ||||
|     protected open suspend fun actualizeAll() { | ||||
|         locker.withWriteLock { | ||||
|             kvCache.clear() | ||||
|             kvCache.set(parentRepo.getAll()) | ||||
|         } | ||||
|         kvCache.actualizeAll(parentRepo, locker) | ||||
|     } | ||||
|  | ||||
|     override suspend fun get(k: Key): Value? = doOrTakeAndActualizeWithWriteLock( | ||||
| @@ -74,7 +71,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>( | ||||
|     override suspend fun getAll(): Map<Key, Value> = doOrTakeAndActualizeWithWriteLock( | ||||
|         { getAll().takeIf { it.isNotEmpty() }.optionalOrAbsentIfNull }, | ||||
|         { getAll() }, | ||||
|         { kvCache.actualizeAll(clear = true) { it } } | ||||
|         { kvCache.actualizeAll(clearMode = ActualizeAllClearMode.BeforeSet) { it } } | ||||
|     ) | ||||
|  | ||||
|     override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize( | ||||
| @@ -150,9 +147,7 @@ open class FullKeyValueCacheRepo<Key,Value>( | ||||
|     override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset) | ||||
|  | ||||
|     override suspend fun invalidate() { | ||||
|         locker.withWriteLock { | ||||
|             kvCache.actualizeAll(parentRepo) | ||||
|         } | ||||
|         kvCache.actualizeAll(parentRepo, locker) | ||||
|     } | ||||
|  | ||||
|     override suspend fun clear() { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock | ||||
| import dev.inmo.micro_utils.pagination.* | ||||
| import dev.inmo.micro_utils.pagination.utils.* | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode | ||||
| import dev.inmo.micro_utils.repos.cache.util.actualizeAll | ||||
| import kotlinx.coroutines.CoroutineScope | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| @@ -41,15 +42,13 @@ open class FullReadKeyValuesCacheRepo<Key,Value>( | ||||
|     ) | ||||
|  | ||||
|     protected open suspend fun actualizeKey(k: Key) { | ||||
|         locker.withWriteLock { | ||||
|             kvCache.set(k, parentRepo.getAll(k)) | ||||
|         kvCache.actualizeAll(locker = locker, clearMode = ActualizeAllClearMode.Never) { | ||||
|             mapOf(k to parentRepo.getAll(k)) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected open suspend fun actualizeAll() { | ||||
|         locker.withWriteLock { | ||||
|             kvCache.actualizeAll(parentRepo) | ||||
|         } | ||||
|         kvCache.actualizeAll(parentRepo, locker = locker) | ||||
|     } | ||||
|  | ||||
|     override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> { | ||||
| @@ -187,9 +186,11 @@ open class FullKeyValuesCacheRepo<Key,Value>( | ||||
|     } | ||||
|  | ||||
|     override suspend fun invalidate() { | ||||
|         locker.withWriteLock { | ||||
|             kvCache.actualizeAll(parentRepo) | ||||
|         kvCache.actualizeAll(parentRepo, locker = locker) | ||||
|     } | ||||
|  | ||||
|     override suspend fun set(toSet: Map<Key, List<Value>>) { | ||||
|         super<KeyValuesRepo>.set(toSet) | ||||
|     } | ||||
|  | ||||
|     override suspend fun removeWithValue(v: Value) { | ||||
|   | ||||
| @@ -1,43 +1,169 @@ | ||||
| package dev.inmo.micro_utils.repos.cache.util | ||||
|  | ||||
| import dev.inmo.micro_utils.coroutines.SmartRWLocker | ||||
| import dev.inmo.micro_utils.coroutines.withWriteLock | ||||
| import dev.inmo.micro_utils.repos.* | ||||
| import kotlinx.serialization.Serializable | ||||
| import kotlin.js.JsName | ||||
| import kotlin.jvm.JvmName | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||
|     clear: Boolean = true, | ||||
| /** | ||||
|  * `invalidate`/`actualizeAll` clearing mode. Declare when data in original repo will be cleared | ||||
|  */ | ||||
| @Serializable | ||||
| sealed interface ActualizeAllClearMode { | ||||
|     /** | ||||
|      * Instruct user of this mode to clear internal data __before load__ of external data | ||||
|      */ | ||||
|     @Serializable | ||||
|     data object BeforeLoad : ActualizeAllClearMode | ||||
|     /** | ||||
|      * Instruct user of this mode to clear internal data __after load__ of external data and __before set__ of internal data | ||||
|      */ | ||||
|     @Serializable | ||||
|     data object BeforeSet : ActualizeAllClearMode | ||||
|     /** | ||||
|      * Instruct user of this mode to never clear internal data | ||||
|      */ | ||||
|     @Serializable | ||||
|     data object Never : ActualizeAllClearMode | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     set( | ||||
|         getAll().also { | ||||
|             if (clear) { | ||||
|     clear() | ||||
|     val newData = getAll() | ||||
|     set(newData) | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     val newData = getAll() | ||||
|     clear() | ||||
|     set(newData) | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     val newData = getAll() | ||||
|     set(newData) | ||||
| } | ||||
|  | ||||
| @JvmName("actualizeAllWithClearBeforeLoadWithLocker") | ||||
| @JsName("actualizeAllWithClearBeforeLoadWithLocker") | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||
|     locker: SmartRWLocker, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     locker.withWriteLock { | ||||
|         clear() | ||||
|     } | ||||
|  | ||||
|     val newData = getAll() | ||||
|     locker.withWriteLock { | ||||
|         set(newData) | ||||
|     } | ||||
|     ) | ||||
| } | ||||
|  | ||||
| @JvmName("actualizeAllWithClearBeforeSetWithLocker") | ||||
| @JsName("actualizeAllWithClearBeforeSetWithLocker") | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||
|     locker: SmartRWLocker, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     val newData = getAll() | ||||
|     locker.withWriteLock { | ||||
|         clear() | ||||
|         set(newData) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @JvmName("actualizeAllWithoutClearWithLocker") | ||||
| @JsName("actualizeAllWithoutClearWithLocker") | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||
|     locker: SmartRWLocker, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     val newData = getAll() | ||||
|     locker.withWriteLock { | ||||
|         set(newData) | ||||
|     } | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeLoad( | ||||
|     locker: SmartRWLocker? = null, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     locker ?.let { | ||||
|         actualizeAllWithClearBeforeLoad(locker = locker, getAll) | ||||
|     } ?: actualizeAllWithClearBeforeLoad(getAll) | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithClearBeforeSet( | ||||
|     locker: SmartRWLocker? = null, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     locker ?.let { | ||||
|         actualizeAllWithClearBeforeSet(locker = locker, getAll) | ||||
|     } ?: actualizeAllWithClearBeforeSet(getAll) | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAllWithoutClear( | ||||
|     locker: SmartRWLocker? = null, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     locker ?.let { | ||||
|         actualizeAllWithoutClear(locker = locker, getAll) | ||||
|     } ?: actualizeAllWithoutClear(getAll) | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||
|     repo: ReadKeyValueRepo<K, V>, | ||||
|     clear: Boolean = true, | ||||
|     locker: SmartRWLocker? = null, | ||||
|     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||
|     getAll: () -> Map<K, V> | ||||
| ) { | ||||
|     actualizeAll(clear) { | ||||
|         repo.getAll() | ||||
|     when (clearMode) { | ||||
|         ActualizeAllClearMode.BeforeLoad -> locker ?.let { | ||||
|             actualizeAllWithClearBeforeLoad(locker = locker, getAll) | ||||
|         } ?: actualizeAllWithClearBeforeLoad(getAll) | ||||
|         ActualizeAllClearMode.BeforeSet -> locker ?.let { | ||||
|             actualizeAllWithClearBeforeSet(locker = locker, getAll) | ||||
|         } ?: actualizeAllWithClearBeforeSet(getAll) | ||||
|         ActualizeAllClearMode.Never -> locker ?.let { | ||||
|             actualizeAllWithoutClear(locker = locker, getAll) | ||||
|         } ?: actualizeAllWithoutClear(getAll) | ||||
|     } | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||
|     parentRepo: ReadKeyValueRepo<K, V>, | ||||
|     locker: SmartRWLocker? = null, | ||||
|     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||
| ) { | ||||
|     actualizeAll(locker, clearMode) { | ||||
|         parentRepo.getAll() | ||||
|     } | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, List<V>>.actualizeAll( | ||||
|     repo: ReadKeyValuesRepo<K, V>, | ||||
|     clear: Boolean = true, | ||||
|     parentRepo: ReadKeyValuesRepo<K, V>, | ||||
|     locker: SmartRWLocker? = null, | ||||
|     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||
| ) { | ||||
|     actualizeAll(clear) { | ||||
|         repo.getAll() | ||||
|     actualizeAll(locker, clearMode) { | ||||
|         parentRepo.getAll() | ||||
|     } | ||||
| } | ||||
|  | ||||
| suspend inline fun <K, V> KeyValueRepo<K, V>.actualizeAll( | ||||
|     repo: ReadCRUDRepo<V, K>, | ||||
|     clear: Boolean = true, | ||||
|     parentRepo: ReadCRUDRepo<V, K>, | ||||
|     locker: SmartRWLocker? = null, | ||||
|     clearMode: ActualizeAllClearMode = ActualizeAllClearMode.BeforeSet, | ||||
| ) { | ||||
|     actualizeAll(clear) { | ||||
|         repo.getAll() | ||||
|     actualizeAll(locker, clearMode) { | ||||
|         parentRepo.getAll() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package dev.inmo.micro_utils.repos | ||||
|  | ||||
| import dev.inmo.micro_utils.common.diff | ||||
| import dev.inmo.micro_utils.pagination.* | ||||
| import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging | ||||
| import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging | ||||
| @@ -130,6 +131,14 @@ interface KeyValuesRepo<Key, Value> : ReadKeyValuesRepo<Key, Value>, WriteKeyVal | ||||
|  | ||||
|         remove(toRemove) | ||||
|     } | ||||
|  | ||||
|     override suspend fun set(toSet: Map<Key, List<Value>>) { | ||||
|         toSet.forEach { (k, v) -> | ||||
|             val diff = getAll(k).diff(v) | ||||
|             remove(k, diff.removed.map { it.value }) | ||||
|             add(k, diff.added.map { it.value }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| typealias OneToManyKeyValueRepo<Key,Value> = KeyValuesRepo<Key, Value> | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package dev.inmo.micro_utils.repos.exposed.keyvalue | ||||
|  | ||||
| import dev.inmo.micro_utils.repos.KeyValueRepo | ||||
| import kotlinx.coroutines.channels.BufferOverflow | ||||
| import kotlinx.coroutines.flow.* | ||||
| import org.jetbrains.exposed.sql.* | ||||
| import org.jetbrains.exposed.sql.statements.* | ||||
| @@ -8,13 +9,15 @@ import org.jetbrains.exposed.sql.transactions.transaction | ||||
|  | ||||
| abstract class AbstractExposedKeyValueRepo<Key, Value>( | ||||
|     override val database: Database, | ||||
|     tableName: String? = null | ||||
|     tableName: String? = null, | ||||
|     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||
|     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||
| ) : KeyValueRepo<Key, Value>, AbstractExposedReadKeyValueRepo<Key, Value>( | ||||
|     database, | ||||
|     tableName | ||||
| ) { | ||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>() | ||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>() | ||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|  | ||||
|     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() | ||||
|     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue | ||||
|  | ||||
| import dev.inmo.micro_utils.repos.KeyValueRepo | ||||
| import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | ||||
| import kotlinx.coroutines.channels.BufferOverflow | ||||
| import kotlinx.coroutines.flow.* | ||||
| import org.jetbrains.exposed.sql.* | ||||
| import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | ||||
| @@ -13,15 +14,17 @@ open class ExposedKeyValueRepo<Key, Value>( | ||||
|     database: Database, | ||||
|     keyColumnAllocator: ColumnAllocator<Key>, | ||||
|     valueColumnAllocator: ColumnAllocator<Value>, | ||||
|     tableName: String? = null | ||||
|     tableName: String? = null, | ||||
|     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||
|     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||
| ) : KeyValueRepo<Key, Value>, ExposedReadKeyValueRepo<Key, Value>( | ||||
|     database, | ||||
|     keyColumnAllocator, | ||||
|     valueColumnAllocator, | ||||
|     tableName | ||||
| ) { | ||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>() | ||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>() | ||||
|     protected val _onNewValue = MutableSharedFlow<Pair<Key, Value>>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     protected val _onValueRemoved = MutableSharedFlow<Key>(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|  | ||||
|     override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow() | ||||
|     override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow() | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package dev.inmo.micro_utils.repos.exposed.onetomany | ||||
|  | ||||
| import dev.inmo.micro_utils.repos.KeyValuesRepo | ||||
| import kotlinx.coroutines.channels.BufferOverflow | ||||
| import kotlinx.coroutines.flow.* | ||||
| import org.jetbrains.exposed.sql.* | ||||
| import org.jetbrains.exposed.sql.statements.InsertStatement | ||||
| @@ -8,18 +9,20 @@ import org.jetbrains.exposed.sql.transactions.transaction | ||||
|  | ||||
| abstract class AbstractExposedKeyValuesRepo<Key, Value>( | ||||
|     override val database: Database, | ||||
|     tableName: String? = null | ||||
|     tableName: String? = null, | ||||
|     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||
|     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||
| ) : KeyValuesRepo<Key, Value>, AbstractExposedReadKeyValuesRepo<Key, Value>( | ||||
|     database, | ||||
|     tableName | ||||
| ) { | ||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() | ||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onNewValue: Flow<Pair<Key, Value>> | ||||
|         get() = _onNewValue.asSharedFlow() | ||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() | ||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onValueRemoved: Flow<Pair<Key, Value>> | ||||
|         get() = _onValueRemoved.asSharedFlow() | ||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow() | ||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onDataCleared: Flow<Key> | ||||
|         get() = _onDataCleared.asSharedFlow() | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.exposed.onetomany | ||||
|  | ||||
| import dev.inmo.micro_utils.repos.KeyValuesRepo | ||||
| import dev.inmo.micro_utils.repos.exposed.ColumnAllocator | ||||
| import kotlinx.coroutines.channels.BufferOverflow | ||||
| import kotlinx.coroutines.flow.* | ||||
| import org.jetbrains.exposed.sql.* | ||||
| import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq | ||||
| @@ -13,20 +14,22 @@ open class ExposedKeyValuesRepo<Key, Value>( | ||||
|     database: Database, | ||||
|     keyColumnAllocator: ColumnAllocator<Key>, | ||||
|     valueColumnAllocator: ColumnAllocator<Value>, | ||||
|     tableName: String? = null | ||||
|     tableName: String? = null, | ||||
|     flowsExtraBufferCapacity: Int = Int.MAX_VALUE, | ||||
|     flowsBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND | ||||
| ) : KeyValuesRepo<Key, Value>, ExposedReadKeyValuesRepo<Key, Value>( | ||||
|     database, | ||||
|     keyColumnAllocator, | ||||
|     valueColumnAllocator, | ||||
|     tableName | ||||
| ) { | ||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() | ||||
|     protected val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onNewValue: Flow<Pair<Key, Value>> | ||||
|         get() = _onNewValue | ||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() | ||||
|     protected val _onValueRemoved: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onValueRemoved: Flow<Pair<Key, Value>> | ||||
|         get() = _onValueRemoved | ||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow() | ||||
|     protected val _onDataCleared: MutableSharedFlow<Key> = MutableSharedFlow(extraBufferCapacity = flowsExtraBufferCapacity, onBufferOverflow = flowsBufferOverflow) | ||||
|     override val onDataCleared: Flow<Key> | ||||
|         get() = _onDataCleared | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| package dev.inmo.micro_utils.repos.generator | ||||
|  | ||||
| import com.google.devtools.ksp.KspExperimental | ||||
| import com.google.devtools.ksp.getAnnotationsByType | ||||
| import com.google.devtools.ksp.isAnnotationPresent | ||||
| import com.google.devtools.ksp.* | ||||
| import com.google.devtools.ksp.processing.CodeGenerator | ||||
| import com.google.devtools.ksp.processing.Resolver | ||||
| import com.google.devtools.ksp.processing.SymbolProcessor | ||||
| @@ -36,6 +34,7 @@ import kotlinx.serialization.Serializable | ||||
| import java.io.File | ||||
| import kotlin.reflect.KProperty1 | ||||
| import kotlin.reflect.full.memberProperties | ||||
| import kotlin.reflect.jvm.jvmName | ||||
|  | ||||
| private fun KSClassifierReference.quilifiedName(): String = "${qualifier ?.let { "${it.quilifiedName()}." } ?: ""}${referencedName()}" | ||||
|  | ||||
| @@ -75,16 +74,29 @@ class Processor( | ||||
|                         ORIGINAL FILE: ${ksFile.fileName} | ||||
|                     """.trimIndent() | ||||
|                     ) | ||||
|  | ||||
|                     val newName = "New${ksClassDeclaration.simpleName.getShortName()}" | ||||
|                     val registeredName = "Registered${ksClassDeclaration.simpleName.getShortName()}" | ||||
|  | ||||
|                     val allKSClassProperties = ksClassDeclaration.getAllProperties() | ||||
|                     val excludedKSClassProperties = allKSClassProperties.filter { | ||||
|                         it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) | ||||
|                     val excludedKSClassProperties = allKSClassProperties.filter { property -> | ||||
|                         property.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) || (property.findOverridee() ?.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) == true) | ||||
|                     } | ||||
|                     val excludedKSClassPropertiesNames = excludedKSClassProperties.map { it.simpleName.asString() } | ||||
|                     val ksClassProperties = allKSClassProperties.filter { | ||||
|                         it !in excludedKSClassProperties | ||||
|                     }.groupBy { it.simpleName.asString() }.map { | ||||
|                         var current = it.value.first() | ||||
|                         var currentType = current.type.resolve() | ||||
|                         it.value.forEach { | ||||
|                             val type = it.type.resolve() | ||||
|  | ||||
|                             if (currentType.isAssignableFrom(type) && !type.isAssignableFrom(currentType)) { | ||||
|                                 current = it | ||||
|                                 currentType = type | ||||
|                             } | ||||
|                         } | ||||
|                         current | ||||
|                     } | ||||
|                     val ksClassPropertiesNames = ksClassProperties.map { it.simpleName.asString() } | ||||
|                     val newNewType = TypeSpec.classBuilder(newName).apply { | ||||
| @@ -99,17 +111,20 @@ class Processor( | ||||
|                         } | ||||
|                         primaryConstructor( | ||||
|                             FunSpec.constructorBuilder().apply { | ||||
|                                 val withoutDefaults = mutableListOf<Pair<ParameterSpec.Builder, PropertySpec.Builder>>() | ||||
|                                 ksClassProperties.forEach { | ||||
|                                     addParameter( | ||||
|                                         ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply { | ||||
|                                             annotations += it.annotations.map { it.toAnnotationSpec() } | ||||
|                                         }.build() | ||||
|                                     ) | ||||
|                                     typeBuilder.addProperty( | ||||
|                                         PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { | ||||
|                                     val property = PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { | ||||
|                                         initializer(it.simpleName.getShortName()) | ||||
|                                         }.build() | ||||
|                                     ) | ||||
|                                     } | ||||
|                                     ParameterSpec.builder(it.simpleName.getShortName(), it.type.toTypeName()).apply { | ||||
|                                         withoutDefaults.add(this to property) | ||||
|                                         annotations += it.annotations.map { it.toAnnotationSpec() } | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
|                                 withoutDefaults.forEach { | ||||
|                                     addParameter(it.first.build()) | ||||
|                                     addProperty(it.second.build()) | ||||
|                                 } | ||||
|                             }.build() | ||||
|                         ) | ||||
| @@ -125,14 +140,25 @@ class Processor( | ||||
|                         (it.arguments.first().value as List<KSType>).map { it.declaration as KSClassDeclaration } | ||||
|                     }.toList() | ||||
|  | ||||
|  | ||||
|                     val registeredTypesProperties: List<KSPropertyDeclaration> = registeredSupertypes.flatMap { registeredType -> | ||||
|                         registeredType.getAllProperties() | ||||
|                     }.filter { | ||||
|                         it.simpleName.asString() !in excludedKSClassPropertiesNames && it.getAnnotationsByType(GenerateCRUDModelExcludeOverride::class).none() | ||||
|                         it.simpleName.asString() !in excludedKSClassPropertiesNames && !it.isAnnotationPresent(GenerateCRUDModelExcludeOverride::class) | ||||
|                     } | ||||
|                     val allProperties: List<KSPropertyDeclaration> = ksClassProperties.toList() + registeredTypesProperties | ||||
|                     val propertiesToOverrideInRegistered = allProperties.distinctBy { it.simpleName.asString() }.sortedBy { property -> | ||||
|                     val allProperties: List<KSPropertyDeclaration> = registeredTypesProperties + ksClassProperties.toList() | ||||
|                     val propertiesToOverrideInRegistered = allProperties.groupBy { it.simpleName.asString() }.map { | ||||
|                         var current = it.value.first() | ||||
|                         var currentType = current.type.resolve() | ||||
|                         it.value.forEach { | ||||
|                             val type = it.type.resolve() | ||||
|  | ||||
|                             if (currentType.isAssignableFrom(type) && !type.isAssignableFrom(currentType)) { | ||||
|                                 current = it | ||||
|                                 currentType = type | ||||
|                             } | ||||
|                         } | ||||
|                         current | ||||
|                     }.sortedBy { property -> | ||||
|                         val name = property.simpleName.asString() | ||||
|  | ||||
|                         ksClassPropertiesNames.indexOf(name).takeIf { it > -1 } ?.let { | ||||
| @@ -156,17 +182,20 @@ class Processor( | ||||
|                         addModifiers(KModifier.DATA) | ||||
|                         primaryConstructor( | ||||
|                             FunSpec.constructorBuilder().apply { | ||||
|                                 val withoutDefaults = mutableListOf<Pair<ParameterSpec.Builder, PropertySpec.Builder>>() | ||||
|                                 propertiesToOverrideInRegistered.forEach { | ||||
|                                     addParameter( | ||||
|                                         ParameterSpec.builder(it.simpleName.getShortName(), it.typeName).apply { | ||||
|                                             annotations += it.annotations.map { it.toAnnotationSpec() } | ||||
|                                         }.build() | ||||
|                                     ) | ||||
|                                     typeBuilder.addProperty( | ||||
|                                         PropertySpec.builder(it.simpleName.getShortName(), it.typeName, KModifier.OVERRIDE).apply { | ||||
|                                     val property = PropertySpec.builder(it.simpleName.getShortName(), it.type.toTypeName(), KModifier.OVERRIDE).apply { | ||||
|                                         initializer(it.simpleName.getShortName()) | ||||
|                                         }.build() | ||||
|                                     ) | ||||
|                                     } | ||||
|                                     ParameterSpec.builder(it.simpleName.getShortName(), it.type.toTypeName()).apply { | ||||
|                                         withoutDefaults.add(this to property) | ||||
|                                         annotations += it.annotations.map { it.toAnnotationSpec() } | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
|                                 withoutDefaults.forEach { | ||||
|                                     addParameter(it.first.build()) | ||||
|                                     addProperty(it.second.build()) | ||||
|                                 } | ||||
|                             }.build() | ||||
|                         ) | ||||
| @@ -191,7 +220,7 @@ class Processor( | ||||
|                         FunSpec.builder("asRegistered").apply { | ||||
|                             receiver(ksClassDeclaration.toClassName()) | ||||
|                             (registeredTypesProperties.filter { it.simpleName.asString() !in ksClassPropertiesNames }).forEach { | ||||
|                                 addParameter(it.simpleName.asString(), it.typeName) | ||||
|                                 addParameter(it.simpleName.asString(), it.type.toTypeName()) | ||||
|                             } | ||||
|                             addCode( | ||||
|                                 CodeBlock.of( | ||||
|   | ||||
| @@ -14,6 +14,7 @@ public data class NewTest( | ||||
|   override val property1: String, | ||||
|   override val property2: Int, | ||||
|   @Serializable | ||||
|   @SerialName(`value` = "custom_parent_name") | ||||
|   override val parent: ParentTypeId?, | ||||
| ) : Test | ||||
|  | ||||
| @@ -24,6 +25,7 @@ public data class RegisteredTest( | ||||
|   override val property1: String, | ||||
|   override val property2: Int, | ||||
|   @Serializable | ||||
|   @SerialName(`value` = "custom_parent_name") | ||||
|   override val parent: ParentTypeId?, | ||||
| ) : Test, IRegisteredTest | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.generator.test | ||||
|  | ||||
| import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModel | ||||
| import dev.inmo.micro_utils.repos.annotations.GenerateCRUDModelExcludeOverride | ||||
| import kotlinx.serialization.SerialName | ||||
| import kotlinx.serialization.Serializable | ||||
| import kotlin.jvm.JvmInline | ||||
|  | ||||
| @@ -18,6 +19,7 @@ sealed interface Test { | ||||
|     val property1: String | ||||
|     val property2: Int | ||||
|     @Serializable | ||||
|     @SerialName("custom_parent_name") | ||||
|     val parent: ParentTypeId? | ||||
|  | ||||
|     @GenerateCRUDModelExcludeOverride | ||||
|   | ||||
		Reference in New Issue
	
	Block a user