Compare commits

...

31 Commits
0.2.0 ... 0.2.3

Author SHA1 Message Date
5b325a8ff9 add dokka 2020-10-28 14:47:12 +06:00
4582e0c817 small refactoring of BroadcastStateFlow 2020-10-28 14:19:57 +06:00
e2d1c5d6a1 corotoutines actualization 2020-10-28 14:17:39 +06:00
4019ad7d31 update exposed and coroutines versions 2020-10-28 13:58:23 +06:00
e7df21e91a common js visibility and on screen extensions 2020-10-28 13:57:24 +06:00
b2e30c9f6d start 0.2.3 2020-10-28 13:55:49 +06:00
0b27b5cc06 Revert "start add recycler view"
This reverts commit 347e9c32fe.
2020-10-28 13:51:24 +06:00
347e9c32fe start add recycler view 2020-10-28 13:51:16 +06:00
cc18f58e4c Merge pull request #6 from InsanusMokrassar/0.2.2
0.2.2
2020-10-25 22:26:18 +06:00
dbd2e963a1 change order of functions in read one to many interface 2020-10-25 22:23:24 +06:00
6928ca5329 optimize imports 2020-10-25 22:21:54 +06:00
9ece160aa8 add extensions for onetomany functions 2020-10-25 22:21:23 +06:00
6115c1bcac add extensions for OneToManyKeyValueRepo 2020-10-25 22:08:42 +06:00
e026e94cbf start 0.2.2 2020-10-25 21:52:36 +06:00
56cdd8d6af remove fixing of last index due to solving that pages size must be saved in reversing of pagination 2020-10-22 18:50:17 +06:00
899e6760e1 fix for lastIndex in reversing of pagination 2020-10-22 18:48:05 +06:00
864d0ffcc6 hope last fix 2020-10-22 18:37:56 +06:00
c6f417f8c8 fixes in pagination 2020-10-22 17:57:27 +06:00
9091fa5bd8 Merge pull request #4 from InsanusMokrassar/0.2.1
0.2.1
2020-10-22 15:50:30 +06:00
418af7874d update repos to use new reverse method 2020-10-22 15:47:28 +06:00
4972cc9daa several additions and tests for pagination reversing 2020-10-22 15:41:21 +06:00
ff905e1491 fixes in reverse extension 2020-10-22 14:54:27 +06:00
64b0184a17 Pagination#reverse 2020-10-22 14:39:39 +06:00
97cbe44fb5 start 0.2.1 2020-10-22 14:38:53 +06:00
452d8778c5 update changelog 2020-10-17 18:53:20 +06:00
02ad1a748e fix table name parameter in keyvalue and onetomany repos 2020-10-17 18:51:48 +06:00
c5a32e2b1b Merge pull request #3 from InsanusMokrassar/0.2.0
0.2.0
2020-10-17 18:09:36 +06:00
702300f761 Update github_release.gradle 2020-10-16 21:39:52 +06:00
efcaa08b70 Update github_release.gradle 2020-10-16 21:38:31 +06:00
7f7369b3a8 Update and rename changelog_info_retriever to changelog_parser.sh 2020-10-16 21:37:24 +06:00
45a9a95888 Update github_release.gradle 2020-10-16 21:36:01 +06:00
24 changed files with 474 additions and 94 deletions

View File

@@ -1,5 +1,34 @@
# Changelog
## 0.2.3
* `Versions`
* `Coroutines`: `1.3.9` -> `1.4.0`
* `Exposed`: `0.27.1` -> `0.28.1`
* `Common`
* `K/JS`
* Add several extensions for `Element` objects to detect that object is on screen viewport
* Add several extensions for `Element` objects to detect object visibility
* `Coroutines`
* `BroadcastStateFlow` now use different strategy for getting of state and implements `replayCache`
## 0.2.2
* `Repos`
* `Common`
* Several new methods `ReadOneToManyKeyValueRepo#getAll`
* Several new method `WriteOneToManyKeyValueRepo#add` and several extensions
* Several new method `WriteOneToManyKeyValueRepo#remove` and several extensions
## 0.2.1
* `Pagination`
* `Common`:
* Extension `Pagination#reverse` has been added
* Factory `PaginationByIndexes`
* Shortcut `calculatePagesNumber` with reversed parameters
* Value `emptyPagination` for empty `SimplePagination` cases
## 0.2.0
* `Repos`
@@ -10,6 +39,7 @@
* `ExposedCRUDRepo` now extends `ExposedRepo` instead of simple `Repo`
* New extension `initTable` for classes which are `Table` and `ExposedRepo` at the same time
* `KeyValue`:
* `tableName` parameter
* Class `AbstractExposedReadKeyValueRepo`
* Renamed to `ExposedReadKeyValueRepo`
* Changed incoming types to `ColumnAllocator`
@@ -20,6 +50,7 @@
* Changed incoming types to `ColumnAllocator`
* `open` instead of `abstract`
* `OneToMany`:
* `tableName` parameter
* Class `AbstractExposedReadOneToManyKeyValueRepo`
* Renamed to `ExposedReadOneToManyKeyValueRepo`
* Changed incoming arguments order

View File

@@ -1,24 +0,0 @@
#!/bin/bash
function parse() {
version=$1
while IFS= read -r line && [ -z "`echo $line | grep -e "^#\+ $version"`" ]
do
: # do nothing
done
while IFS= read -r line && [ -z "`echo $line | grep -e "^#\+"`" ]
do
echo "$line"
done
}
version=$1
file=$2
if [ -n "$file" ]; then
parse $version < "$file"
else
parse $version
fi

24
changelog_parser.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
function parse() {
version="$1"
while IFS= read -r line && [ -z "`echo "$line" | grep -e "^#\+ $version"`" ]
do
: # do nothing
done
while IFS= read -r line && [ -z "`echo "$line" | grep -e "^#\+"`" ]
do
echo "$line"
done
}
version="$1"
file="$2"
if [ -n "$file" ]; then
parse "$version" < "$file"
else
parse "$version"
fi

View File

@@ -0,0 +1,43 @@
package dev.inmo.micro_utils.common
import kotlinx.browser.window
import org.w3c.dom.DOMRect
import org.w3c.dom.Element
val DOMRect.isOnScreenByLeftEdge: Boolean
get() = left >= 0 && left <= window.innerWidth
inline val Element.isOnScreenByLeftEdge
get() = getBoundingClientRect().isOnScreenByLeftEdge
val DOMRect.isOnScreenByRightEdge: Boolean
get() = right >= 0 && right <= window.innerWidth
inline val Element.isOnScreenByRightEdge
get() = getBoundingClientRect().isOnScreenByRightEdge
internal val DOMRect.isOnScreenHorizontally: Boolean
get() = isOnScreenByLeftEdge || isOnScreenByRightEdge
val DOMRect.isOnScreenByTopEdge: Boolean
get() = top >= 0 && top <= window.innerHeight
inline val Element.isOnScreenByTopEdge
get() = getBoundingClientRect().isOnScreenByTopEdge
val DOMRect.isOnScreenByBottomEdge: Boolean
get() = bottom >= 0 && bottom <= window.innerHeight
inline val Element.isOnScreenByBottomEdge
get() = getBoundingClientRect().isOnScreenByBottomEdge
internal val DOMRect.isOnScreenVertically: Boolean
get() = isOnScreenByLeftEdge || isOnScreenByRightEdge
val DOMRect.isOnScreenFully: Boolean
get() = isOnScreenByLeftEdge && isOnScreenByTopEdge && isOnScreenByRightEdge && isOnScreenByBottomEdge
val Element.isOnScreenFully: Boolean
get() = getBoundingClientRect().isOnScreenFully
val DOMRect.isOnScreen: Boolean
get() = isOnScreenFully || (isOnScreenHorizontally && isOnScreenVertically)
inline val Element.isOnScreen: Boolean
get() = getBoundingClientRect().isOnScreen

View File

@@ -0,0 +1,48 @@
package dev.inmo.micro_utils.common
import kotlinx.browser.window
import org.w3c.dom.Element
import org.w3c.dom.css.CSSStyleDeclaration
sealed class Visibility
object Visible : Visibility()
object Invisible : Visibility()
object Gone : Visibility()
var CSSStyleDeclaration.visibilityState: Visibility
get() = when {
display == "none" -> Gone
visibility == "hidden" -> Invisible
else -> Visible
}
set(value) {
when (value) {
Visible -> {
if (display == "none") {
display = "initial"
}
visibility = "visible"
}
Invisible -> {
if (display == "none") {
display = "initial"
}
visibility = "hidden"
}
Gone -> {
display = "none"
}
}
}
inline var Element.visibilityState: Visibility
get() = window.getComputedStyle(this).visibilityState
set(value) {
window.getComputedStyle(this).visibilityState = value
}
inline val Element.isVisible: Boolean
get() = visibilityState == Visible
inline val Element.isInvisible: Boolean
get() = visibilityState == Invisible
inline val Element.isGone: Boolean
get() = visibilityState == Gone

View File

@@ -5,29 +5,59 @@ import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
const val defaultBroadcastStateFlowReplayCacheSize = 1
class BroadcastStateFlow<T> internal constructor(
parentFlow: Flow<T>,
private val stateGetter: () -> T
initial: T,
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize,
replayScope: CoroutineScope
) : StateFlow<T>, Flow<T> by parentFlow {
private val deque = ArrayDeque<T>(1).also {
it.add(initial)
}
override val replayCache: List<T>
get() = deque.toList()
override val value: T
get() = stateGetter()
}
get() = deque.last()
fun <T> BroadcastChannel<T>.asStateFlow(value: T, scope: CoroutineScope): StateFlow<T> = asFlow().let {
var state: T = value
it.onEach { state = it }.launchIn(scope)
BroadcastStateFlow(it) {
state
init {
if (replayCacheSize < 1) {
error("Replay cache size can't be less than 1, but was $replayCacheSize")
}
parentFlow.onEach {
deque.addLast(it)
if (deque.size > replayCacheSize) {
deque.removeFirst()
}
}.launchIn(replayScope)
}
}
fun <T> BroadcastChannel<T?>.asStateFlow(scope: CoroutineScope): StateFlow<T?> = asStateFlow(null, scope)
fun <T> BroadcastChannel<T>.asStateFlow(
value: T,
scope: CoroutineScope,
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
): StateFlow<T> = BroadcastStateFlow(asFlow(), value, replayCacheSize, scope)
fun <T> broadcastStateFlow(initial: T, scope: CoroutineScope, channelSize: Int = Channel.BUFFERED) = BroadcastChannel<T>(
fun <T> BroadcastChannel<T?>.asStateFlow(
scope: CoroutineScope,
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
): StateFlow<T?> = asStateFlow(null, scope, replayCacheSize)
fun <T> broadcastStateFlow(
initial: T, scope: CoroutineScope,
channelSize: Int = Channel.BUFFERED,
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
) = BroadcastChannel<T>(
channelSize
).let {
it to it.asStateFlow(initial, scope)
it to it.asStateFlow(initial, scope, replayCacheSize)
}
fun <T> broadcastStateFlow(scope: CoroutineScope, channelSize: Int = Channel.BUFFERED) = broadcastStateFlow<T?>(null, scope, channelSize)
fun <T> broadcastStateFlow(
scope: CoroutineScope,
channelSize: Int = Channel.BUFFERED,
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
) = broadcastStateFlow<T?>(null, scope, channelSize, replayCacheSize)

88
dokka/build.gradle Normal file
View File

@@ -0,0 +1,88 @@
buildscript {
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
}
}
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka" version "$dokka_version"
}
repositories {
mavenLocal()
jcenter()
mavenCentral()
}
kotlin {
jvm()
js(BOTH) {
browser()
nodejs()
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
project.parent.subprojects.forEach {
if (
it != project
&& it.hasProperty("kotlin")
&& it.kotlin.sourceSets.any { it.name.contains("commonMain") }
) {
api it
}
}
}
}
}
}
private List<SourceDirectorySet> findSourcesWithName(String... approximateNames) {
return parent.subprojects
.findAll { it != project && it.hasProperty("kotlin") }
.collectMany { it.kotlin.sourceSets }
.findAll { sourceSet ->
approximateNames.any { nameToFilter ->
sourceSet.name.contains(nameToFilter)
}
}.collect { it.kotlin }
}
tasks.dokkaHtml {
dokkaSourceSets {
configureEach {
skipDeprecated.set(true)
sourceLink {
localDirectory.set(file("./"))
remoteUrl.set(new URL("https://github.com/InsanusMokrassar/MicroUtils/blob/master/"))
remoteLineSuffix.set("#L")
}
}
named("commonMain") {
sourceRoots.setFrom(findSourcesWithName("commonMain"))
}
named("jsMain") {
sourceRoots.setFrom(findSourcesWithName("jsMain", "commonMain"))
}
named("jvmMain") {
sourceRoots.setFrom(findSourcesWithName("jvmMain", "commonMain"))
}
}
}

3
dokka/gradle.properties Normal file
View File

@@ -0,0 +1,3 @@
dokka_version=1.4.0
org.gradle.jvmargs=-Xmx1024m

View File

@@ -1,8 +1,11 @@
private String getCurrentVersionChangelog() {
OutputStream changelogDataOS = new ByteArrayOutputStream()
exec {
commandLine 'chmod', "+x", './changelog_parser.sh'
}
exec {
standardOutput = changelogDataOS
commandLine './changelog_info_retriever', "$library_version", 'CHANGELOG.md'
commandLine './changelog_parser.sh', "${project.version}", 'CHANGELOG.md'
}
return changelogDataOS.toString().trim()
@@ -18,9 +21,9 @@ if (new File(projectDir, "secret.gradle").exists()) {
owner "InsanusMokrassar"
repo "MicroUtils"
tagName "$library_version"
releaseName "$library_version"
targetCommitish "$library_version"
tagName "${project.version}"
releaseName "${project.version}"
targetCommitish "${project.version}"
body getCurrentVersionChangelog()
}

View File

@@ -5,9 +5,9 @@ kotlin.incremental=true
kotlin.incremental.js=true
kotlin_version=1.4.10
kotlin_coroutines_version=1.3.9
kotlin_coroutines_version=1.4.0
kotlin_serialisation_core_version=1.0.0
kotlin_exposed_version=0.27.1
kotlin_exposed_version=0.28.1
ktor_version=1.4.1
@@ -19,4 +19,4 @@ github_release_plugin_version=2.2.12
uuidVersion=0.2.2
group=dev.inmo
version=0.2.0
version=0.2.3

View File

@@ -43,6 +43,11 @@ val Pagination.lastIndex: Int
fun calculatePagesNumber(datasetSize: Long, pageSize: Int): Int {
return ceil(datasetSize.toDouble() / pageSize).toInt()
}
/**
* Calculates pages count for given [datasetSize]. As a fact, it is shortcut for [calculatePagesNumber]
* @return calculated page number which can be correctly used in [PaginationResult] as [PaginationResult.page] value
*/
fun calculatePagesNumber(pageSize: Int, datasetSize: Long): Int = calculatePagesNumber(datasetSize, pageSize)
/**
* Calculates pages count for given [datasetSize]
*/

View File

@@ -14,6 +14,8 @@ inline fun FirstPagePagination(size: Int = defaultMediumPageSize) =
size = size
)
val emptyPagination = Pagination(0, 0)
@Suppress("NOTHING_TO_INLINE")
inline fun Pagination.nextPage() =
SimplePagination(
@@ -27,7 +29,21 @@ data class SimplePagination(
override val size: Int
) : Pagination
/**
* Factory for [SimplePagination]
*/
fun Pagination(
page: Int,
size: Int
) = SimplePagination(page, size)
/**
* @param firstIndex Inclusive first index of pagination
* @param lastIndex INCLUSIVE last index of pagination (last index of object covered by result [SimplePagination])
*/
fun PaginationByIndexes(
firstIndex: Int,
lastIndex: Int
) = maxOf(0, (lastIndex - firstIndex + 1)).let { size ->
Pagination(calculatePage(firstIndex, size), size)
}

View File

@@ -0,0 +1,28 @@
package dev.inmo.micro_utils.pagination.utils
import dev.inmo.micro_utils.pagination.*
/**
* Example:
*
* * `|__f__l_______________________|` will be transformed to `|_______________________f__l__|`
* * `|__f__l_|` will be transformed to `|__f__l_|`
*
* @return Reversed version of this [Pagination]
*/
fun Pagination.reverse(datasetSize: Long): SimplePagination {
val pagesNumber = calculatePagesNumber(size, datasetSize)
val newPage = pagesNumber - page - 1
return when {
page < 0 || page >= pagesNumber -> emptyPagination
else -> Pagination(
newPage,
size
)
}
}
/**
* Shortcut for [reverse]
*/
fun Pagination.reverse(objectsCount: Int) = reverse(objectsCount.toLong())

View File

@@ -0,0 +1,24 @@
package dev.inmo.micro_utils.pagination.utils
import dev.inmo.micro_utils.pagination.*
import kotlin.test.Test
import kotlin.test.assertEquals
class PaginationReversingTests {
@Test
fun testThatCommonCaseWorksOk() {
val pageSize = 3
val collectionSize = 9
assertEquals(Pagination(-1, pageSize).reverse(collectionSize), Pagination(0, 0))
val middleFirstIndex = collectionSize / 2 - pageSize / 2
val middleLastIndex = middleFirstIndex + pageSize - 1
assertEquals(
PaginationByIndexes(middleFirstIndex, middleLastIndex).reverse(collectionSize),
PaginationByIndexes(middleFirstIndex, middleLastIndex)
)
assertEquals(Pagination(calculatePagesNumber(collectionSize, pageSize), pageSize).reverse(collectionSize), Pagination(0, 0))
}
}

View File

@@ -1,7 +1,6 @@
package dev.inmo.micro_utils.repos
import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.pagination.*
import kotlinx.coroutines.flow.Flow
interface ReadOneToManyKeyValueRepo<Key, Value> : Repo {
@@ -11,6 +10,30 @@ interface ReadOneToManyKeyValueRepo<Key, Value> : Repo {
suspend fun contains(k: Key, v: Value): Boolean
suspend fun count(k: Key): Long
suspend fun count(): Long
suspend fun getAll(k: Key, reversed: Boolean = false): List<Value> = mutableListOf<Value>().also { list ->
doWithPagination {
get(k, it).also {
list.addAll(it.results)
}.nextPageIfNotEmpty()
}
if (reversed) {
list.reverse()
}
}
/**
* WARNING!!! THIS METHOD PROBABLY IS NOT EFFICIENT, USE WITH CAUTION
*/
suspend fun getAll(reverseLists: Boolean = false): Map<Key, List<Value>> = mutableMapOf<Key, List<Value>>().also { map ->
doWithPagination {
keys(it).also { paginationResult ->
paginationResult.results.forEach { k ->
map[k] = getAll(k, reverseLists)
}
}.nextPageIfNotEmpty()
}
}
}
@Deprecated("Renamed", ReplaceWith("ReadOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo"))
typealias OneToManyReadKeyValueRepo<Key, Value> = ReadOneToManyKeyValueRepo<Key, Value>
@@ -20,11 +43,51 @@ interface WriteOneToManyKeyValueRepo<Key, Value> : Repo {
val onValueRemoved: Flow<Pair<Key, Value>>
val onDataCleared: Flow<Key>
suspend fun add(toAdd: Map<Key, List<Value>>) = toAdd.forEach { (k, values) ->
values.forEach { v ->
add(k, v)
}
}
@Deprecated("Will be extracted as extension for other add method")
suspend fun add(k: Key, v: Value)
suspend fun remove(toRemove: Map<Key, List<Value>>) = toRemove.forEach { (k, values) ->
values.forEach { v ->
remove(k, v)
}
}
@Deprecated("Will be extracted as extension for other remove method")
suspend fun remove(k: Key, v: Value)
suspend fun clear(k: Key)
}
@Deprecated("Renamed", ReplaceWith("WriteOneToManyKeyValueRepo", "dev.inmo.micro_utils.repos.WriteOneToManyKeyValueRepo"))
typealias OneToManyWriteKeyValueRepo<Key, Value> = WriteOneToManyKeyValueRepo<Key, Value>
interface OneToManyKeyValueRepo<Key, Value> : ReadOneToManyKeyValueRepo<Key, Value>, WriteOneToManyKeyValueRepo<Key, Value>
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.add(
k: Key,
vararg v: Value
) = add(mapOf(k to v.toList()))
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.add(
keysAndValues: List<Pair<Key, List<Value>>>
) = add(keysAndValues.toMap())
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.add(
vararg keysAndValues: Pair<Key, List<Value>>
) = add(keysAndValues.toMap())
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.remove(
k: Key,
vararg v: Value
) = remove(mapOf(k to v.toList()))
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.remove(
keysAndValues: List<Pair<Key, List<Value>>>
) = remove(keysAndValues.toMap())
suspend inline fun <Key, Value, REPO : WriteOneToManyKeyValueRepo<Key, Value>> REPO.remove(
vararg keysAndValues: Pair<Key, List<Value>>
) = remove(keysAndValues.toMap())

View File

@@ -1,7 +1,7 @@
package dev.inmo.micro_utils.repos.pagination
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ReadStandardKeyValueRepo
suspend inline fun <Key, Value, REPO : ReadStandardKeyValueRepo<Key, Value>> REPO.doForAll(
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")

View File

@@ -1,7 +1,7 @@
package dev.inmo.micro_utils.repos.pagination
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.ReadOneToManyKeyValueRepo
suspend inline fun <Key, Value, REPO : ReadOneToManyKeyValueRepo<Key, Value>> REPO.doForAll(
@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE")

View File

@@ -12,11 +12,13 @@ import org.jetbrains.exposed.sql.transactions.transaction
open class ExposedKeyValueRepo<Key, Value>(
database: Database,
keyColumnAllocator: ColumnAllocator<Key>,
valueColumnAllocator: ColumnAllocator<Value>
valueColumnAllocator: ColumnAllocator<Value>,
tableName: String? = null
) : StandardKeyValueRepo<Key, Value>, ExposedReadKeyValueRepo<Key, Value>(
database,
keyColumnAllocator,
valueColumnAllocator
valueColumnAllocator,
tableName
) {
private val onNewValueChannel = BroadcastChannel<Pair<Key, Value>>(Channel.BUFFERED)
private val onValueRemovedChannel = BroadcastChannel<Key>(Channel.BUFFERED)
@@ -24,8 +26,6 @@ open class ExposedKeyValueRepo<Key, Value>(
override val onNewValue: Flow<Pair<Key, Value>> = onNewValueChannel.asFlow()
override val onValueRemoved: Flow<Key> = onValueRemovedChannel.asFlow()
init { initTable() }
override suspend fun set(k: Key, v: Value) {
transaction(database) {
if (select { keyColumn.eq(k) }.limit(1).any()) {

View File

@@ -10,13 +10,12 @@ open class ExposedReadKeyValueRepo<Key, Value>(
override val database: Database,
keyColumnAllocator: ColumnAllocator<Key>,
valueColumnAllocator: ColumnAllocator<Value>,
) : ReadStandardKeyValueRepo<Key, Value>, ExposedRepo, Table() {
tableName: String? = null
) : ReadStandardKeyValueRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
protected val keyColumn: Column<Key> = keyColumnAllocator()
protected val valueColumn: Column<Value> = valueColumnAllocator()
override val primaryKey: PrimaryKey = PrimaryKey(keyColumn, valueColumn)
init { initTable() }
override suspend fun get(k: Key): Value? = transaction(database) {
select { keyColumn.eq(k) }.limit(1).firstOrNull() ?.getOrNull(valueColumn)
}

View File

@@ -11,11 +11,13 @@ import org.jetbrains.exposed.sql.transactions.transaction
open class ExposedOneToManyKeyValueRepo<Key, Value>(
database: Database,
keyColumnAllocator: ColumnAllocator<Key>,
valueColumnAllocator: ColumnAllocator<Value>
valueColumnAllocator: ColumnAllocator<Value>,
tableName: String? = null
) : OneToManyKeyValueRepo<Key, Value>, ExposedReadOneToManyKeyValueRepo<Key, Value>(
database,
keyColumnAllocator,
valueColumnAllocator
valueColumnAllocator,
tableName
) {
protected val _onNewValue: BroadcastFlow<Pair<Key, Value>> = BroadcastFlow()
override val onNewValue: Flow<Pair<Key, Value>>
@@ -27,8 +29,6 @@ open class ExposedOneToManyKeyValueRepo<Key, Value>(
override val onDataCleared: Flow<Key>
get() = _onDataCleared
init { initTable() }
override suspend fun add(k: Key, v: Value) {
transaction(database) {
insert {

View File

@@ -9,8 +9,9 @@ import org.jetbrains.exposed.sql.transactions.transaction
open class ExposedReadOneToManyKeyValueRepo<Key, Value>(
override val database: Database,
keyColumnAllocator: ColumnAllocator<Key>,
valueColumnAllocator: ColumnAllocator<Value>
) : ReadOneToManyKeyValueRepo<Key, Value>, ExposedRepo, Table() {
valueColumnAllocator: ColumnAllocator<Value>,
tableName: String? = null
) : ReadOneToManyKeyValueRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
protected val keyColumn: Column<Key> = keyColumnAllocator()
protected val valueColumn: Column<Value> = valueColumnAllocator()

View File

@@ -2,6 +2,8 @@ package dev.inmo.micro_utils.repos
import dev.inmo.micro_utils.coroutines.BroadcastFlow
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.pagination.utils.reverse
import kotlinx.coroutines.flow.Flow
class ReadMapKeyValueRepo<Key, Value>(
@@ -13,31 +15,27 @@ class ReadMapKeyValueRepo<Key, Value>(
pagination: Pagination,
reversed: Boolean
): PaginationResult<Value> {
val firstIndex: Int = if (reversed) {
val size = map.size
(size - pagination.lastIndex).let { if (it < 0) 0 else it }
val values = map.values
val actualPagination = if (reversed) pagination.reverse(values.size) else pagination
return values.paginate(actualPagination).let {
if (reversed) {
it.copy(results = it.results.reversed())
} else {
pagination.firstIndex
it
}
}
return map.keys.drop(firstIndex).take(pagination.size).mapNotNull { map[it] }.createPaginationResult(
firstIndex,
count()
)
}
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> {
val firstIndex: Int = if (reversed) {
val size = map.size
(size - pagination.lastIndex).let { if (it < 0) 0 else it }
val keys = map.keys
val actualPagination = if (reversed) pagination.reverse(keys.size) else pagination
return keys.paginate(actualPagination).let {
if (reversed) {
it.copy(results = it.results.reversed())
} else {
pagination.firstIndex
it
}
}
return map.keys.drop(firstIndex).take(pagination.size).createPaginationResult(
firstIndex,
count()
)
}
override suspend fun contains(key: Key): Boolean = map.containsKey(key)

View File

@@ -3,6 +3,7 @@ package dev.inmo.micro_utils.repos
import dev.inmo.micro_utils.coroutines.BroadcastFlow
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.pagination.utils.reverse
import kotlinx.coroutines.flow.Flow
class MapReadOneToManyKeyValueRepo<Key, Value>(
@@ -13,8 +14,7 @@ class MapReadOneToManyKeyValueRepo<Key, Value>(
return list.paginate(
if (reversed) {
val firstIndex = (map.size - pagination.lastIndex).let { if (it < 0) 0 else it }
SimplePagination(firstIndex, pagination.size)
pagination.reverse(list.size)
} else {
pagination
}
@@ -22,17 +22,15 @@ class MapReadOneToManyKeyValueRepo<Key, Value>(
}
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> {
val firstIndex: Int = if (reversed) {
val size = map.size
(size - pagination.lastIndex).let { if (it < 0) 0 else it }
val keys = map.keys
val actualPagination = if (reversed) pagination.reverse(keys.size) else pagination
return keys.paginate(actualPagination).let {
if (reversed) {
it.copy(results = it.results.reversed())
} else {
pagination.firstIndex
it
}
}
return map.keys.drop(firstIndex).take(pagination.size).createPaginationResult(
firstIndex,
count()
)
}
override suspend fun contains(k: Key): Boolean = map.containsKey(k)

View File

@@ -16,7 +16,9 @@ String[] includes = [
":ktor:server",
":ktor:common",
":ktor:client",
":coroutines"
":coroutines",
":dokka"
]