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 ## Unreleased
### Added ### Added
- Relax requirements for `withDefault` and `view`. Now they could be used with `MutableMetaProvider`
- Add `MutableMetaProvider` to `MutableMeta` converter `asMutableMeta`.
### Changed ### Changed
- Implementation of `Meta::withDefault`
### Deprecated ### 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 } 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 this
} else { } else {
//TODO optimize object : Meta {
toMutableMeta().withDefault(default) 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> 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? override var value: Value?
@ -437,7 +437,7 @@ public inline fun Meta.copy(modification: MutableMeta.() -> Unit = {}): Meta = M
} }
private class MutableMetaWithDefault( private class MutableMetaWithDefault(
val source: MutableMeta, val default: MetaProvider, val rootName: Name, val source: MutableMetaProvider, val default: MetaProvider, val rootName: Name,
) : MutableMeta { ) : MutableMeta {
override val items: Map<NameToken, MutableMeta> override val items: Map<NameToken, MutableMeta>
get() { 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. * Changes are propagated only to this provider.
*/ */
public fun MutableMeta.withDefault(default: MetaProvider?): MutableMeta = if (default == null) { public fun MutableMetaProvider.withDefault(
this default: MetaProvider?
} else MutableMetaWithDefault(this, default, Name.EMPTY) ): 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 * A [Meta] child proxy that creates required nodes on value write
*/ */
private class MutableMetaView( private class MutableMetaView(
val origin: MutableMeta, val origin: MutableMetaProvider,
val path: Name val path: Name
) : MutableMeta { ) : MutableMeta {
@ -42,6 +42,11 @@ private class MutableMetaView(
* The difference between this method and regular [getOrCreate] is that [getOrCreate] always creates and attaches node * The difference between this method and regular [getOrCreate] is that [getOrCreate] always creates and attaches node
* even if it is empty. * 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 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 public fun Value.isList(): Boolean = this.type == ValueType.LIST