-
Notifications
You must be signed in to change notification settings - Fork 2
/
KeyValuesFromKeyValueRepo.kt
96 lines (83 loc) · 3.17 KB
/
KeyValuesFromKeyValueRepo.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package dev.inmo.micro_utils.repos.transforms.kvs
import dev.inmo.micro_utils.pagination.FirstPagePagination
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.KeyValuesRepo
import dev.inmo.micro_utils.repos.set
import dev.inmo.micro_utils.repos.unset
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlin.js.JsName
import kotlin.jvm.JvmName
open class KeyValuesFromKeyValueRepo<Key, Value, ValuesIterable : Iterable<Value>>(
private val original: KeyValueRepo<Key, ValuesIterable>,
private val listToValuesIterable: suspend (List<Value>) -> ValuesIterable
) : KeyValuesRepo<Key, Value>, ReadKeyValuesFromKeyValueRepo<Key, Value, ValuesIterable>(original) {
private val _onNewValue = MutableSharedFlow<Pair<Key, Value>>()
private val _onValueRemoved = MutableSharedFlow<Pair<Key, Value>>()
override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow()
override val onValueRemoved: Flow<Pair<Key, Value>> = _onValueRemoved.asSharedFlow()
override val onDataCleared: Flow<Key> = original.onValueRemoved
override suspend fun clearWithValue(v: Value) {
val keys = mutableSetOf<Key>()
doForAllWithNextPaging(FirstPagePagination(count().toInt())) {
original.keys(it).also {
it.results.forEach {
if (contains(it, v)) {
keys.add(it)
}
}
}
}
original.unset(keys.toList())
}
override suspend fun clear(k: Key) {
original.unset(k)
}
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
original.set(
toRemove.mapNotNull { (k, removing) ->
val exists = original.get(k) ?: return@mapNotNull null
k to listToValuesIterable(exists - removing).also {
if (it.firstOrNull() == null) {
original.unset(k)
return@mapNotNull null
}
}
}.toMap()
)
toRemove.forEach { (k, v) ->
v.forEach {
_onValueRemoved.emit(k to it)
}
}
}
override suspend fun removeWithValue(v: Value) {
val toRemove = mutableMapOf<Key, List<Value>>()
doForAllWithNextPaging {
original.keys(it).also {
it.results.forEach {
val data = original.get(it) ?: return@forEach
if (v in data) {
toRemove[it] = listOf(v)
}
}
}
}
remove(toRemove)
}
override suspend fun add(toAdd: Map<Key, List<Value>>) {
original.set(
toAdd.mapNotNull { (k, adding) ->
val exists = original.get(k) ?: emptyList()
k to listToValuesIterable(exists + adding)
}.toMap()
)
toAdd.forEach { (k, v) ->
v.forEach {
_onNewValue.emit(k to it)
}
}
}
}