Replace EmptyName by Name.Empty
Composite builders for node descriptor
This commit is contained in:
parent
659fded3a5
commit
ce8be78549
@ -72,7 +72,7 @@ class TaglessEnvelopeFormat(
|
||||
properties[key] = value
|
||||
}
|
||||
//If can't read line, return envelope without data
|
||||
if (eof()) return SimpleEnvelope(Meta.empty, null)
|
||||
if (eof()) return SimpleEnvelope(Meta.EMPTY, null)
|
||||
line = readUtf8Line()
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ class TaglessEnvelopeFormat(
|
||||
line = readUtf8Line()
|
||||
offset += line.toUtf8Bytes().size.toUInt()
|
||||
} catch (ex: EOFException) {
|
||||
return PartialEnvelope(Meta.empty, offset.toUInt(), 0.toULong())
|
||||
return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ class TaglessEnvelopeFormat(
|
||||
}
|
||||
|
||||
do {
|
||||
line = readUtf8Line() ?: return PartialEnvelope(Meta.empty, offset.toUInt(), 0.toULong())
|
||||
line = readUtf8Line() ?: return PartialEnvelope(Meta.EMPTY, offset.toUInt(), 0.toULong())
|
||||
offset += line.toUtf8Bytes().size.toUInt()
|
||||
//returning an Envelope without data if end of input is reached
|
||||
} while (!line.startsWith(dataStart))
|
||||
|
@ -132,7 +132,7 @@ fun IOPlugin.readEnvelopeFile(
|
||||
return formatPeeker(path)?.let { format ->
|
||||
FileEnvelope(path, format)
|
||||
} ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary
|
||||
SimpleEnvelope(Meta.empty, path.asBinary())
|
||||
SimpleEnvelope(Meta.EMPTY, path.asBinary())
|
||||
} else null
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.False
|
||||
import hep.dataforge.values.True
|
||||
import hep.dataforge.values.Value
|
||||
@ -36,7 +37,7 @@ sealed class ItemDescriptor(override val config: Config) : Specific {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
var attributes by node()
|
||||
var attributes by child()
|
||||
|
||||
/**
|
||||
* True if the item is required
|
||||
@ -66,13 +67,54 @@ class NodeDescriptor(config: Config) : ItemDescriptor(config) {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
var default: Config? by node()
|
||||
var default: Config? by child()
|
||||
|
||||
/**
|
||||
* The map of children node descriptors
|
||||
*/
|
||||
val nodes: Map<String, NodeDescriptor>
|
||||
get() = config.getIndexed(NODE_KEY.asName()).entries.associate { (name, node) ->
|
||||
name to wrap(node.node ?: error("Node descriptor must be a node"))
|
||||
}
|
||||
|
||||
|
||||
fun node(name: String, descriptor: NodeDescriptor) {
|
||||
if (items.keys.contains(name)) error("The key $name already exists in descriptor")
|
||||
val token = NameToken(NODE_KEY, name)
|
||||
config[token] = descriptor.config
|
||||
}
|
||||
|
||||
|
||||
fun node(name: String, block: NodeDescriptor.() -> Unit) {
|
||||
val token = NameToken(NODE_KEY, name)
|
||||
if (config[token] == null) {
|
||||
config[token] = NodeDescriptor(block)
|
||||
} else {
|
||||
NodeDescriptor.update(config[token].node ?: error("Node expected"), block)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNode(name: Name): NodeDescriptor {
|
||||
return when (name.length) {
|
||||
0 -> this
|
||||
1 -> {
|
||||
val token = NameToken(NODE_KEY, name.toString())
|
||||
val config: Config = config[token].node ?: Config().also { config[token] = it }
|
||||
wrap(config)
|
||||
}
|
||||
else -> buildNode(name.first()?.asName()!!).buildNode(name.cutFirst())
|
||||
}
|
||||
}
|
||||
|
||||
fun node(name: Name, block: NodeDescriptor.() -> Unit) {
|
||||
buildNode(name).apply(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of value descriptors
|
||||
*/
|
||||
val values: Map<String, ValueDescriptor>
|
||||
get() = config.getIndexed(VALUE_KEY.toName()).entries.associate { (name, node) ->
|
||||
get() = config.getIndexed(VALUE_KEY.asName()).entries.associate { (name, node) ->
|
||||
name to ValueDescriptor.wrap(node.node ?: error("Value descriptor must be a node"))
|
||||
}
|
||||
|
||||
@ -89,23 +131,9 @@ class NodeDescriptor(config: Config) : ItemDescriptor(config) {
|
||||
value(name, ValueDescriptor { this.name = name }.apply(block))
|
||||
}
|
||||
|
||||
/**
|
||||
* The map of children node descriptors
|
||||
*/
|
||||
val nodes: Map<String, NodeDescriptor>
|
||||
get() = config.getIndexed(NODE_KEY.toName()).entries.associate { (name, node) ->
|
||||
name to wrap(node.node ?: error("Node descriptor must be a node"))
|
||||
}
|
||||
|
||||
|
||||
fun node(name: String, descriptor: NodeDescriptor) {
|
||||
if (items.keys.contains(name)) error("The key $name already exists in descriptor")
|
||||
val token = NameToken(NODE_KEY, name)
|
||||
config[token] = descriptor.config
|
||||
}
|
||||
|
||||
fun node(name: String, block: NodeDescriptor.() -> Unit) {
|
||||
node(name, invoke { this.name = name }.apply(block))
|
||||
fun value(name: Name, block: ValueDescriptor.() -> Unit) {
|
||||
require(name.length >= 1) { "Name length for value descriptor must be non-empty" }
|
||||
buildNode(name.cutLast()).value(name.last().toString())
|
||||
}
|
||||
|
||||
val items: Map<String, ItemDescriptor> get() = nodes + values
|
||||
|
@ -60,7 +60,7 @@ interface Meta : MetaRepr {
|
||||
*/
|
||||
const val VALUE_KEY = "@value"
|
||||
|
||||
val empty: EmptyMeta = EmptyMeta
|
||||
val EMPTY: EmptyMeta = EmptyMeta
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: Name? = null
|
||||
|
||||
/* Node delegates */
|
||||
|
||||
fun Configurable.node(key: Name? = null): MutableNodeDelegate<Config> = MutableNodeDelegate(config, key)
|
||||
fun Configurable.child(key: Name? = null): MutableNodeDelegate<Config> = MutableNodeDelegate(config, key)
|
||||
|
||||
fun <T : Specific> Configurable.spec(spec: Specification<T>, key: Name? = null) =
|
||||
MutableMorphDelegate(config, key) { spec.wrap(it) }
|
||||
@ -133,5 +133,5 @@ fun Configurable.doubleArray(key: Name? = null): ReadWriteDelegateWrapper<Value?
|
||||
?: doubleArrayOf()
|
||||
}
|
||||
|
||||
fun <T : Configurable> Configurable.node(key: Name? = null, converter: (Meta) -> T) =
|
||||
fun <T : Configurable> Configurable.child(key: Name? = null, converter: (Meta) -> T) =
|
||||
MutableMorphDelegate(config, key, converter)
|
||||
|
@ -144,7 +144,7 @@ fun Meta.boolean(default: Boolean? = null, key: String? = null) = BooleanDelegat
|
||||
|
||||
fun Meta.number(default: Number? = null, key: String? = null) = NumberDelegate(this, key, default)
|
||||
|
||||
fun Meta.node(key: String? = null) = ChildDelegate(this, key) { it }
|
||||
fun Meta.child(key: String? = null) = ChildDelegate(this, key) { it }
|
||||
|
||||
@JvmName("safeString")
|
||||
fun Meta.string(default: String, key: String? = null) =
|
||||
@ -400,7 +400,7 @@ fun <M : MutableMeta<M>> M.boolean(default: Boolean? = null, key: Name? = null)
|
||||
fun <M : MutableMeta<M>> M.number(default: Number? = null, key: Name? = null) =
|
||||
MutableNumberDelegate(this, key, default)
|
||||
|
||||
fun <M : MutableMeta<M>> M.node(key: Name? = null) =
|
||||
fun <M : MutableMeta<M>> M.child(key: Name? = null) =
|
||||
MutableNodeDelegate(this, key)
|
||||
|
||||
@JvmName("safeString")
|
||||
|
@ -53,6 +53,8 @@ class Name(val tokens: List<NameToken>) {
|
||||
|
||||
companion object {
|
||||
const val NAME_SEPARATOR = "."
|
||||
|
||||
val EMPTY = Name(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ data class NameToken(val body: String, val index: String = "") {
|
||||
* This operation is rather heavy so it should be used with care in high performance code.
|
||||
*/
|
||||
fun String.toName(): Name {
|
||||
if (isBlank()) return EmptyName
|
||||
if (isBlank()) return Name.EMPTY
|
||||
val tokens = sequence {
|
||||
var bodyBuilder = StringBuilder()
|
||||
var queryBuilder = StringBuilder()
|
||||
@ -139,7 +141,7 @@ fun String.toName(): Name {
|
||||
* Convert the [String] to a [Name] by simply wrapping it in a single name token without parsing.
|
||||
* The input string could contain dots and braces, but they are just escaped, not parsed.
|
||||
*/
|
||||
fun String.asName(): Name = if (isBlank()) EmptyName else NameToken(this).asName()
|
||||
fun String.asName(): Name = if (isBlank()) Name.EMPTY else NameToken(this).asName()
|
||||
|
||||
operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + other.tokens)
|
||||
|
||||
@ -153,8 +155,6 @@ fun Name.appendLeft(other: String): Name = NameToken(other) + this
|
||||
|
||||
fun NameToken.asName() = Name(listOf(this))
|
||||
|
||||
val EmptyName = Name(emptyList())
|
||||
|
||||
fun Name.isEmpty(): Boolean = this.length == 0
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,6 @@ import hep.dataforge.context.*
|
||||
import hep.dataforge.context.PluginTag.Companion.DATAFORGE_GROUP
|
||||
import hep.dataforge.meta.EmptyMeta
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -24,7 +23,7 @@ interface OutputManager {
|
||||
operator fun <T : Any> get(
|
||||
type: KClass<out T>,
|
||||
name: Name,
|
||||
stage: Name = EmptyName,
|
||||
stage: Name = Name.EMPTY,
|
||||
meta: Meta = EmptyMeta
|
||||
): Renderer<T>
|
||||
}
|
||||
@ -39,7 +38,7 @@ val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager(
|
||||
*/
|
||||
inline operator fun <reified T : Any> OutputManager.get(
|
||||
name: Name,
|
||||
stage: Name = EmptyName,
|
||||
stage: Name = Name.EMPTY,
|
||||
meta: Meta = EmptyMeta
|
||||
): Renderer<T> {
|
||||
return get(T::class, name, stage, meta)
|
||||
@ -48,7 +47,7 @@ inline operator fun <reified T : Any> OutputManager.get(
|
||||
/**
|
||||
* Directly render an object using the most suitable renderer
|
||||
*/
|
||||
fun OutputManager.render(obj: Any, name: Name, stage: Name = EmptyName, meta: Meta = EmptyMeta) =
|
||||
fun OutputManager.render(obj: Any, name: Name, stage: Name = Name.EMPTY, meta: Meta = EmptyMeta) =
|
||||
get(obj::class, name, stage).render(obj, meta)
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,10 @@ import hep.dataforge.data.filter
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.meta.buildMeta
|
||||
import hep.dataforge.names.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.isEmpty
|
||||
import hep.dataforge.names.plus
|
||||
|
||||
/**
|
||||
* A dependency of the task which allows to lazily create a data tree for single dependency
|
||||
@ -15,7 +18,7 @@ sealed class Dependency : MetaRepr {
|
||||
abstract fun apply(workspace: Workspace): DataNode<Any>
|
||||
}
|
||||
|
||||
class DataDependency(val filter: DataFilter, val placement: Name = EmptyName) : Dependency() {
|
||||
class DataDependency(val filter: DataFilter, val placement: Name = Name.EMPTY) : Dependency() {
|
||||
override fun apply(workspace: Workspace): DataNode<Any> {
|
||||
val result = workspace.data.filter(filter)
|
||||
return if (placement.isEmpty()) {
|
||||
@ -31,7 +34,7 @@ class DataDependency(val filter: DataFilter, val placement: Name = EmptyName) :
|
||||
}
|
||||
}
|
||||
|
||||
class AllDataDependency(val placement: Name = EmptyName) : Dependency() {
|
||||
class AllDataDependency(val placement: Name = Name.EMPTY) : Dependency() {
|
||||
override fun apply(workspace: Workspace): DataNode<Any> = if (placement.isEmpty()) {
|
||||
workspace.data
|
||||
} else {
|
||||
@ -46,7 +49,7 @@ class AllDataDependency(val placement: Name = EmptyName) : Dependency() {
|
||||
|
||||
abstract class TaskDependency<out T : Any>(
|
||||
val meta: Meta,
|
||||
val placement: Name = EmptyName
|
||||
val placement: Name = Name.EMPTY
|
||||
) : Dependency() {
|
||||
abstract fun resolveTask(workspace: Workspace): Task<T>
|
||||
|
||||
|
@ -7,7 +7,6 @@ import hep.dataforge.meta.DFBuilder
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.string
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.isEmpty
|
||||
import hep.dataforge.names.toName
|
||||
@ -57,7 +56,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
|
||||
block: TaskEnv.(DataNode<*>) -> DataNode<R>
|
||||
) {
|
||||
dataTransforms += DataTransformation(from, to) { context, model, data ->
|
||||
val env = TaskEnv(EmptyName, model.meta, context, data)
|
||||
val env = TaskEnv(Name.EMPTY, model.meta, context, data)
|
||||
env.block(data)
|
||||
}
|
||||
}
|
||||
@ -70,7 +69,7 @@ class TaskBuilder<R : Any>(val name: Name, val type: KClass<out R>) {
|
||||
) {
|
||||
dataTransforms += DataTransformation(from, to) { context, model, data ->
|
||||
data.ensureType(inputType)
|
||||
val env = TaskEnv(EmptyName, model.meta, context, data)
|
||||
val env = TaskEnv(Name.EMPTY, model.meta, context, data)
|
||||
env.block(data.cast(inputType))
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import hep.dataforge.data.DataFilter
|
||||
import hep.dataforge.data.DataTree
|
||||
import hep.dataforge.data.DataTreeBuilder
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.toName
|
||||
@ -68,21 +67,21 @@ interface TaskDependencyContainer {
|
||||
*/
|
||||
fun TaskDependencyContainer.dependsOn(
|
||||
name: Name,
|
||||
placement: Name = EmptyName,
|
||||
placement: Name = Name.EMPTY,
|
||||
meta: Meta = defaultMeta
|
||||
): WorkspaceTaskDependency =
|
||||
WorkspaceTaskDependency(name, meta, placement).also { add(it) }
|
||||
|
||||
fun TaskDependencyContainer.dependsOn(
|
||||
name: String,
|
||||
placement: Name = EmptyName,
|
||||
placement: Name = Name.EMPTY,
|
||||
meta: Meta = defaultMeta
|
||||
): WorkspaceTaskDependency =
|
||||
dependsOn(name.toName(), placement, meta)
|
||||
|
||||
fun <T : Any> TaskDependencyContainer.dependsOn(
|
||||
task: Task<T>,
|
||||
placement: Name = EmptyName,
|
||||
placement: Name = Name.EMPTY,
|
||||
meta: Meta = defaultMeta
|
||||
): DirectTaskDependency<T> =
|
||||
DirectTaskDependency(task, meta, placement).also { add(it) }
|
||||
@ -96,7 +95,7 @@ fun <T : Any> TaskDependencyContainer.dependsOn(
|
||||
|
||||
fun <T : Any> TaskDependencyContainer.dependsOn(
|
||||
task: Task<T>,
|
||||
placement: Name = EmptyName,
|
||||
placement: Name = Name.EMPTY,
|
||||
metaBuilder: MetaBuilder.() -> Unit
|
||||
): DirectTaskDependency<T> =
|
||||
dependsOn(task, placement, buildMeta(metaBuilder))
|
||||
@ -120,7 +119,7 @@ fun TaskDependencyContainer.data(pattern: String? = null, from: String? = null,
|
||||
/**
|
||||
* Add all data as root node
|
||||
*/
|
||||
fun TaskDependencyContainer.allData(to: Name = EmptyName) = AllDataDependency(to).also { add(it) }
|
||||
fun TaskDependencyContainer.allData(to: Name = Name.EMPTY) = AllDataDependency(to).also { add(it) }
|
||||
|
||||
/**
|
||||
* A builder for [TaskModel]
|
||||
|
@ -5,7 +5,6 @@ import hep.dataforge.context.ContextBuilder
|
||||
import hep.dataforge.data.DataNode
|
||||
import hep.dataforge.data.DataTreeBuilder
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.isEmpty
|
||||
import hep.dataforge.names.toName
|
||||
@ -32,7 +31,7 @@ fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBuilder.(
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> WorkspaceBuilder.data(
|
||||
name: Name = EmptyName,
|
||||
name: Name = Name.EMPTY,
|
||||
noinline block: DataTreeBuilder<T>.() -> Unit
|
||||
): DataNode<T> {
|
||||
val node = DataTreeBuilder(T::class).apply(block)
|
||||
@ -47,7 +46,7 @@ inline fun <reified T : Any> WorkspaceBuilder.data(
|
||||
|
||||
@JvmName("rawData")
|
||||
fun WorkspaceBuilder.data(
|
||||
name: Name = EmptyName,
|
||||
name: Name = Name.EMPTY,
|
||||
block: DataTreeBuilder<Any>.() -> Unit
|
||||
): DataNode<Any> = data<Any>(name, block)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user