commonMain.util.TablePathUtils.kt Maven / Gradle / Ivy
@file:JvmName("TablePathUtils")
package io.kform.util
import io.kform.*
import io.kform.datatypes.Table
import kotlin.jvm.JvmName
/**
* Utility function which converts a path where table rows are indexed by their index into a path
* where said rows are indexed by their id in the corresponding table within the provided form value
* [formValue] (with schema [formSchema]).
*
* This function is especially useful when tables are being encoded and decoded as lists (e.g. via
* [Table.ValuesSerializer]) and we need to convert paths between one representation and the other.
*/
public suspend fun Path.convertTableRowIndicesToIds(
formSchema: Schema,
formValue: T
): AbsolutePath =
toAbsolutePath().let { absolutePath ->
var ids: MutableMap? = null
for (i in 0 until absolutePath.size) {
val index =
(absolutePath.fragment(i) as? AbsolutePathFragment.Id)?.id?.toIntOrNull()
?: continue
val parent = get(formSchema, formValue, AbsolutePath(absolutePath.fragments.take(i)))
if (parent is Table<*>) {
if (ids == null) {
ids = HashMap(absolutePath.size)
}
ids[i] = AbsolutePathFragment.Id(parent.rowAt(index).id)
}
}
return if (ids == null) absolutePath
else AbsolutePath(absolutePath.fragments.mapIndexed { i, fragment -> ids[i] ?: fragment })
}
/**
* Utility function which converts a path where table rows are indexed by their index into a path
* where said rows are indexed by their id in the corresponding table within the provided form value
* [formValue] (with schema [formSchema]).
*
* This function is especially useful when tables are being encoded and decoded as lists (e.g. via
* [Table.ValuesSerializer]) and we need to convert paths between one representation and the other.
*/
public suspend fun String.convertTableRowIndicesToIds(
formSchema: Schema,
formValue: T
): AbsolutePath = AbsolutePath(this).convertTableRowIndicesToIds(formSchema, formValue)
/**
* Utility function which converts a path where table rows are indexed by their id into a path where
* said rows are indexed by their index in the corresponding table within the provided form value
* [formValue] (with schema [formSchema]).
*
* This function is especially useful when transforming paths into human-readable names where it
* makes more sense to reference a table row by its index than by its internal id.
*/
public suspend fun Path.convertTableRowIdsToIndices(
formSchema: Schema,
formValue: T
): AbsolutePath =
toAbsolutePath().let { absolutePath ->
var indices: MutableMap? = null
for (i in 0 until absolutePath.size) {
val id =
(absolutePath.fragment(i) as? AbsolutePathFragment.Id)?.id?.toIntOrNull()
?: continue
val parentPath = AbsolutePath(absolutePath.fragments.take(i))
val parent = get(formSchema, formValue, parentPath)
if (parent is Table<*>) {
if (indices == null) {
indices = HashMap(absolutePath.size)
}
val index = parent.indexOfId(id)
if (index == -1) {
throw InvalidPathException(parentPath, "Table has no row with id '$id'.")
}
indices[i] = AbsolutePathFragment.Id(index)
}
}
return if (indices == null) absolutePath
else
AbsolutePath(
absolutePath.fragments.mapIndexed { i, fragment -> indices[i] ?: fragment }
)
}
/**
* Utility function which converts a path where table rows are indexed by their id into a path where
* said rows are indexed by their index in the corresponding table within the provided form value
* [formValue] (with schema [formSchema]).
*
* This function is especially useful when transforming paths into human-readable names where it
* makes more sense to reference a table row by its index than by its internal id.
*/
public suspend fun String.convertTableRowIdsToIndices(
formSchema: Schema,
formValue: T
): AbsolutePath = AbsolutePath(this).convertTableRowIdsToIndices(formSchema, formValue)
/**
* Utility function which converts the paths of a [LocatedValidationIssue] where table rows are
* indexed by their index into paths where said rows are indexed by their id in the corresponding
* table within the provided form value [formValue] (with schema [formSchema]).
*
* This function is especially useful when tables are being encoded and decoded as lists (e.g. via
* [Table.ValuesSerializer]) and we need to add this external validation issue to a
* [form manager][FormManager].
*/
public suspend fun LocatedValidationIssue.convertTableRowIndicesToIds(
formSchema: Schema,
formValue: T
): LocatedValidationIssue =
LocatedValidationIssue(
path.convertTableRowIndicesToIds(formSchema, formValue),
code,
severity,
dependencies.map { it.convertTableRowIndicesToIds(formSchema, formValue) },
dependsOnDescendants,
externalContextDependencies,
data
)
/**
* Utility function which converts the paths of an iterable of [LocatedValidationIssue]s where table
* rows are indexed by their index into paths where said rows are indexed by their id in the
* corresponding table within the provided form value [formValue] (with schema [formSchema]).
*
* This function is especially useful when tables are being encoded and decoded as lists (e.g. via
* [Table.ValuesSerializer]) and we need to add these external validation issues to a
* [form manager][FormManager].
*/
public suspend fun Iterable.convertTableRowIndicesToIds(
formSchema: Schema,
formValue: T
): List = map { it.convertTableRowIndicesToIds(formSchema, formValue) }