DeviceSpec properties no explicitly pass property name to getters and setters

This commit is contained in:
Alexander Nozik 2023-11-18 15:39:56 +03:00
parent b539c2046a
commit 0c647cff30
2 changed files with 87 additions and 77 deletions

View File

@ -8,9 +8,7 @@ import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.transformations.MetaConverter import space.kscience.dataforge.meta.transformations.MetaConverter
import kotlin.properties.PropertyDelegateProvider import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
public object UnitMetaConverter : MetaConverter<Unit> { public object UnitMetaConverter : MetaConverter<Unit> {
override fun metaToObject(meta: Meta): Unit = Unit override fun metaToObject(meta: Meta): Unit = Unit
@ -44,11 +42,11 @@ public abstract class DeviceSpec<D : Device> {
return deviceProperty return deviceProperty
} }
public inline fun <reified T> property( public fun <T> property(
converter: MetaConverter<T>, converter: MetaConverter<T>,
crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, descriptorBuilder: PropertyDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
crossinline read: suspend D.(propertyName: String) -> T?, read: suspend D.(propertyName: String) -> T?,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> =
PropertyDelegateProvider { _: DeviceSpec<D>, property -> PropertyDelegateProvider { _: DeviceSpec<D>, property ->
val propertyName = name ?: property.name val propertyName = name ?: property.name
@ -56,7 +54,8 @@ public abstract class DeviceSpec<D : Device> {
override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply(descriptorBuilder) override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply(descriptorBuilder)
override val converter: MetaConverter<T> = converter override val converter: MetaConverter<T> = converter
override suspend fun read(device: D): T? = withContext(device.coroutineContext) { device.read(propertyName) } override suspend fun read(device: D): T? =
withContext(device.coroutineContext) { device.read(propertyName) }
} }
registerProperty(deviceProperty) registerProperty(deviceProperty)
ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>> { _, _ -> ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>> { _, _ ->
@ -64,12 +63,12 @@ public abstract class DeviceSpec<D : Device> {
} }
} }
public inline fun <reified T> mutableProperty( public fun <T> mutableProperty(
converter: MetaConverter<T>, converter: MetaConverter<T>,
crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {}, descriptorBuilder: PropertyDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
crossinline read: suspend D.(propertyName: String) -> T?, read: suspend D.(propertyName: String) -> T?,
crossinline write: suspend D.(propertyName: String, value: T) -> Unit, write: suspend D.(propertyName: String, value: T) -> Unit,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> -> PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> ->
val propertyName = name ?: property.name val propertyName = name ?: property.name
@ -106,7 +105,7 @@ public abstract class DeviceSpec<D : Device> {
name: String? = null, name: String? = null,
execute: suspend D.(I) -> O, execute: suspend D.(I) -> O,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> =
PropertyDelegateProvider { _: DeviceSpec<D>, property -> PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> ->
val actionName = name ?: property.name val actionName = name ?: property.name
val deviceAction = object : DeviceActionSpec<D, I, O> { val deviceAction = object : DeviceActionSpec<D, I, O> {
override val descriptor: ActionDescriptor = ActionDescriptor(actionName).apply(descriptorBuilder) override val descriptor: ActionDescriptor = ActionDescriptor(actionName).apply(descriptorBuilder)
@ -124,14 +123,33 @@ public abstract class DeviceSpec<D : Device> {
} }
} }
/** }
/**
* An action that takes no parameters and returns no values
*/
public fun <D : Device> DeviceSpec<D>.unitAction(
descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null,
execute: suspend D.() -> Unit,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
action(
MetaConverter.Companion.unit,
MetaConverter.Companion.unit,
descriptorBuilder,
name
) {
execute()
}
/**
* An action that takes [Meta] and returns [Meta]. No conversions are done * An action that takes [Meta] and returns [Meta]. No conversions are done
*/ */
public fun metaAction( public fun <D : Device> DeviceSpec<D>.metaAction(
descriptorBuilder: ActionDescriptor.() -> Unit = {}, descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
execute: suspend D.(Meta) -> Meta, execute: suspend D.(Meta) -> Meta,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
action( action(
MetaConverter.Companion.meta, MetaConverter.Companion.meta,
MetaConverter.Companion.meta, MetaConverter.Companion.meta,
@ -141,60 +159,3 @@ public abstract class DeviceSpec<D : Device> {
execute(it) execute(it)
} }
/**
* An action that takes no parameters and returns no values
*/
public fun unitAction(
descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null,
execute: suspend D.() -> Unit,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
action(
MetaConverter.Companion.unit,
MetaConverter.Companion.unit,
descriptorBuilder,
name
) {
execute()
}
}
public inline fun <reified T, D : Device> DeviceSpec<D>.property(
converter: MetaConverter<T>,
readOnlyProperty: KProperty1<D, T>,
crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {},
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> = property(
converter,
descriptorBuilder,
name = readOnlyProperty.name,
read = { readOnlyProperty.get(this) }
)
public inline fun <reified T, D : Device> DeviceSpec<D>.mutableProperty(
converter: MetaConverter<T>,
readWriteProperty: KMutableProperty1<D, T>,
crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {},
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
mutableProperty(
converter,
descriptorBuilder,
readWriteProperty.name,
read = { _ -> readWriteProperty.get(this) },
write = { _, value: T -> readWriteProperty.set(this, value) }
)
/**
* Register a mutable logical property (without a corresponding physical state) for a device
*/
public inline fun <reified T, D : DeviceBase<D>> DeviceSpec<D>.logicalProperty(
converter: MetaConverter<T>,
crossinline descriptorBuilder: PropertyDescriptor.() -> Unit = {},
name: String? = null,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
mutableProperty(
converter,
descriptorBuilder,
name,
read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) },
write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) }
)

View File

@ -8,6 +8,55 @@ import space.kscience.dataforge.meta.ValueType
import space.kscience.dataforge.meta.transformations.MetaConverter import space.kscience.dataforge.meta.transformations.MetaConverter
import kotlin.properties.PropertyDelegateProvider import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
/**
* A read-only device property that delegates reading to a device [KProperty1]
*/
public fun <T, D : Device> DeviceSpec<D>.property(
converter: MetaConverter<T>,
readOnlyProperty: KProperty1<D, T>,
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> = property(
converter,
descriptorBuilder,
name = readOnlyProperty.name,
read = { readOnlyProperty.get(this) }
)
/**
* Mutable property that delegates reading and writing to a device [KMutableProperty1]
*/
public fun <T, D : Device> DeviceSpec<D>.mutableProperty(
converter: MetaConverter<T>,
readWriteProperty: KMutableProperty1<D, T>,
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
mutableProperty(
converter,
descriptorBuilder,
readWriteProperty.name,
read = { _ -> readWriteProperty.get(this) },
write = { _, value: T -> readWriteProperty.set(this, value) }
)
/**
* Register a mutable logical property (without a corresponding physical state) for a device
*/
public fun <T, D : DeviceBase<D>> DeviceSpec<D>.logicalProperty(
converter: MetaConverter<T>,
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
name: String? = null,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
mutableProperty(
converter,
descriptorBuilder,
name,
read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) },
write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) }
)
//read only delegates //read only delegates