Relax type of view and withDefault

This commit is contained in:
Alexander Nozik 2025-02-02 14:03:59 +03:00
parent a438666d32
commit 3acbaffecb
5 changed files with 48 additions and 14 deletions
CHANGELOG.md
dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta

@ -3,8 +3,11 @@
## Unreleased
### Added
- Relax requirements for `withDefault` and `view`. Now they could be used with `MutableMetaProvider`
- Add `MutableMetaProvider` to `MutableMeta` converter `asMutableMeta`.
### Changed
- Implementation of `Meta::withDefault`
### Deprecated

@ -249,11 +249,26 @@ public inline fun <reified E : Enum<E>> Meta?.enum(): E? = this?.value?.let {
public val Meta?.stringList: List<String>? get() = this?.value?.list?.map { it.string }
/**
* Create a provider that uses given provider for default values if those are not found in this provider
* Create a provider that uses a given provider for default values if those are not found in this provider
*/
public fun Meta.withDefault(default: MetaProvider?): Meta = if (default == null) {
public fun MetaProvider.withDefault(default: MetaProvider?): Meta = if (default == null && this is Meta) {
this
} else {
//TODO optimize
toMutableMeta().withDefault(default)
object : Meta {
override val value: Value?
get() = this@withDefault.getValue(Name.EMPTY) ?: default?.getValue(Name.EMPTY)
override val items: Map<NameToken, Meta>
get() = buildMap {
default?.get(Name.EMPTY)?.items?.let { putAll(it) }
this@withDefault.get(Name.EMPTY)?.items?.let { putAll(it) }
}
override fun toString(): String = Meta.toString(this)
override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta)
override fun hashCode(): Int = Meta.hashCode(this)
}
}

@ -37,7 +37,7 @@ public interface MutableMeta : Meta, MutableMetaProvider {
override val items: Map<NameToken, MutableMeta>
/**
* Get or set value of this node
* Get or set the value of this node
*/
override var value: Value?
@ -437,7 +437,7 @@ public inline fun Meta.copy(modification: MutableMeta.() -> Unit = {}): Meta = M
}
private class MutableMetaWithDefault(
val source: MutableMeta, val default: MetaProvider, val rootName: Name,
val source: MutableMetaProvider, val default: MetaProvider, val rootName: Name,
) : MutableMeta {
override val items: Map<NameToken, MutableMeta>
get() {
@ -474,9 +474,20 @@ private class MutableMetaWithDefault(
}
/**
* Create a mutable item provider that uses given provider for default values if those are not found in this provider.
* Create a mutable item provider that uses a given provider for default values if those are not found in this provider.
* Changes are propagated only to this provider.
*/
public fun MutableMeta.withDefault(default: MetaProvider?): MutableMeta = if (default == null) {
this
} else MutableMetaWithDefault(this, default, Name.EMPTY)
public fun MutableMetaProvider.withDefault(
default: MetaProvider?
): MutableMeta = if (default == null) {
(this as? MutableMeta) ?: asMutableMeta()
} else {
MutableMetaWithDefault(this, default, Name.EMPTY)
}
/**
* Use multiple default providers. Providers are queried in order of appearance. The first non-null value is returned
*/
public fun MutableMetaProvider.withDefaults(vararg defaults: MetaProvider): MutableMeta = withDefault { name ->
defaults.firstNotNullOfOrNull { it[name] }
}

@ -9,7 +9,7 @@ import space.kscience.dataforge.names.plus
* A [Meta] child proxy that creates required nodes on value write
*/
private class MutableMetaView(
val origin: MutableMeta,
val origin: MutableMetaProvider,
val path: Name
) : MutableMeta {
@ -42,6 +42,11 @@ private class MutableMetaView(
* The difference between this method and regular [getOrCreate] is that [getOrCreate] always creates and attaches node
* even if it is empty.
*/
public fun MutableMeta.view(name: Name): MutableMeta = MutableMetaView(this, name)
public fun MutableMetaProvider.view(name: Name): MutableMeta = MutableMetaView(this, name)
public fun MutableMeta.view(name: String): MutableMeta = view(name.parseAsName())
public fun MutableMetaProvider.view(name: String): MutableMeta = view(name.parseAsName())
/**
* Create a view of root node, thus effectively representing [MutableMetaProvider] as [MutableMeta]
*/
public fun MutableMetaProvider.asMutableMeta(): MutableMeta = view(Name.EMPTY)

@ -6,7 +6,7 @@ package space.kscience.dataforge.meta
public fun Value.isNull(): Boolean = this == Null
/**
* Check if value is list.
* Check if the value is a list.
*/
public fun Value.isList(): Boolean = this.type == ValueType.LIST