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 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 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/properties/ReadOnlyProperty;
public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)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 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;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 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; 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 final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
public synthetic fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider; public synthetic fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme; 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 synthetic fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun write (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme; 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 { 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 empty ()Lhep/dataforge/meta/MutableItemProvider;
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)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 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 final class hep/dataforge/meta/Specification$DefaultImpls {
public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider; 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 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 { 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 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; public abstract fun getItems ()Ljava/util/Map;
} }

View File

@ -1,9 +1,7 @@
package hep.dataforge.meta package hep.dataforge.meta
import hep.dataforge.meta.MetaItem.NodeItem import hep.dataforge.meta.MetaItem.NodeItem
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.NameToken
import hep.dataforge.names.toName
public fun interface ItemProvider { public fun interface ItemProvider {
//getItem used instead of get in order to provide extension freedom //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) 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] * 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 * 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 { public fun ItemProvider.withDefault(default: ItemProvider): ItemProvider = ItemProvider {
this[it] ?: default[it] 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 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
import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY
import hep.dataforge.meta.descriptors.NodeDescriptor 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 //Use these methods to customize JSON key mapping
@Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER") @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) //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.meta.MetaItem.ValueItem
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.values.Value import hep.dataforge.values.Value
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json 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 * 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 { public interface TypedMeta<out M : TypedMeta<M>> : Meta {
override val items: Map<NameToken, MetaItem<M>> 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 * 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) { public operator fun <M : TypedMeta<M>> M?.get(name: Name): MetaItem<M>? = this?.getItem(name)
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(key: String): MetaItem<M>? = this[key.toName()] 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()] 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.NodeItem
import hep.dataforge.meta.MetaItem.ValueItem import hep.dataforge.meta.MetaItem.ValueItem
import hep.dataforge.values.* import hep.dataforge.values.*
import kotlinx.serialization.Serializable
/** /**
* A member of the meta tree. Could be represented as one of following: * 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<*>?.long: Long? get() = number?.toLong()
public val MetaItem<*>?.short: Short? get() = number?.toShort() 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 this.value.value as E
} else { } else {
string?.let { enumValueOf<E>(it) } string?.let { enumValueOf<E>(it) }

View File

@ -28,7 +28,6 @@ public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractTypedMet
//itemChanged(key.asName(), oldItem, newItem) //itemChanged(key.asName(), oldItem, newItem)
} }
@Suppress("UNCHECKED_CAST")
protected fun wrapItem(item: MetaItem<*>?): MetaItem<M>? = when (item) { protected fun wrapItem(item: MetaItem<*>?): MetaItem<M>? = when (item) {
null -> null null -> null
is MetaItem.ValueItem -> item 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") 0 -> error("Can't setValue meta item for empty name")
1 -> { 1 -> {
val token = name.firstOrNull()!! 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)) replaceItem(token, oldItem, wrapItem(item))
} }
else -> { 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 * A specification for simplified generation of wrappers
*/ */
public open class SchemeSpec<T : Scheme>( 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 { ) : 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 { emptyBuilder().apply {
this.items = config this.items = target
this.default = defaultProvider this.default = defaultProvider
this.descriptor = descriptor this.descriptor = descriptor
} }
@ -100,8 +100,8 @@ public open class SchemeSpec<T : Scheme>(
override fun read(items: ItemProvider): T = override fun read(items: ItemProvider): T =
builder(Config(), items, descriptor) builder(Config(), items, descriptor)
override fun write(config: Config, defaultProvider: ItemProvider): T = override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): T =
builder(config, defaultProvider, descriptor) builder(target, defaultProvider, descriptor)
//TODO Generate descriptor from Scheme class //TODO Generate descriptor from Scheme class
override val descriptor: NodeDescriptor? get() = null 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] * 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 * 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 import kotlin.test.assertEquals
class SpecificationTest { 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) var list by numberList(1, 2, 3)
companion object : Specification<TestStyled> { companion object : Specification<TestStyled> {
override fun read(items: ItemProvider): TestStyled = TestStyled(Config(), items) override fun read(items: ItemProvider): TestStyled = TestStyled(Config(), items)
override fun write(config: Config, defaultProvider: ItemProvider): TestStyled = override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): TestStyled =
TestStyled(config, defaultProvider) TestStyled(target, defaultProvider)
} }
} }