Code cleanup

This commit is contained in:
Alexander Nozik 2019-01-27 17:16:40 +03:00
parent 5dd40f0226
commit 4cafac1f1b
26 changed files with 159 additions and 106 deletions

0
README.md Normal file
View File

View File

@ -7,7 +7,7 @@ description = "Context and provider definitions"
val coroutinesVersion: String by rootProject.extra val coroutinesVersion: String by rootProject.extra
kotlin { kotlin {
jvm () jvm()
js() js()
sourceSets { sourceSets {

View File

@ -11,7 +11,6 @@ import kotlinx.coroutines.Dispatchers
import mu.KLogger import mu.KLogger
import mu.KotlinLogging import mu.KotlinLogging
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KClass
/** /**
* The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top. * The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top.
@ -102,12 +101,11 @@ inline fun <reified T : Any> Context.list(target: String): Sequence<T> {
/** /**
* A global root context * A global root context
*/ */
expect object Global : Context{ expect object Global : Context {
fun getContext(name: String): Context fun getContext(name: String): Context
} }
/** /**
* The interface for something that encapsulated in context * The interface for something that encapsulated in context
* *

View File

@ -59,7 +59,8 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
* @return * @return
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
operator fun <T : Plugin> get(type: KClass<T>, recursive: Boolean = true): T? = get(recursive) { type.isInstance(it) } as T? operator fun <T : Plugin> get(type: KClass<T>, recursive: Boolean = true): T? =
get(recursive) { type.isInstance(it) } as T?
inline fun <reified T : Plugin> get(recursive: Boolean = true): T? = get(T::class, recursive) inline fun <reified T : Plugin> get(recursive: Boolean = true): T? = get(T::class, recursive)

View File

@ -24,5 +24,6 @@ expect object PluginRepository {
/** /**
* Fetch specific plugin and instantiate it with given meta * Fetch specific plugin and instantiate it with given meta
*/ */
fun PluginRepository.fetch(tag: PluginTag, meta: Meta): Plugin = PluginRepository.list().find { it.tag.matches(tag) }?.build(meta) fun PluginRepository.fetch(tag: PluginTag, meta: Meta): Plugin =
PluginRepository.list().find { it.tag.matches(tag) }?.build(meta)
?: error("Plugin with tag $tag not found in the repository") ?: error("Plugin with tag $tag not found in the repository")

View File

@ -5,14 +5,14 @@ import mu.KLogger
import mu.KotlinLogging import mu.KotlinLogging
import kotlin.jvm.Synchronized import kotlin.jvm.Synchronized
actual object Global: Context, JSContext("GLOBAL", null){ actual object Global : Context, JSContext("GLOBAL", null) {
/** /**
* Closing all contexts * Closing all contexts
* *
* @throws Exception * @throws Exception
*/ */
override fun close() { override fun close() {
logger.info{"Shutting down GLOBAL"} logger.info { "Shutting down GLOBAL" }
for (ctx in contextRegistry.values) { for (ctx in contextRegistry.values) {
ctx.close() ctx.close()
} }
@ -37,7 +37,7 @@ open class JSContext(
final override val name: String, final override val name: String,
final override val parent: JSContext? = Global, final override val parent: JSContext? = Global,
properties: Meta = EmptyMeta properties: Meta = EmptyMeta
): Context { ) : Context {
private val _properties = Config().apply { update(properties) } private val _properties = Config().apply { update(properties) }
override val properties: Meta override val properties: Meta

View File

@ -16,7 +16,6 @@
package hep.dataforge.context package hep.dataforge.context
import hep.dataforge.meta.* import hep.dataforge.meta.*
import kotlinx.coroutines.Dispatchers
import mu.KLogger import mu.KLogger
import mu.KotlinLogging import mu.KotlinLogging
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -24,7 +23,6 @@ import java.util.*
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.collections.HashSet import kotlin.collections.HashSet
import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.full.cast import kotlin.reflect.full.cast
@ -75,7 +73,8 @@ open class JVMContext(
private val serviceCache: MutableMap<Class<*>, ServiceLoader<*>> = HashMap() private val serviceCache: MutableMap<Class<*>, ServiceLoader<*>> = HashMap()
fun <T : Any> services(type: KClass<T>): Sequence<T> { fun <T : Any> services(type: KClass<T>): Sequence<T> {
return serviceCache.getOrPut(type.java) { ServiceLoader.load(type.java, classLoader) }.asSequence().map { type.cast(it) } return serviceCache.getOrPut(type.java) { ServiceLoader.load(type.java, classLoader) }.asSequence()
.map { type.cast(it) }
} }
/** /**

View File

@ -50,7 +50,8 @@ class PipeAction<in T : Any, out R : Any>(val transform: (Name, Data<T>, Meta) -
/** /**
* A simple pipe that performs transformation on the data and copies input meta into the output * A simple pipe that performs transformation on the data and copies input meta into the output
*/ */
inline fun <T : Any, reified R : Any> simple(noinline transform: suspend (Name, T, Meta) -> R) = PipeAction { name, data: Data<T>, meta -> inline fun <T : Any, reified R : Any> simple(noinline transform: suspend (Name, T, Meta) -> R) =
PipeAction { name, data: Data<T>, meta ->
val goal = data.goal.pipe { transform(name, it, meta) } val goal = data.goal.pipe { transform(name, it, meta) }
return@PipeAction Data.of(goal, data.meta) return@PipeAction Data.of(goal, data.meta)
} }

View File

@ -20,7 +20,8 @@ interface Goal<out T> : Deferred<T>, CoroutineScope {
/** /**
* Create goal wrapping static value. This goal is always completed * Create goal wrapping static value. This goal is always completed
*/ */
fun <T> static(context: CoroutineContext, value: T): Goal<T> = StaticGoalImpl(context, CompletableDeferred(value)) fun <T> static(context: CoroutineContext, value: T): Goal<T> =
StaticGoalImpl(context, CompletableDeferred(value))
} }
} }
@ -50,14 +51,16 @@ class GoalMonitor {
private class GoalImpl<T>( private class GoalImpl<T>(
override val dependencies: Collection<Goal<*>>, override val dependencies: Collection<Goal<*>>,
val monitor: GoalMonitor, val monitor: GoalMonitor,
deferred: Deferred<T>) : Goal<T>, Deferred<T> by deferred { deferred: Deferred<T>
) : Goal<T>, Deferred<T> by deferred {
override val coroutineContext: CoroutineContext get() = this override val coroutineContext: CoroutineContext get() = this
override val totalWork: Double get() = dependencies.sumByDouble { totalWork } + monitor.totalWork override val totalWork: Double get() = dependencies.sumByDouble { totalWork } + monitor.totalWork
override val workDone: Double get() = dependencies.sumByDouble { workDone } + monitor.workDone override val workDone: Double get() = dependencies.sumByDouble { workDone } + monitor.workDone
override val status: String get() = monitor.status override val status: String get() = monitor.status
} }
private class StaticGoalImpl<T>(val context: CoroutineContext, deferred: CompletableDeferred<T>) : Goal<T>, Deferred<T> by deferred { private class StaticGoalImpl<T>(val context: CoroutineContext, deferred: CompletableDeferred<T>) : Goal<T>,
Deferred<T> by deferred {
override val dependencies: Collection<Goal<*>> get() = emptyList() override val dependencies: Collection<Goal<*>> get() = emptyList()
override val status: String get() = "" override val status: String get() = ""
override val totalWork: Double get() = 0.0 override val totalWork: Double get() = 0.0
@ -94,7 +97,10 @@ fun <T, R> Goal<T>.pipe(block: suspend GoalMonitor.(T) -> R): Goal<R> = createGo
* Create a joining goal. * Create a joining goal.
* @param scope the scope for resulting goal. By default use first goal in list * @param scope the scope for resulting goal. By default use first goal in list
*/ */
fun <T, R> Collection<Goal<T>>.join(scope: CoroutineScope = first(), block: suspend GoalMonitor.(Collection<T>) -> R): Goal<R> = fun <T, R> Collection<Goal<T>>.join(
scope: CoroutineScope = first(),
block: suspend GoalMonitor.(Collection<T>) -> R
): Goal<R> =
scope.createGoal(this) { scope.createGoal(this) {
block(map { it.await() }) block(map { it.await() })
} }

View File

@ -31,6 +31,10 @@ interface OutputManager : Plugin {
/** /**
* Get an output with given [name], [stage] and reified content type * Get an output with given [name], [stage] and reified content type
*/ */
inline fun <reified T : Any> OutputManager.typed(name: Name, stage: Name = EmptyName, meta: Meta = EmptyMeta): Output<T> { inline fun <reified T : Any> OutputManager.typed(
name: Name,
stage: Name = EmptyName,
meta: Meta = EmptyMeta
): Output<T> {
return typed(T::class, name, stage, meta) return typed(T::class, name, stage, meta)
} }

View File

@ -124,7 +124,7 @@ object BinaryMetaFormat : MetaFormat {
} }
} }
class BinaryMetaFormatFactory: MetaFormatFactory{ class BinaryMetaFormatFactory : MetaFormatFactory {
override val name: String = "bin" override val name: String = "bin"
override val key: Short = 0x4249//BI override val key: Short = 0x4249//BI

View File

@ -74,7 +74,7 @@ class JsonMeta(val json: JsonObject) : Meta {
} }
} }
class JsonMetaFormatFactory: MetaFormatFactory{ class JsonMetaFormatFactory : MetaFormatFactory {
override val name: String = "json" override val name: String = "json"
override val key: Short = 0x4a53//"JS" override val key: Short = 0x4a53//"JS"

View File

@ -21,13 +21,13 @@ interface MetaFormatFactory {
fun build(): MetaFormat fun build(): MetaFormat
} }
fun Meta.asString(format: MetaFormat = JsonMetaFormat): String{ fun Meta.asString(format: MetaFormat = JsonMetaFormat): String {
val builder = BytePacketBuilder() val builder = BytePacketBuilder()
format.write(this,builder) format.write(this, builder)
return builder.build().readText() return builder.build().readText()
} }
fun MetaFormat.parse(str: String): Meta{ fun MetaFormat.parse(str: String): Meta {
return read(ByteReadPacket(str.toByteArray())) return read(ByteReadPacket(str.toByteArray()))
} }

View File

@ -4,9 +4,9 @@ import hep.dataforge.meta.buildMeta
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class MetaFormatTest{ class MetaFormatTest {
@Test @Test
fun testBinaryMetaFormat(){ fun testBinaryMetaFormat() {
val meta = buildMeta { val meta = buildMeta {
"a" to 22 "a" to 22
"node" to { "node" to {
@ -20,7 +20,7 @@ class MetaFormatTest{
} }
@Test @Test
fun testJsonMetaFormat(){ fun testJsonMetaFormat() {
val meta = buildMeta { val meta = buildMeta {
"a" to 22 "a" to 22
"node" to { "node" to {
@ -30,7 +30,7 @@ class MetaFormatTest{
} }
val string = meta.asString(JsonMetaFormat) val string = meta.asString(JsonMetaFormat)
val result = JsonMetaFormat.parse(string) val result = JsonMetaFormat.parse(string)
assertEquals(meta,result) assertEquals(meta, result)
} }
} }

View File

@ -11,25 +11,29 @@ import kotlin.reflect.KProperty
//TODO add caching for sealed nodes //TODO add caching for sealed nodes
class ValueDelegate(private val key: String? = null, private val default: Value? = null) : ReadOnlyProperty<Metoid, Value?> { class ValueDelegate(private val key: String? = null, private val default: Value? = null) :
ReadOnlyProperty<Metoid, Value?> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): Value? { override fun getValue(thisRef: Metoid, property: KProperty<*>): Value? {
return thisRef.meta[key ?: property.name]?.value ?: default return thisRef.meta[key ?: property.name]?.value ?: default
} }
} }
class StringDelegate(private val key: String? = null, private val default: String? = null) : ReadOnlyProperty<Metoid, String?> { class StringDelegate(private val key: String? = null, private val default: String? = null) :
ReadOnlyProperty<Metoid, String?> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): String? { override fun getValue(thisRef: Metoid, property: KProperty<*>): String? {
return thisRef.meta[key ?: property.name]?.string ?: default return thisRef.meta[key ?: property.name]?.string ?: default
} }
} }
class BooleanDelegate(private val key: String? = null, private val default: Boolean? = null) : ReadOnlyProperty<Metoid, Boolean?> { class BooleanDelegate(private val key: String? = null, private val default: Boolean? = null) :
ReadOnlyProperty<Metoid, Boolean?> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean? { override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean? {
return thisRef.meta[key ?: property.name]?.boolean ?: default return thisRef.meta[key ?: property.name]?.boolean ?: default
} }
} }
class NumberDelegate(private val key: String? = null, private val default: Number? = null) : ReadOnlyProperty<Metoid, Number?> { class NumberDelegate(private val key: String? = null, private val default: Number? = null) :
ReadOnlyProperty<Metoid, Number?> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): Number? { override fun getValue(thisRef: Metoid, property: KProperty<*>): Number? {
return thisRef.meta[key ?: property.name]?.number ?: default return thisRef.meta[key ?: property.name]?.number ?: default
} }
@ -37,25 +41,32 @@ class NumberDelegate(private val key: String? = null, private val default: Numbe
//Delegates with non-null values //Delegates with non-null values
class SafeStringDelegate(private val key: String? = null, private val default: String) : ReadOnlyProperty<Metoid, String> { class SafeStringDelegate(private val key: String? = null, private val default: String) :
ReadOnlyProperty<Metoid, String> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): String { override fun getValue(thisRef: Metoid, property: KProperty<*>): String {
return thisRef.meta[key ?: property.name]?.string ?: default return thisRef.meta[key ?: property.name]?.string ?: default
} }
} }
class SafeBooleanDelegate(private val key: String? = null, private val default: Boolean) : ReadOnlyProperty<Metoid, Boolean> { class SafeBooleanDelegate(private val key: String? = null, private val default: Boolean) :
ReadOnlyProperty<Metoid, Boolean> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean { override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean {
return thisRef.meta[key ?: property.name]?.boolean ?: default return thisRef.meta[key ?: property.name]?.boolean ?: default
} }
} }
class SafeNumberDelegate(private val key: String? = null, private val default: Number) : ReadOnlyProperty<Metoid, Number> { class SafeNumberDelegate(private val key: String? = null, private val default: Number) :
ReadOnlyProperty<Metoid, Number> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): Number { override fun getValue(thisRef: Metoid, property: KProperty<*>): Number {
return thisRef.meta[key ?: property.name]?.number ?: default return thisRef.meta[key ?: property.name]?.number ?: default
} }
} }
class SafeEnumDelegate<E : Enum<E>>(private val key: String? = null, private val default: E, private val resolver: (String) -> E) : ReadOnlyProperty<Metoid, E> { class SafeEnumDelegate<E : Enum<E>>(
private val key: String? = null,
private val default: E,
private val resolver: (String) -> E
) : ReadOnlyProperty<Metoid, E> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): E { override fun getValue(thisRef: Metoid, property: KProperty<*>): E {
return (thisRef.meta[key ?: property.name]?.string)?.let { resolver(it) } ?: default return (thisRef.meta[key ?: property.name]?.string)?.let { resolver(it) } ?: default
} }
@ -63,9 +74,10 @@ class SafeEnumDelegate<E : Enum<E>>(private val key: String? = null, private val
//Child node delegate //Child node delegate
class ChildDelegate<T>(private val key: String? = null, private val converter: (Meta) -> T) : ReadOnlyProperty<Metoid, T?> { class ChildDelegate<T>(private val key: String? = null, private val converter: (Meta) -> T) :
ReadOnlyProperty<Metoid, T?> {
override fun getValue(thisRef: Metoid, property: KProperty<*>): T? { override fun getValue(thisRef: Metoid, property: KProperty<*>): T? {
return thisRef.meta[key ?: property.name]?.node?.let { converter(it)} return thisRef.meta[key ?: property.name]?.node?.let { converter(it) }
} }
} }
@ -95,18 +107,20 @@ fun Metoid.boolean(default: Boolean, key: String? = null) = SafeBooleanDelegate(
@JvmName("safeNumber") @JvmName("safeNumber")
fun Metoid.number(default: Number, key: String? = null) = SafeNumberDelegate(key, default) fun Metoid.number(default: Number, key: String? = null) = SafeNumberDelegate(key, default)
inline fun <reified E : Enum<E>> Metoid.enum(default: E, key: String? = null) = SafeEnumDelegate(key, default) { enumValueOf(it) } inline fun <reified E : Enum<E>> Metoid.enum(default: E, key: String? = null) =
SafeEnumDelegate(key, default) { enumValueOf(it) }
/* Config delegates */ /* Config delegates */
class ValueConfigDelegate(private val key: String? = null, private val default: Value? = null) : ReadWriteProperty<Configurable, Value?> { class ValueConfigDelegate(private val key: String? = null, private val default: Value? = null) :
ReadWriteProperty<Configurable, Value?> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): Value? { override fun getValue(thisRef: Configurable, property: KProperty<*>): Value? {
return thisRef.config[key ?: property.name]?.value ?: default return thisRef.config[key ?: property.name]?.value ?: default
} }
override fun setValue(thisRef: Configurable, property: KProperty<*>, value: Value?) { override fun setValue(thisRef: Configurable, property: KProperty<*>, value: Value?) {
val name = key ?: property.name val name = key ?: property.name
if(value == null){ if (value == null) {
thisRef.config.remove(name) thisRef.config.remove(name)
} else { } else {
thisRef.config[name] = value thisRef.config[name] = value
@ -114,7 +128,8 @@ class ValueConfigDelegate(private val key: String? = null, private val default:
} }
} }
class StringConfigDelegate(private val key: String? = null, private val default: String? = null) : ReadWriteProperty<Configurable, String?> { class StringConfigDelegate(private val key: String? = null, private val default: String? = null) :
ReadWriteProperty<Configurable, String?> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): String? { override fun getValue(thisRef: Configurable, property: KProperty<*>): String? {
return thisRef.config[key ?: property.name]?.string ?: default return thisRef.config[key ?: property.name]?.string ?: default
} }
@ -124,7 +139,8 @@ class StringConfigDelegate(private val key: String? = null, private val default:
} }
} }
class BooleanConfigDelegate(private val key: String? = null, private val default: Boolean? = null) : ReadWriteProperty<Configurable, Boolean?> { class BooleanConfigDelegate(private val key: String? = null, private val default: Boolean? = null) :
ReadWriteProperty<Configurable, Boolean?> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): Boolean? { override fun getValue(thisRef: Configurable, property: KProperty<*>): Boolean? {
return thisRef.config[key ?: property.name]?.boolean ?: default return thisRef.config[key ?: property.name]?.boolean ?: default
} }
@ -134,7 +150,8 @@ class BooleanConfigDelegate(private val key: String? = null, private val default
} }
} }
class NumberConfigDelegate(private val key: String? = null, private val default: Number? = null) : ReadWriteProperty<Configurable, Number?> { class NumberConfigDelegate(private val key: String? = null, private val default: Number? = null) :
ReadWriteProperty<Configurable, Number?> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): Number? { override fun getValue(thisRef: Configurable, property: KProperty<*>): Number? {
return thisRef.config[key ?: property.name]?.number ?: default return thisRef.config[key ?: property.name]?.number ?: default
} }
@ -146,7 +163,8 @@ class NumberConfigDelegate(private val key: String? = null, private val default:
//Delegates with non-null values //Delegates with non-null values
class SafeStringConfigDelegate(private val key: String? = null, private val default: String) : ReadWriteProperty<Configurable, String> { class SafeStringConfigDelegate(private val key: String? = null, private val default: String) :
ReadWriteProperty<Configurable, String> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): String { override fun getValue(thisRef: Configurable, property: KProperty<*>): String {
return thisRef.config[key ?: property.name]?.string ?: default return thisRef.config[key ?: property.name]?.string ?: default
} }
@ -156,7 +174,8 @@ class SafeStringConfigDelegate(private val key: String? = null, private val defa
} }
} }
class SafeBooleanConfigDelegate(private val key: String? = null, private val default: Boolean) : ReadWriteProperty<Configurable, Boolean> { class SafeBooleanConfigDelegate(private val key: String? = null, private val default: Boolean) :
ReadWriteProperty<Configurable, Boolean> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): Boolean { override fun getValue(thisRef: Configurable, property: KProperty<*>): Boolean {
return thisRef.config[key ?: property.name]?.boolean ?: default return thisRef.config[key ?: property.name]?.boolean ?: default
} }
@ -166,7 +185,8 @@ class SafeBooleanConfigDelegate(private val key: String? = null, private val def
} }
} }
class SafeNumberConfigDelegate(private val key: String? = null, private val default: Number) : ReadWriteProperty<Configurable, Number> { class SafeNumberConfigDelegate(private val key: String? = null, private val default: Number) :
ReadWriteProperty<Configurable, Number> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): Number { override fun getValue(thisRef: Configurable, property: KProperty<*>): Number {
return thisRef.config[key ?: property.name]?.number ?: default return thisRef.config[key ?: property.name]?.number ?: default
} }
@ -176,7 +196,11 @@ class SafeNumberConfigDelegate(private val key: String? = null, private val defa
} }
} }
class SafeEnumvConfigDelegate<E : Enum<E>>(private val key: String? = null, private val default: E, private val resolver: (String) -> E) : ReadWriteProperty<Configurable, E> { class SafeEnumvConfigDelegate<E : Enum<E>>(
private val key: String? = null,
private val default: E,
private val resolver: (String) -> E
) : ReadWriteProperty<Configurable, E> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): E { override fun getValue(thisRef: Configurable, property: KProperty<*>): E {
return (thisRef.config[key ?: property.name]?.string)?.let { resolver(it) } ?: default return (thisRef.config[key ?: property.name]?.string)?.let { resolver(it) } ?: default
} }
@ -188,7 +212,8 @@ class SafeEnumvConfigDelegate<E : Enum<E>>(private val key: String? = null, priv
//Child node delegate //Child node delegate
class ChildConfigDelegate<T : Configurable>(private val key: String? = null, private val converter: (Config) -> T) : ReadWriteProperty<Configurable, T> { class ChildConfigDelegate<T : Configurable>(private val key: String? = null, private val converter: (Config) -> T) :
ReadWriteProperty<Configurable, T> {
override fun getValue(thisRef: Configurable, property: KProperty<*>): T { override fun getValue(thisRef: Configurable, property: KProperty<*>): T {
return converter(thisRef.config[key ?: property.name]?.node ?: Config()) return converter(thisRef.config[key ?: property.name]?.node ?: Config())
} }
@ -214,7 +239,8 @@ fun Configurable.number(default: Number? = null, key: String? = null) = NumberCo
fun Configurable.child(key: String? = null) = ChildConfigDelegate(key) { SimpleConfigurable(it) } fun Configurable.child(key: String? = null) = ChildConfigDelegate(key) { SimpleConfigurable(it) }
fun <T : Configurable> Configurable.child(key: String? = null, converter: (Config) -> T) = ChildConfigDelegate(key, converter) fun <T : Configurable> Configurable.child(key: String? = null, converter: (Config) -> T) =
ChildConfigDelegate(key, converter)
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) } //fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
@ -227,4 +253,5 @@ fun Configurable.boolean(default: Boolean, key: String? = null) = SafeBooleanCon
@JvmName("safeNumber") @JvmName("safeNumber")
fun Configurable.number(default: Number, key: String? = null) = SafeNumberConfigDelegate(key, default) fun Configurable.number(default: Number, key: String? = null) = SafeNumberConfigDelegate(key, default)
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) = SafeEnumvConfigDelegate(key, default) { enumValueOf(it) } inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) =
SafeEnumvConfigDelegate(key, default) { enumValueOf(it) }

View File

@ -10,14 +10,14 @@ import hep.dataforge.names.NameToken
class Laminate(layers: List<Meta>) : Meta { class Laminate(layers: List<Meta>) : Meta {
val layers: List<Meta> = layers.flatMap { val layers: List<Meta> = layers.flatMap {
if(it is Laminate){ if (it is Laminate) {
it.layers it.layers
} else{ } else {
listOf(it) listOf(it)
} }
} }
constructor(vararg layers: Meta): this(layers.asList()) constructor(vararg layers: Meta) : this(layers.asList())
override val items: Map<NameToken, MetaItem<out Meta>> override val items: Map<NameToken, MetaItem<out Meta>>
get() = layers.map { it.items.keys }.flatten().associateWith { key -> get() = layers.map { it.items.keys }.flatten().associateWith { key ->

View File

@ -6,7 +6,10 @@ import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.values.Value import hep.dataforge.values.Value
class MetaListener(val owner: Any? = null, val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit) { class MetaListener(
val owner: Any? = null,
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
) {
operator fun invoke(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) = action(name, oldItem, newItem) operator fun invoke(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) = action(name, oldItem, newItem)
} }
@ -130,16 +133,20 @@ fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
meta.items.forEach { entry -> meta.items.forEach { entry ->
val value = entry.value val value = entry.value
when (value) { when (value) {
is MetaItem.ValueItem -> setValue(entry.key.toName(),value.value) is MetaItem.ValueItem -> setValue(entry.key.toName(), value.value)
is MetaItem.NodeItem -> (this[entry.key.toName()] as? MetaItem.NodeItem)?.node?.update(value.node) is MetaItem.NodeItem -> (this[entry.key.toName()] as? MetaItem.NodeItem)?.node?.update(value.node)
?: run { setNode(entry.key.toName(),value.node)} ?: run { setNode(entry.key.toName(), value.node) }
} }
} }
} }
/* Same name siblings generation */ /* Same name siblings generation */
fun <M : MutableMeta<M>> M.setIndexed(name: Name, items: Iterable<MetaItem<M>>, queryFactory: (Int) -> String = { it.toString() }) { fun <M : MutableMeta<M>> M.setIndexed(
name: Name,
items: Iterable<MetaItem<M>>,
queryFactory: (Int) -> String = { it.toString() }
) {
val tokens = name.tokens.toMutableList() val tokens = name.tokens.toMutableList()
val last = tokens.last() val last = tokens.last()
items.forEachIndexed { index, meta -> items.forEachIndexed { index, meta ->
@ -149,7 +156,11 @@ fun <M : MutableMeta<M>> M.setIndexed(name: Name, items: Iterable<MetaItem<M>>,
} }
} }
fun <M : MutableMetaNode<M>> M.setIndexed(name: Name, metas: Iterable<Meta>, queryFactory: (Int) -> String = { it.toString() }) { fun <M : MutableMetaNode<M>> M.setIndexed(
name: Name,
metas: Iterable<Meta>,
queryFactory: (Int) -> String = { it.toString() }
) {
setIndexed(name, metas.map { wrap(name, it) }, queryFactory) setIndexed(name, metas.map { wrap(name, it) }, queryFactory)
} }

View File

@ -3,7 +3,7 @@ package hep.dataforge.meta
/** /**
* Marker interface for specifications * Marker interface for specifications
*/ */
interface Specification: Configurable{ interface Specification : Configurable {
operator fun get(name: String): MetaItem<Config>? = config[name] operator fun get(name: String): MetaItem<Config>? = config[name]
} }
@ -26,24 +26,29 @@ interface SpecificationBuilder<T : Specification> {
fun wrap(meta: Meta): T = wrap(meta.toConfig()) fun wrap(meta: Meta): T = wrap(meta.toConfig())
} }
fun <T : Specification> specification(wrapper: (Config) -> T): SpecificationBuilder<T> = object : SpecificationBuilder<T> { fun <T : Specification> specification(wrapper: (Config) -> T): SpecificationBuilder<T> =
object : SpecificationBuilder<T> {
override fun wrap(config: Config): T = wrapper(config) override fun wrap(config: Config): T = wrapper(config)
} }
/** /**
* Apply specified configuration to configurable * Apply specified configuration to configurable
*/ */
fun <T : Configurable, C : Specification, S : SpecificationBuilder<C>> T.configure(spec: S, action: C.() -> Unit) = apply { spec.update(config, action) } fun <T : Configurable, C : Specification, S : SpecificationBuilder<C>> T.configure(spec: S, action: C.() -> Unit) =
apply { spec.update(config, action) }
/** /**
* Update configuration using given specification * Update configuration using given specification
*/ */
fun <C : Specification, S : SpecificationBuilder<C>> Specification.update(spec: S, action: C.() -> Unit) = apply { spec.update(config, action) } fun <C : Specification, S : SpecificationBuilder<C>> Specification.update(spec: S, action: C.() -> Unit) =
apply { spec.update(config, action) }
/** /**
* Create a style based on given specification * Create a style based on given specification
*/ */
fun <C : Specification, S : SpecificationBuilder<C>> S.createStyle(action: C.() -> Unit): Meta = Config().also { update(it, action) } fun <C : Specification, S : SpecificationBuilder<C>> S.createStyle(action: C.() -> Unit): Meta =
Config().also { update(it, action) }
fun <C : Specification> Specification.spec(spec: SpecificationBuilder<C>, key: String? = null) = ChildConfigDelegate<C>(key) { spec.wrap(config) } fun <C : Specification> Specification.spec(spec: SpecificationBuilder<C>, key: String? = null) =
ChildConfigDelegate<C>(key) { spec.wrap(config) }

View File

@ -5,12 +5,12 @@ import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class MetaBuilderTest{ class MetaBuilderTest {
@Test @Test
fun testBuilder(){ fun testBuilder() {
val meta = buildMeta { val meta = buildMeta {
"a" to 22 "a" to 22
"b" to listOf(1,2,3) "b" to listOf(1, 2, 3)
this["c"] = "myValue".asValue() this["c"] = "myValue".asValue()
"node" to { "node" to {
"e" to 12.2 "e" to 12.2

View File

@ -3,17 +3,17 @@ package hep.dataforge.names
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class NameTest{ class NameTest {
@Test @Test
fun simpleName(){ fun simpleName() {
val name = "token1.token2.token3".toName() val name = "token1.token2.token3".toName()
assertEquals("token2", name[1].toString()) assertEquals("token2", name[1].toString())
} }
@Test @Test
fun equalityTest(){ fun equalityTest() {
val name1 = "token1.token2[2].token3".toName() val name1 = "token1.token2[2].token3".toName()
val name2 = "token1".toName() + "token2[2].token3" val name2 = "token1".toName() + "token2[2].token3"
assertEquals(name1,name2) assertEquals(name1, name2)
} }
} }