Compare commits

...

8 Commits
0.5.7 ... 0.5.9

7 changed files with 96 additions and 23 deletions

12
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
name: Regular build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build
run: ./gradlew build

View File

@@ -1,5 +1,20 @@
# Changelog # Changelog
## 0.5.9
* `Repos`
* `Common`
* `OneToManyAndroidRepo` got new primary constructor
## 0.5.8
* `Common`:
* New extension `Iterable#firstNotNull`
* `Coroutines`
* New extension `Flow#firstNotNull`
* New extensions `CoroutineContext#LinkedSupervisorJob`, `CoroutineScope#LinkedSupervisorJob` and
`CoroutineScope#LinkedSupervisorScope`
## 0.5.7 ## 0.5.7
* `Pagination` * `Pagination`

View File

@@ -0,0 +1,3 @@
package dev.inmo.micro_utils.common
fun <T> Iterable<T?>.firstNotNull() = first { it != null }!!

View File

@@ -0,0 +1,6 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
suspend fun <T> Flow<T?>.firstNotNull() = first { it != null }!!

View File

@@ -0,0 +1,17 @@
package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
fun CoroutineContext.LinkedSupervisorJob(
additionalContext: CoroutineContext? = null
) = SupervisorJob(job).let { if (additionalContext != null) it + additionalContext else it }
fun CoroutineScope.LinkedSupervisorJob(
additionalContext: CoroutineContext? = null
) = coroutineContext.LinkedSupervisorJob(additionalContext)
fun CoroutineScope.LinkedSupervisorScope(
additionalContext: CoroutineContext? = null
) = CoroutineScope(
coroutineContext + LinkedSupervisorJob(additionalContext)
)

View File

@@ -45,5 +45,5 @@ dokka_version=1.4.32
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.5.7 version=0.5.9
android_code_version=48 android_code_version=50

View File

@@ -20,10 +20,14 @@ private val internalSerialFormat = Json {
ignoreUnknownKeys = true ignoreUnknownKeys = true
} }
typealias KeyValuesAndroidRepo<Key, Value> = OneToManyAndroidRepo<Key, Value>
class OneToManyAndroidRepo<Key, Value>( class OneToManyAndroidRepo<Key, Value>(
private val tableName: String, private val tableName: String,
private val keySerializer: KSerializer<Key>, private val keyAsString: Key.() -> String,
private val valueSerializer: KSerializer<Value>, private val valueAsString: Value.() -> String,
private val keyFromString: String.() -> Key,
private val valueFromString: String.() -> Value,
private val helper: SQLiteOpenHelper private val helper: SQLiteOpenHelper
) : OneToManyKeyValueRepo<Key, Value> { ) : OneToManyKeyValueRepo<Key, Value> {
private val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow() private val _onNewValue: MutableSharedFlow<Pair<Key, Value>> = MutableSharedFlow()
@@ -36,11 +40,6 @@ class OneToManyAndroidRepo<Key, Value>(
private val idColumnName = "id" private val idColumnName = "id"
private val valueColumnName = "value" private val valueColumnName = "value"
private fun Key.asId() = internalSerialFormat.encodeToString(keySerializer, this)
private fun Value.asValue() = internalSerialFormat.encodeToString(valueSerializer, this)
private fun String.asValue(): Value = internalSerialFormat.decodeFromString(valueSerializer, this)
private fun String.asKey(): Key = internalSerialFormat.decodeFromString(keySerializer, this)
init { init {
helper.blockingWritableTransaction { helper.blockingWritableTransaction {
createTable( createTable(
@@ -61,8 +60,8 @@ class OneToManyAndroidRepo<Key, Value>(
tableName, tableName,
null, null,
contentValuesOf( contentValuesOf(
idColumnName to k.asId(), idColumnName to k.keyAsString(),
valueColumnName to v.asValue() valueColumnName to v.valueAsString()
) )
).also { ).also {
if (it != -1L) { if (it != -1L) {
@@ -77,7 +76,7 @@ class OneToManyAndroidRepo<Key, Value>(
override suspend fun clear(k: Key) { override suspend fun clear(k: Key) {
helper.blockingWritableTransaction { helper.blockingWritableTransaction {
delete(tableName, "$idColumnName=?", arrayOf(k.asId())) delete(tableName, "$idColumnName=?", arrayOf(k.keyAsString()))
}.also { }.also {
if (it > 0) { if (it > 0) {
_onDataCleared.emit(k) _onDataCleared.emit(k)
@@ -88,7 +87,7 @@ class OneToManyAndroidRepo<Key, Value>(
override suspend fun set(toSet: Map<Key, List<Value>>) { override suspend fun set(toSet: Map<Key, List<Value>>) {
val (clearedKeys, inserted) = helper.blockingWritableTransaction { val (clearedKeys, inserted) = helper.blockingWritableTransaction {
toSet.mapNotNull { (k, _) -> toSet.mapNotNull { (k, _) ->
if (delete(tableName, "$idColumnName=?", arrayOf(k.asId())) > 0) { if (delete(tableName, "$idColumnName=?", arrayOf(k.keyAsString())) > 0) {
k k
} else { } else {
null null
@@ -98,7 +97,7 @@ class OneToManyAndroidRepo<Key, Value>(
insert( insert(
tableName, tableName,
null, null,
contentValuesOf(idColumnName to k.asId(), valueColumnName to v.asValue()) contentValuesOf(idColumnName to k.keyAsString(), valueColumnName to v.valueAsString())
) )
k to v k to v
} }
@@ -109,7 +108,7 @@ class OneToManyAndroidRepo<Key, Value>(
} }
override suspend fun contains(k: Key): Boolean = helper.blockingReadableTransaction { override suspend fun contains(k: Key): Boolean = helper.blockingReadableTransaction {
select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use { select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use {
it.count > 0 it.count > 0
} }
} }
@@ -118,7 +117,7 @@ class OneToManyAndroidRepo<Key, Value>(
select( select(
tableName, tableName,
selection = "$idColumnName=? AND $valueColumnName=?", selection = "$idColumnName=? AND $valueColumnName=?",
selectionArgs = arrayOf(k.asId(), v.asValue()), selectionArgs = arrayOf(k.keyAsString(), v.valueAsString()),
limit = FirstPagePagination(1).limitClause() limit = FirstPagePagination(1).limitClause()
).use { ).use {
it.count > 0 it.count > 0
@@ -134,7 +133,7 @@ class OneToManyAndroidRepo<Key, Value>(
}.toLong() }.toLong()
override suspend fun count(k: Key): Long = helper.blockingReadableTransaction { override suspend fun count(k: Key): Long = helper.blockingReadableTransaction {
select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.asId()), limit = FirstPagePagination(1).limitClause()).use { select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use {
it.count it.count
} }
}.toLong() }.toLong()
@@ -149,13 +148,13 @@ class OneToManyAndroidRepo<Key, Value>(
select( select(
tableName, tableName,
selection = "$idColumnName=?", selection = "$idColumnName=?",
selectionArgs = arrayOf(k.asId()), selectionArgs = arrayOf(k.keyAsString()),
limit = resultPagination.limitClause() limit = resultPagination.limitClause()
).use { c -> ).use { c ->
mutableListOf<Value>().also { mutableListOf<Value>().also {
if (c.moveToFirst()) { if (c.moveToFirst()) {
do { do {
it.add(c.getString(valueColumnName).asValue()) it.add(c.getString(valueColumnName).valueFromString())
} while (c.moveToNext()) } while (c.moveToNext())
} }
} }
@@ -179,7 +178,7 @@ class OneToManyAndroidRepo<Key, Value>(
mutableListOf<Key>().also { mutableListOf<Key>().also {
if (c.moveToFirst()) { if (c.moveToFirst()) {
do { do {
it.add(c.getString(idColumnName).asKey()) it.add(c.getString(idColumnName).keyFromString())
} while (c.moveToNext()) } while (c.moveToNext())
} }
} }
@@ -200,13 +199,13 @@ class OneToManyAndroidRepo<Key, Value>(
select( select(
tableName, tableName,
selection = "$valueColumnName=?", selection = "$valueColumnName=?",
selectionArgs = arrayOf(v.asValue()), selectionArgs = arrayOf(v.valueAsString()),
limit = resultPagination.limitClause() limit = resultPagination.limitClause()
).use { c -> ).use { c ->
mutableListOf<Key>().also { mutableListOf<Key>().also {
if (c.moveToFirst()) { if (c.moveToFirst()) {
do { do {
it.add(c.getString(idColumnName).asKey()) it.add(c.getString(idColumnName).keyFromString())
} while (c.moveToNext()) } while (c.moveToNext())
} }
} }
@@ -221,7 +220,7 @@ class OneToManyAndroidRepo<Key, Value>(
helper.blockingWritableTransaction { helper.blockingWritableTransaction {
toRemove.flatMap { (k, vs) -> toRemove.flatMap { (k, vs) ->
vs.mapNotNullA { v -> vs.mapNotNullA { v ->
if (delete(tableName, "$idColumnName=? AND $valueColumnName=?", arrayOf(k.asId(), v.asValue())) > 0) { if (delete(tableName, "$idColumnName=? AND $valueColumnName=?", arrayOf(k.keyAsString(), v.valueAsString())) > 0) {
k to v k to v
} else { } else {
null null
@@ -233,3 +232,24 @@ class OneToManyAndroidRepo<Key, Value>(
} }
} }
} }
fun <Key, Value> OneToManyAndroidRepo(
tableName: String,
keySerializer: KSerializer<Key>,
valueSerializer: KSerializer<Value>,
helper: SQLiteOpenHelper
) = OneToManyAndroidRepo(
tableName,
{ internalSerialFormat.encodeToString(keySerializer, this) },
{ internalSerialFormat.encodeToString(valueSerializer, this) },
{ internalSerialFormat.decodeFromString(keySerializer, this) },
{ internalSerialFormat.decodeFromString(valueSerializer, this) },
helper
)
fun <Key, Value> KeyValuesAndroidRepo(
tableName: String,
keySerializer: KSerializer<Key>,
valueSerializer: KSerializer<Value>,
helper: SQLiteOpenHelper
) = OneToManyAndroidRepo(tableName, keySerializer, valueSerializer, helper)