Fixed getAll bug

This commit is contained in:
Alexander Nozik 2019-03-26 12:21:33 +03:00
parent ad23478a79
commit 63cd209f58
10 changed files with 153 additions and 74 deletions

View File

@ -111,6 +111,42 @@ subprojects {
}
}
sourceSets {
val commonMain by getting {
dependencies {
api(kotlin("stdlib"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
api(kotlin("stdlib-jdk8"))
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val jsMain by getting {
dependencies {
api(kotlin("stdlib-js"))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
targets.all {
sourceSets.all {
languageSettings.progressiveMode = true

View File

@ -22,6 +22,7 @@ kotlin {
val jvmMain by getting {
dependencies {
api("io.github.microutils:kotlin-logging:1.6.10")
api("ch.qos.logback:logback-classic:1.2.3")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
}
}

View File

@ -1,6 +1,9 @@
package hep.dataforge.context
import hep.dataforge.meta.*
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta
import kotlin.reflect.KClass
/**
@ -112,7 +115,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
fun load(tag: PluginTag, meta: Meta = EmptyMeta): Plugin {
val loaded = get(tag, false)
return when {
loaded == null -> load(PluginRepository.fetch(tag)).configure(meta)
loaded == null -> load(PluginRepository.fetch(tag,meta))
loaded.config == meta -> loaded // if meta is the same, return existing plugin
else -> throw RuntimeException("Can't load plugin with tag $tag. Plugin with this tag and different configuration already exists in context.")
}
@ -121,7 +124,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
fun load(factory: PluginFactory<*>, meta: Meta = EmptyMeta): Plugin{
val loaded = get(factory.tag, false)
return when {
loaded == null -> factory.build(meta)
loaded == null -> load(factory(meta))
loaded.config == meta -> loaded // if meta is the same, return existing plugin
else -> throw RuntimeException("Can't load plugin with tag ${factory.tag}. Plugin with this tag and different configuration already exists in context.")
}
@ -135,7 +138,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
val loaded = get(type, false)
return when {
loaded == null -> {
val plugin = PluginRepository.list().first { it.type == type }.build(meta)
val plugin = PluginRepository.list().first { it.type == type }.invoke(meta)
if (type.isInstance(plugin)) {
@Suppress("UNCHECKED_CAST")
load(plugin as T)

View File

@ -1,16 +1,17 @@
package hep.dataforge.context
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.configure
import kotlin.reflect.KClass
interface PluginFactory<T: Plugin> {
interface PluginFactory<T : Plugin> {
val tag: PluginTag
val type: KClass<out T>
fun build(): T
operator fun invoke(): T
}
fun PluginFactory<*>.build(meta: Meta) = build().configure(meta)
operator fun PluginFactory<*>.invoke(meta: Meta) = invoke().configure(meta)
expect object PluginRepository {
@ -27,16 +28,20 @@ expect object PluginRepository {
/**
* Fetch specific plugin and instantiate it with given meta
*/
fun PluginRepository.fetch(tag: PluginTag): Plugin =
PluginRepository.list().find { it.tag.matches(tag) }?.build()
fun PluginRepository.fetch(tag: PluginTag, meta: Meta = EmptyMeta): Plugin =
PluginRepository.list().find { it.tag.matches(tag) }?.invoke(meta)
?: error("Plugin with tag $tag not found in the repository")
fun <T: Plugin> PluginRepository.register(tag: PluginTag, type: KClass<out T>, constructor: () -> T): PluginFactory<T> {
fun <T : Plugin> PluginRepository.register(
tag: PluginTag,
type: KClass<out T>,
constructor: () -> T
): PluginFactory<T> {
val factory = object : PluginFactory<T> {
override val tag: PluginTag = tag
override val type: KClass<out T> = type
override fun build(): T = constructor()
override fun invoke(): T = constructor()
}
PluginRepository.register(factory)

View File

@ -0,0 +1,38 @@
package hep.dataforge.context
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import kotlin.test.Test
import kotlin.test.assertEquals
class ContextTest {
class DummyPlugin : AbstractPlugin() {
override val tag get() = PluginTag("test")
override fun provideTop(target: String, name: Name): Any? {
return when (target) {
"test" -> return name
else -> super.provideTop(target, name)
}
}
override fun listTop(target: String): Sequence<Name> {
return when (target) {
"test" -> sequenceOf("a", "b", "c.d").map { it.toName() }
else -> super.listTop(target)
}
}
}
@Test
fun testPluginManager() {
Global.plugins.load(DummyPlugin())
val members = Global.members<Name>("test")
assertEquals(3, members.count())
members.forEach {
println(it)
}
}
}

View File

@ -7,54 +7,4 @@ description = "Meta definition and basic operations on meta"
kotlin {
jvm()
js()
sourceSets {
val commonMain by getting {
dependencies {
api(kotlin("stdlib"))
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
api(kotlin("stdlib-jdk8"))
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val jsMain by getting {
dependencies {
api(kotlin("stdlib-js"))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
// mingwMain {
// }
// mingwTest {
// }
}
}
//tasks.withType<Kotlin2JsCompile>{
// kotlinOptions{
// metaInfo = true
// outputFile = "${project.buildDir.path}/js/${project.name}.js"
// sourceMap = true
// moduleKind = "umd"
// main = "call"
// }
//}

View File

@ -3,11 +3,7 @@ package hep.dataforge.meta
import hep.dataforge.meta.Meta.Companion.VALUE_KEY
import hep.dataforge.meta.MetaItem.NodeItem
import hep.dataforge.meta.MetaItem.ValueItem
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.plus
import hep.dataforge.names.toName
import hep.dataforge.names.asName
import hep.dataforge.names.*
import hep.dataforge.values.EnumValue
import hep.dataforge.values.Value
import hep.dataforge.values.boolean
@ -77,16 +73,23 @@ operator fun Meta?.get(key: String): MetaItem<out Meta>? = get(key.toName())
* Get all items matching given name.
*/
fun Meta.getAll(name: Name): Map<String, MetaItem<out Meta>> {
if (name.length == 0) error("Can't use empty name for that")
val (body, query) = name.last()!!
val regex = query.toRegex()
return (this[name.cutLast()] as? NodeItem<*>)?.node?.items
?.filter { it.key.body == body && (query.isEmpty() || regex.matches(it.key.index)) }
val root = when (name.length) {
0 -> error("Can't use empty name for that")
1 -> this
else -> (this[name.cutLast()] as? NodeItem<*>)?.node
}
val (body, index) = name.last()!!
val regex = index.toRegex()
return root?.items
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
?.mapKeys { it.key.index }
?: emptyMap()
}
fun Meta.getAll(name: String): Map<String, MetaItem<out Meta>> = getAll(name.toName())
/**
* Transform meta to sequence of [Name]-[Value] pairs
*/

View File

@ -23,4 +23,18 @@ class MetaBuilderTest {
assertEquals(true, meta["node.childNode.f"]?.boolean)
}
@Test
fun testSNS(){
val meta = buildMeta {
repeat(10){
"b.a[$it]" to it
}
}.seal()
assertEquals(10, meta.asValueSequence().count())
val nodes = meta.getAll("b.a")
assertEquals(3, nodes["3"]?.int)
}
}

View File

@ -0,0 +1,29 @@
package hep.dataforge.meta
import kotlin.test.Test
import kotlin.test.assertEquals
class StyledTest{
@Test
fun testSNS(){
val meta = buildMeta {
repeat(10){
"b.a[$it]" to {
"d" to it
}
}
}.seal().withStyle()
assertEquals(10, meta.asValueSequence().count())
val bNode = meta["b"].node
val aNodes = bNode?.getAll("a")
val allNodes = meta.getAll("b.a")
assertEquals(3, aNodes?.get("3")?.node["d"]?.int)
assertEquals(3, allNodes["3"]?.node["d"]?.int)
}
}

View File

@ -67,7 +67,7 @@ class ConsoleOutputManager : AbstractPlugin(), OutputManager {
override val type = ConsoleOutputManager::class
override fun build() = ConsoleOutputManager()
override fun invoke() = ConsoleOutputManager()
}
}