This commit is contained in:
Alexander Nozik 2020-12-23 21:22:47 +03:00
parent 617ed13efa
commit e931994b75
10 changed files with 69 additions and 74 deletions

View File

@ -56,13 +56,6 @@ public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/l
public abstract interface annotation class hep/dataforge/meta/DFExperimental : java/lang/annotation/Annotation {
}
public final class hep/dataforge/meta/GetIndexedKt {
public static final fun getIndexed (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/TypedMeta;Ljava/lang/String;)Ljava/util/Map;
}
public final class hep/dataforge/meta/ItemDelegateKt {
public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
@ -135,6 +128,11 @@ public final class hep/dataforge/meta/ItemProvider$Companion {
public final class hep/dataforge/meta/ItemProviderKt {
public static final fun get (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public static final fun get (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Ljava/util/Map;
public static final fun getIndexed (Lhep/dataforge/meta/TypedMeta;Ljava/lang/String;)Ljava/util/Map;
public static final fun getRootNode (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Meta;
public static final fun withDefault (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/ItemProvider;
}
@ -492,8 +490,8 @@ public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, h
public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
public synthetic fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
public synthetic fun write (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun write (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
public synthetic fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
}
public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractTypedMeta {
@ -509,13 +507,13 @@ public abstract interface class hep/dataforge/meta/Specification {
public abstract fun empty ()Lhep/dataforge/meta/MutableItemProvider;
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
public abstract fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public abstract fun write (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public abstract fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
}
public final class hep/dataforge/meta/Specification$DefaultImpls {
public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
public static synthetic fun write$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
public static synthetic fun write$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
}
public final class hep/dataforge/meta/SpecificationKt {
@ -529,6 +527,7 @@ public final class hep/dataforge/meta/SpecificationKt {
}
public abstract interface class hep/dataforge/meta/TypedMeta : hep/dataforge/meta/Meta {
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public abstract fun getItems ()Ljava/util/Map;
}

View File

@ -1,9 +1,7 @@
package hep.dataforge.meta
import hep.dataforge.meta.MetaItem.NodeItem
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.toName
import hep.dataforge.names.*
public fun interface ItemProvider {
//getItem used instead of get in order to provide extension freedom
@ -24,10 +22,15 @@ public fun interface ItemProvider {
*/
public operator fun ItemProvider?.get(name: Name): MetaItem<*>? = this?.getItem(name)
/**
* The root node of this item provider if it is present
*/
public val ItemProvider.rootNode: Meta? get() = get(Name.EMPTY).node
/**
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
*/
public operator fun ItemProvider?.get(key: String): MetaItem<*>? = get(key.toName())
public operator fun ItemProvider?.get(key: String): MetaItem<*>? = this?.get(key.toName())
/**
* Create a provider that uses given provider for default values if those are not found in this provider
@ -35,3 +38,36 @@ public operator fun ItemProvider?.get(key: String): MetaItem<*>? = get(key.toNam
public fun ItemProvider.withDefault(default: ItemProvider): ItemProvider = ItemProvider {
this[it] ?: default[it]
}
/**
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
* against which indexes of elements are matched.
*/
public fun ItemProvider.getIndexed(name: Name): Map<String?, MetaItem<*>> {
val root: Meta = when (name.length) {
0 -> error("Can't use empty name for 'getIndexed'")
1 -> this.rootNode ?: return emptyMap()
else -> this[name.cutLast()].node ?: return emptyMap()
}
val (body, index) = name.lastOrNull()!!
return if (index == null) {
root.items.filter { it.key.body == body }.mapKeys { it.key.index }
} else {
val regex = index.toRegex()
root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
.mapKeys { it.key.index }
}
}
public fun ItemProvider.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
/**
* Get all items matching given name.
*/
@Suppress("UNCHECKED_CAST")
public fun <M : TypedMeta<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
(this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
public fun <M : TypedMeta<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> =
getIndexed(name.toName())

View File

@ -2,7 +2,6 @@
package hep.dataforge.meta
import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
import hep.dataforge.meta.descriptors.ItemDescriptor
import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY
import hep.dataforge.meta.descriptors.NodeDescriptor
@ -26,7 +25,7 @@ public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement = when
//Use these methods to customize JSON key mapping
@Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER")
private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes["jsonName"].string ?: toString()
private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes?.get("jsonName").string ?: toString()
//private fun NodeDescriptor?.getDescriptor(key: String) = this?.items?.get(key)

View File

@ -4,7 +4,6 @@ import hep.dataforge.meta.MetaItem.NodeItem
import hep.dataforge.meta.MetaItem.ValueItem
import hep.dataforge.names.*
import hep.dataforge.values.Value
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@ -63,7 +62,7 @@ public interface Meta : MetaRepr, ItemProvider {
}
}
public operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
public operator fun Meta.get(token: NameToken): MetaItem<*>? = items.get(token)
/**
* Get a sequence of [Name]-[Value] pairs
@ -98,17 +97,17 @@ public operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = itemSeq
*/
public interface TypedMeta<out M : TypedMeta<M>> : Meta {
override val items: Map<NameToken, MetaItem<M>>
@Suppress("UNCHECKED_CAST")
override fun getItem(name: Name): MetaItem<M>? = super.getItem(name)?.let { it as MetaItem<M> }
//Typed meta guarantees that all children have M type
}
/**
* The same as [Meta.get], but with specific node type
*/
public operator fun <M : TypedMeta<M>> M?.get(name: Name): MetaItem<M>? = if (this == null) {
null
} else {
@Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
(this as Meta).get(name) as MetaItem<M>? // Do not change
}
public operator fun <M : TypedMeta<M>> M?.get(name: Name): MetaItem<M>? = this?.getItem(name)
public operator fun <M : TypedMeta<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
public operator fun <M : TypedMeta<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]

View File

@ -3,7 +3,6 @@ package hep.dataforge.meta
import hep.dataforge.meta.MetaItem.NodeItem
import hep.dataforge.meta.MetaItem.ValueItem
import hep.dataforge.values.*
import kotlinx.serialization.Serializable
/**
* A member of the meta tree. Could be represented as one of following:
@ -72,7 +71,7 @@ public val MetaItem<*>?.int: Int? get() = number?.toInt()
public val MetaItem<*>?.long: Long? get() = number?.toLong()
public val MetaItem<*>?.short: Short? get() = number?.toShort()
public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is MetaItem.ValueItem && this.value is EnumValue<*>) {
public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
this.value.value as E
} else {
string?.let { enumValueOf<E>(it) }

View File

@ -28,7 +28,6 @@ public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractTypedMet
//itemChanged(key.asName(), oldItem, newItem)
}
@Suppress("UNCHECKED_CAST")
protected fun wrapItem(item: MetaItem<*>?): MetaItem<M>? = when (item) {
null -> null
is MetaItem.ValueItem -> item
@ -50,7 +49,7 @@ public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractTypedMet
0 -> error("Can't setValue meta item for empty name")
1 -> {
val token = name.firstOrNull()!!
@Suppress("UNCHECKED_CAST") val oldItem: MetaItem<M>? = getItem(name) as? MetaItem<M>
val oldItem: MetaItem<M>? = getItem(name)
replaceItem(token, oldItem, wrapItem(item))
}
else -> {

View File

@ -86,12 +86,12 @@ public inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit): T = apply
* A specification for simplified generation of wrappers
*/
public open class SchemeSpec<T : Scheme>(
private val builder: (config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor?) -> T,
private val builder: (target: MutableItemProvider, defaultProvider: ItemProvider, descriptor: NodeDescriptor?) -> T,
) : Specification<T>, Described {
public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider, descriptor: NodeDescriptor? ->
public constructor(emptyBuilder: () -> T) : this({ target: MutableItemProvider, defaultProvider: ItemProvider, descriptor: NodeDescriptor? ->
emptyBuilder().apply {
this.items = config
this.items = target
this.default = defaultProvider
this.descriptor = descriptor
}
@ -100,8 +100,8 @@ public open class SchemeSpec<T : Scheme>(
override fun read(items: ItemProvider): T =
builder(Config(), items, descriptor)
override fun write(config: Config, defaultProvider: ItemProvider): T =
builder(config, defaultProvider, descriptor)
override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): T =
builder(target, defaultProvider, descriptor)
//TODO Generate descriptor from Scheme class
override val descriptor: NodeDescriptor? get() = null

View File

@ -19,7 +19,7 @@ public interface Specification<T : MutableItemProvider> {
/**
* Wrap [MutableItemProvider], using it as inner storage (changes to [Specification] are reflected on [MutableItemProvider]
*/
public fun write(config: Config, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
public fun write(target: MutableItemProvider, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
/**
* Generate an empty object

View File

@ -1,36 +0,0 @@
package hep.dataforge.meta
import hep.dataforge.names.*
/**
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
* against which indexes of elements are matched.
*/
public fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
val root = when (name.length) {
0 -> error("Can't use empty name for 'getIndexed'")
1 -> this
else -> this[name.cutLast()].node ?: return emptyMap()
}
val (body, index) = name.lastOrNull()!!
return if (index == null) {
root.items.filter { it.key.body == body }.mapKeys { it.key.index }
} else {
val regex = index.toRegex()
root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
.mapKeys { it.key.index }
}
}
public fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
/**
* Get all items matching given name.
*/
@Suppress("UNCHECKED_CAST")
public fun <M : TypedMeta<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
(this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
public fun <M : TypedMeta<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> =
getIndexed(name.toName())

View File

@ -4,14 +4,14 @@ import kotlin.test.Test
import kotlin.test.assertEquals
class SpecificationTest {
class TestStyled(config: Config, default: ItemProvider?) : Scheme(config, default) {
class TestStyled(target: MutableItemProvider, default: ItemProvider?) : Scheme(target, default) {
var list by numberList(1, 2, 3)
companion object : Specification<TestStyled> {
override fun read(items: ItemProvider): TestStyled = TestStyled(Config(), items)
override fun write(config: Config, defaultProvider: ItemProvider): TestStyled =
TestStyled(config, defaultProvider)
override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): TestStyled =
TestStyled(target, defaultProvider)
}
}