Meta subtyping and get by empty name.

This commit is contained in:
Alexander Nozik 2019-12-22 20:30:47 +03:00
parent effac131de
commit f9ae9348e2
2 changed files with 23 additions and 16 deletions

View File

@ -66,8 +66,14 @@ interface Meta : MetaRepr {
/* Get operations*/
/**
* Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [Meta.items] of a parent node.
*
* If [name] is empty reture current [Meta] as a [NodeItem]
*/
operator fun Meta?.get(name: Name): MetaItem<*>? {
if (this == null) return null
if (name.isEmpty()) return NodeItem(this)
return name.first()?.let { token ->
val tail = name.cutFirst()
when (tail.length) {
@ -78,6 +84,9 @@ operator fun Meta?.get(name: Name): MetaItem<*>? {
}
operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
/**
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
*/
operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
/**
@ -113,12 +122,16 @@ operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().ite
/**
* A meta node that ensures that all of its descendants has at least the same type
*/
interface MetaNode<M : MetaNode<M>> : Meta {
interface MetaNode<out M : MetaNode<M>> : Meta {
override val items: Map<NameToken, MetaItem<M>>
}
operator fun <M : MetaNode<M>> MetaNode<M>?.get(name: Name): MetaItem<M>? {
/**
* The same as [Meta.get], but with specific node type
*/
operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? {
if (this == null) return null
if (name.isEmpty()) return NodeItem(this)
return name.first()?.let { token ->
val tail = name.cutFirst()
when (tail.length) {
@ -128,17 +141,9 @@ operator fun <M : MetaNode<M>> MetaNode<M>?.get(name: Name): MetaItem<M>? {
}
}
operator fun <M : MetaNode<M>> MetaNode<M>?.get(key: String): MetaItem<M>? = if (this == null) {
null
} else {
this[key.toName()]
}
operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
operator fun <M : MetaNode<M>> MetaNode<M>?.get(key: NameToken): MetaItem<M>? = if (this == null) {
null
} else {
this[key.asName()]
}
operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
/**
* Equals, hashcode and to string for any meta

View File

@ -3,7 +3,7 @@ package hep.dataforge.meta
import hep.dataforge.names.*
import hep.dataforge.values.Value
interface MutableMeta<M : MutableMeta<M>> : MetaNode<M> {
interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M> {
override val items: Map<NameToken, MetaItem<M>>
operator fun set(name: Name, item: MetaItem<*>?)
// fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
@ -54,7 +54,8 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
0 -> error("Can't setValue meta item for empty name")
1 -> {
val token = name.first()!!
replaceItem(token, get(name), wrapItem(item))
@Suppress("UNCHECKED_CAST") val oldItem: MetaItem<M>? = get(name) as? MetaItem<M>
replaceItem(token, oldItem, wrapItem(item))
}
else -> {
val token = name.first()!!
@ -71,6 +72,7 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
@Suppress("NOTHING_TO_INLINE")
inline fun MutableMeta<*>.remove(name: Name) = set(name, null)
@Suppress("NOTHING_TO_INLINE")
inline fun MutableMeta<*>.remove(name: String) = remove(name.toName())