cleanup specification. again

This commit is contained in:
Alexander Nozik 2020-12-25 18:28:23 +03:00
parent adf65a5bde
commit 9c3f9420ea
4 changed files with 66 additions and 64 deletions

View File

@ -9,13 +9,9 @@ import hep.dataforge.names.asName
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification]. * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
* Default item provider and [NodeDescriptor] are optional * Default item provider and [NodeDescriptor] are optional
*/ */
public open class Scheme( public open class Scheme() : MutableItemProvider, Described, MetaRepr {
items: MutableItemProvider = Config(),
internal var default: ItemProvider? = null,
descriptor: NodeDescriptor? = null,
) : MutableItemProvider, Described, MetaRepr {
public var items: MutableItemProvider = items public var items: MutableItemProvider = MetaBuilder()
internal set(value) { internal set(value) {
//Fix problem with `init` blocks in specifications //Fix problem with `init` blocks in specifications
field = value.apply { field = value.apply {
@ -23,9 +19,21 @@ public open class Scheme(
} }
} }
override var descriptor: NodeDescriptor? = descriptor internal var default: ItemProvider? = null
final override var descriptor: NodeDescriptor? = null
internal set internal set
public constructor(
items: MutableItemProvider,
default: ItemProvider? = null,
descriptor: NodeDescriptor? = null,
) : this(){
this.items = items
this.default = default
this.descriptor = descriptor
}
private fun getDefaultItem(name: Name): MetaItem? { private fun getDefaultItem(name: Name): MetaItem? {
return default?.get(name) ?: descriptor?.get(name)?.defaultItem() return default?.get(name) ?: descriptor?.get(name)?.defaultItem()
@ -114,7 +122,4 @@ public open class SchemeSpec<T : Scheme>(
public fun Meta.asScheme(): Scheme = Scheme().apply { public fun Meta.asScheme(): Scheme = Scheme().apply {
items = this@asScheme.asConfig() items = this@asScheme.asConfig()
} }
public fun <T : MutableItemProvider> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
spec.read(this).apply(block)

View File

@ -35,8 +35,9 @@ public interface Specification<T : MutableItemProvider> {
/** /**
* Update a [MutableItemProvider] using given specification * Update a [MutableItemProvider] using given specification
*/ */
public fun <T : MutableItemProvider> MutableItemProvider.update(spec: Specification<T>, action: T.() -> Unit): T = public fun <T : MutableItemProvider> MutableItemProvider.update(spec: Specification<T>, action: T.() -> Unit) {
spec.write(this).apply(action) spec.write(this).apply(action)
}
/** /**
* Update configuration using given specification * Update configuration using given specification
@ -44,38 +45,24 @@ public fun <T : MutableItemProvider> MutableItemProvider.update(spec: Specificat
public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update( public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(
spec: S, spec: S,
action: C.() -> Unit, action: C.() -> Unit,
): Configurable = apply { config.update(spec, action) } ) {
config.update(spec, action)
}
public fun <T : MutableItemProvider> TypedMetaItem<Config>.withSpec(spec: Specification<T>): T? = public fun <T : MutableItemProvider> TypedMetaItem<MutableMeta<*>>.withSpec(spec: Specification<T>): T? =
node?.let { spec.write(it) } node?.let { spec.write(it) }
public fun <T : Scheme> MutableItemProvider.spec( public fun <T : Scheme> MutableItemProvider.spec(
spec: Specification<T>, spec: Specification<T>,
key: Name? = null, key: Name? = null,
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val name = key ?: property.name.asName()
return get(name).node?.let { spec.read(it) }
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
val name = key ?: property.name.asName()
set(name, value?.toMeta()?.asMetaItem())
}
}
public fun <T : Scheme> MutableItemProvider.spec(
spec: Specification<T>,
default: T,
key: Name? = null,
): 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 {
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
return get(name).node?.let { spec.read(it) } ?: default return getChild(name).let { spec.write(it) }
} }
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val name = key ?: property.name.asName() val name = key ?: property.name.asName()
set(name, value.toMeta().asMetaItem()) set(name, value.toMeta().asMetaItem())
} }
} }

View File

@ -1,32 +0,0 @@
package hep.dataforge.meta
import kotlin.test.Test
import kotlin.test.assertEquals
class SchemeTest{
@Test
fun testMetaScheme(){
val styled = Meta {
repeat(10){
"b.a[$it]" put {
"d" put it
}
}
}.asScheme()
val meta = styled.toMeta()
assertEquals(10, meta.valueSequence().count())
val bNode = styled.get("b").node
val aNodes = bNode?.getIndexed("a")
val allNodes = meta.getIndexed("b.a")
assertEquals(3, aNodes?.get("3").node["d"].int)
assertEquals(3, allNodes["3"].node["d"].int)
}
}

View File

@ -15,6 +15,37 @@ class SpecificationTest {
} }
} }
class TestScheme : Scheme() {
var a by int()
var b by string()
companion object : SchemeSpec<TestScheme>(::TestScheme)
}
// @Test
// fun testMetaScheme(){
// val styled = Meta {
// repeat(10){
// "b.a[$it]" put {
// "d" put it
// }
// }
// }.asScheme()
//
// val meta = styled.toMeta()
//
// assertEquals(10, meta.valueSequence().count())
//
// val bNode = styled["b"].node
//
// val aNodes = bNode?.getIndexed("a")
//
// val allNodes = meta.getIndexed("b.a")
//
// assertEquals(3, aNodes?.get("3").node["d"].int)
// assertEquals(3, allNodes["3"].node["d"].int)
// }
@Test @Test
fun testSpecific() { fun testSpecific() {
@ -23,4 +54,15 @@ class SpecificationTest {
} }
assertEquals(emptyList(), testObject.list) assertEquals(emptyList(), testObject.list)
} }
@Test
fun testChildModification() {
val config = Config()
val child = config.getChild("child")
val scheme = TestScheme.write(child)
scheme.a = 22
scheme.b = "test"
assertEquals(22,config["child.a"].int)
assertEquals("test",config["child.b"].string)
}
} }