Add convertable and serializable extensions to Meta delegates

This commit is contained in:
Alexander Nozik 2023-12-20 11:07:30 +03:00
parent f7dec52438
commit f9e7d0098f
4 changed files with 96 additions and 7 deletions

View File

@ -5,10 +5,12 @@
### Added ### Added
- Wasm artifacts - Wasm artifacts
- Add automatic MetaConverter for serializeable objects - Add automatic MetaConverter for serializeable objects
- Add Meta and MutableMeta delegates for convertable and serializeable
### Changed ### Changed
### Deprecated ### Deprecated
- `node(key,converter)` in favor of `serializable` delegate
### Removed ### Removed

View File

@ -1,6 +1,8 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.transformations.MetaConverter import space.kscience.dataforge.meta.transformations.MetaConverter
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
@ -11,13 +13,48 @@ public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
get(key ?: property.name.asName()) get(key ?: property.name.asName())
} }
public fun <T> MetaProvider.node( /**
* Use [converter] to read the Meta node
*/
public fun <T> MetaProvider.convertable(
converter: MetaConverter<T>,
key: Name? = null, key: Name? = null,
converter: MetaConverter<T>
): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property ->
get(key ?: property.name.asName())?.let { converter.metaToObject(it) } get(key ?: property.name.asName())?.let { converter.metaToObject(it) }
} }
/**
* Use object serializer to transform it to Meta and back
*/
@DFExperimental
public inline fun <reified T> MetaProvider.serializable(
descriptor: MetaDescriptor? = null,
key: Name? = null,
): ReadOnlyProperty<Any?, T?> = convertable(MetaConverter.serializable(descriptor), key)
@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)"))
public fun <T> MetaProvider.node(
key: Name? = null,
converter: MetaConverter<T>,
): ReadOnlyProperty<Any?, T?> = convertable(converter, key)
/**
* Use [converter] to convert a list of same name siblings meta to object
*/
public fun <T> Meta.listOfConvertable(
converter: MetaConverter<T>,
key: Name? = null,
): ReadOnlyProperty<Any?, List<T>> = ReadOnlyProperty{_, property ->
val name = key ?: property.name.asName()
getIndexed(name).values.map { converter.metaToObject(it) }
}
@DFExperimental
public inline fun <reified T> Meta.listOfSerializable(
descriptor: MetaDescriptor? = null,
key: Name? = null,
): ReadOnlyProperty<Any?, List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key)
/** /**
* A property delegate that uses custom key * A property delegate that uses custom key
*/ */
@ -27,7 +64,7 @@ public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?>
public fun <R> MetaProvider.value( public fun <R> MetaProvider.value(
key: Name? = null, key: Name? = null,
reader: (Value?) -> R reader: (Value?) -> R,
): ReadOnlyProperty<Any?, R> = ReadOnlyProperty { _, property -> ): ReadOnlyProperty<Any?, R> = ReadOnlyProperty { _, property ->
reader(get(key ?: property.name.asName())?.value) reader(get(key ?: property.name.asName())?.value)
} }

View File

@ -165,7 +165,7 @@ public fun MutableMetaProvider.remove(key: String) {
// node setters // node setters
public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = set(Key.asName(), value) public operator fun MutableMetaProvider.set(key: NameToken, value: Meta): Unit = set(key.asName(), value)
public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = set(Name.parse(key), value) public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = set(Name.parse(key), value)

View File

@ -1,6 +1,8 @@
package space.kscience.dataforge.meta package space.kscience.dataforge.meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.transformations.MetaConverter import space.kscience.dataforge.meta.transformations.MetaConverter
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
@ -20,10 +22,18 @@ public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?,
} }
} }
public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): ReadWriteProperty<Any?, T?> = /**
* Use [converter] to transform an object to Meta and back.
* Note that mutation of the object does not change Meta.
*/
public fun <T> MutableMetaProvider.convertable(
converter: MetaConverter<T>,
key: Name? = null,
): ReadWriteProperty<Any?, T?> =
object : ReadWriteProperty<Any?, T?> { object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? { override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return get(key ?: property.name.asName())?.let { converter.metaToObject(it) } val name = key ?: property.name.asName()
return get(name)?.let { converter.metaToObject(it) }
} }
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
@ -32,6 +42,46 @@ public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConver
} }
} }
@Deprecated("Use convertable", ReplaceWith("convertable(converter, key)"))
public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): ReadWriteProperty<Any?, T?> =
convertable(converter, key)
/**
* Use object serializer to transform it to Meta and back.
* Note that mutation of the object does not change Meta.
*/
@DFExperimental
public inline fun <reified T> MutableMetaProvider.serializable(
descriptor: MetaDescriptor? = null,
key: Name? = null,
): ReadWriteProperty<Any?, T?> = convertable(MetaConverter.serializable(descriptor), key)
/**
* Use [converter] to convert a list of same name siblings meta to object and back.
* Note that mutation of the object does not change Meta.
*/
public fun <T> MutableMeta.listOfConvertable(
converter: MetaConverter<T>,
key: Name? = null,
): ReadWriteProperty<Any?, List<T>> = object : ReadWriteProperty<Any?, List<T>> {
override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> {
val name = key ?: property.name.asName()
return getIndexed(name).values.map { converter.metaToObject(it) }
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: List<T>) {
val name = key ?: property.name.asName()
setIndexed(name, value.map { converter.objectToMeta(it) })
}
}
@DFExperimental
public inline fun <reified T> MutableMeta.listOfSerializable(
descriptor: MetaDescriptor? = null,
key: Name? = null,
): ReadWriteProperty<Any?, List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key)
public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> = public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
object : ReadWriteProperty<Any?, Value?> { object : ReadWriteProperty<Any?, Value?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = override fun getValue(thisRef: Any?, property: KProperty<*>): Value? =
@ -45,7 +95,7 @@ public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?,
public fun <T> MutableMetaProvider.value( public fun <T> MutableMetaProvider.value(
key: Name? = null, key: Name? = null,
writer: (T) -> Value? = { Value.of(it) }, writer: (T) -> Value? = { Value.of(it) },
reader: (Value?) -> T reader: (Value?) -> T,
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> { ): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T = override fun getValue(thisRef: Any?, property: KProperty<*>): T =
reader(get(key ?: property.name.asName())?.value) reader(get(key ?: property.name.asName())?.value)