Skip to content

Commit

Permalink
Merge pull request #23 from mipt-npm/dev
Browse files Browse the repository at this point in the history
0.1.4
  • Loading branch information
altavir authored Nov 1, 2019
2 parents 5423dd2 + aefee64 commit 5dc7929
Show file tree
Hide file tree
Showing 103 changed files with 3,471 additions and 1,001 deletions.
7 changes: 4 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
plugins {
id("scientifik.mpp") version "0.1.4" apply false
id("scientifik.publish") version "0.1.4" apply false
id("scientifik.mpp") version "0.2.1" apply false
id("scientifik.jvm") version "0.2.1" apply false
id("scientifik.publish") version "0.2.1" apply false
}

val dataforgeVersion by extra("0.1.3")
val dataforgeVersion by extra("0.1.4")

val bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package hep.dataforge.context
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty

abstract class AbstractPlugin(override val meta: Meta = EmptyMeta) : Plugin {
private var _context: Context? = null
private val dependencies = ArrayList<PluginFactory<*>>()

override val context: Context
get() = _context ?: error("Plugin $tag is not attached")
Expand All @@ -19,9 +22,23 @@ abstract class AbstractPlugin(override val meta: Meta = EmptyMeta) : Plugin {
this._context = null
}

override fun provideTop(target: String): Map<Name, Any> = emptyMap()
final override fun dependsOn(): List<PluginFactory<*>> = dependencies

companion object{
fun <T: Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name.toName() to it }
/**
* Register plugin dependency and return a delegate which provides lazily initialized reference to dependent plugin
*/
protected fun <P : Plugin> require(factory: PluginFactory<P>): ReadOnlyProperty<AbstractPlugin, P> {
dependencies.add(factory)
return PluginDependencyDelegate(factory.type)
}

override fun provideTop(target: String): Map<Name, Any> = emptyMap()
}

fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name to it }

private class PluginDependencyDelegate<P : Plugin>(val type: KClass<out P>) : ReadOnlyProperty<AbstractPlugin, P> {
override fun getValue(thisRef: AbstractPlugin, property: KProperty<*>): P {
return thisRef.context.plugins[type] ?: error("Plugin with type $type not found")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package hep.dataforge.context

import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.appendLeft
import hep.dataforge.names.toName
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.provider.Provider
import hep.dataforge.provider.top
import hep.dataforge.values.Value
Expand All @@ -27,7 +27,7 @@ import kotlin.jvm.JvmName
* @author Alexander Nozik
*/
open class Context(
final override val name: String,
final override val name: Name,
val parent: Context? = Global
) : Named, MetaRepr, Provider, CoroutineScope {

Expand All @@ -45,7 +45,7 @@ open class Context(
/**
* Context logger
*/
val logger: KLogger = KotlinLogging.logger(name)
val logger: KLogger = KotlinLogging.logger(name.toString())

/**
* A [PluginManager] for current context
Expand All @@ -64,7 +64,7 @@ open class Context(
override fun provideTop(target: String): Map<Name, Any> {
return when (target) {
Value.TYPE -> properties.sequence().toMap()
Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name.toName() }
Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name }
else -> emptyMap()
}
}
Expand Down Expand Up @@ -105,8 +105,8 @@ open class Context(

override fun toMeta(): Meta = buildMeta {
"parent" to parent?.name
"properties" to properties.seal()
"plugins" to plugins.map { it.toMeta() }
"properties" put properties.seal()
"plugins" put plugins.map { it.toMeta() }
}
}

Expand All @@ -118,14 +118,14 @@ fun Context.content(target: String): Map<Name, Any> = content<Any>(target)
@JvmName("typedContent")
inline fun <reified T : Any> Context.content(target: String): Map<Name, T> =
plugins.flatMap { plugin ->
plugin.top<T>(target).entries.map { (it.key.appendLeft(plugin.name)) to it.value }
plugin.top<T>(target).entries.map { (plugin.name + it.key) to it.value }
}.associate { it }


/**
* A global root context. Closing [Global] terminates the framework.
*/
object Global : Context("GLOBAL", null) {
object Global : Context("GLOBAL".asName(), null) {
/**
* Closing all contexts
*
Expand Down Expand Up @@ -173,7 +173,7 @@ interface ContextAware {

val logger: KLogger
get() = if (this is Named) {
KotlinLogging.logger(context.name + "." + (this as Named).name)
KotlinLogging.logger((context.name + this.name).toString())
} else {
context.logger
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package hep.dataforge.context

import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta
import hep.dataforge.names.toName

/**
* A convenience builder for context
*/
class ContextBuilder(var name: String = "@anonimous", val parent: Context = Global) {
class ContextBuilder(var name: String = "@anonymous", val parent: Context = Global) {
private val plugins = ArrayList<Plugin>()
private var meta = MetaBuilder()

Expand All @@ -31,7 +32,7 @@ class ContextBuilder(var name: String = "@anonimous", val parent: Context = Glob
}

fun build(): Context {
return Context(name, parent).apply {
return Context(name.toName(), parent).apply {
this@ContextBuilder.plugins.forEach {
plugins.load(it)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package hep.dataforge.context

import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta

interface Factory<out T : Any> {
operator fun invoke(meta: Meta = EmptyMeta, context: Context = Global): T
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package hep.dataforge.context

import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty

/**
* Any object that have name
*
Expand All @@ -27,10 +31,9 @@ interface Named {
*
* @return
*/
val name: String
val name: Name

companion object {
const val ANONYMOUS = ""

/**
* Get the name of given object. If object is Named its name is used,
Expand All @@ -39,11 +42,11 @@ interface Named {
* @param obj
* @return
*/
fun nameOf(obj: Any): String {
fun nameOf(obj: Any): Name {
return if (obj is Named) {
obj.name
} else {
obj.toString()
obj.toString().asName()
}
}
}
Expand All @@ -54,4 +57,4 @@ interface Named {
* @return
*/
val Named.isAnonymous: Boolean
get() = this.name == Named.ANONYMOUS
get() = this.name.isEmpty()
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package hep.dataforge.context
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaRepr
import hep.dataforge.meta.buildMeta
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.provider.Provider

/**
Expand Down Expand Up @@ -37,7 +39,7 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
*
* @return
*/
override val name: String get() = tag.name
override val name: Name get() = tag.name.toName()

/**
* Plugin dependencies which are required to attach this plugin. Plugin
Expand All @@ -46,7 +48,7 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
*
* @return
*/
fun dependsOn(): List<PluginFactory<*>> = emptyList()
fun dependsOn(): Collection<PluginFactory<*>>

/**
* Start this plugin and attach registration info to the context. This method
Expand All @@ -64,10 +66,10 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
fun detach()

override fun toMeta(): Meta = buildMeta {
"context" to context.name
"context" put context.name.toString()
"type" to this::class.simpleName
"tag" to tag
"meta" to meta
"tag" put tag
"meta" put meta
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
* @param recursive search for parent [PluginManager] plugins
* @param predicate condition for the plugin
*/
fun get(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)


/**
Expand All @@ -47,7 +47,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
* @param tag
* @return
*/
operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = get(recursive) { tag.matches(it.tag) }
operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }


/**
Expand All @@ -63,11 +63,13 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
*/
@Suppress("UNCHECKED_CAST")
operator fun <T : Any> get(type: KClass<T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
get(recursive) { type.isInstance(it) && (tag == null || tag.matches(it.tag)) } as T?
find(recursive) { type.isInstance(it) && (tag == null || tag.matches(it.tag)) } as T?

inline fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
get(T::class, tag, recursive)

inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
get(factory.type, factory.tag, recursive)

/**
* Load given plugin into this manager and return loaded instance.
Expand Down Expand Up @@ -97,7 +99,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
* Load a plugin using its factory
*/
fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = EmptyMeta): T =
load(factory(meta))
load(factory(meta, context))

fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
load(factory, buildMeta(metaBuilder))
Expand All @@ -122,7 +124,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = EmptyMeta): T {
val loaded = get(factory.type, factory.tag, recursive)
return when {
loaded == null -> load(factory(meta))
loaded == null -> load(factory(meta, context))
loaded.meta == 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.")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import kotlin.reflect.KClass

interface PluginFactory<T : Plugin> {
interface PluginFactory<T : Plugin> : Factory<T> {
val tag: PluginTag
val type: KClass<out T>
operator fun invoke(meta: Meta = EmptyMeta): T
}

expect object PluginRepository {
Expand All @@ -25,25 +24,26 @@ expect object PluginRepository {
* Fetch specific plugin and instantiate it with given meta
*/
fun PluginRepository.fetch(tag: PluginTag, meta: Meta = EmptyMeta): Plugin =
list().find { it.tag.matches(tag) }?.invoke(meta) ?: error("Plugin with tag $tag not found in the repository")
list().find { it.tag.matches(tag) }?.invoke(meta = meta)
?: error("Plugin with tag $tag not found in the repository")

fun <T : Plugin> PluginRepository.register(
tag: PluginTag,
type: KClass<out T>,
constructor: (Meta) -> T
constructor: (Context, Meta) -> T
): PluginFactory<T> {
val factory = object : PluginFactory<T> {
override val tag: PluginTag = tag
override val type: KClass<out T> = type

override fun invoke(meta: Meta): T = constructor(meta)
override fun invoke(meta: Meta, context: Context): T = constructor(context, meta)

}
register(factory)
return factory
}

inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: (Meta) -> T) =
inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: (Context, Meta) -> T) =
register(tag, T::class, constructor)

fun PluginRepository.register(plugin: Plugin) = register(plugin.tag, plugin::class) { plugin }
fun PluginRepository.register(plugin: Plugin) = register(plugin.tag, plugin::class) { _, _ -> plugin }
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ data class PluginTag(
override fun toString(): String = listOf(group, name, version).joinToString(separator = ":")

override fun toMeta(): Meta = buildMeta {
"name" to name
"group" to group
"version" to version
"name" put name
"group" put group
"version" put version
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import hep.dataforge.names.appendLeft
import hep.dataforge.names.toName
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue


class ContextTest {
Expand All @@ -26,7 +25,7 @@ class ContextTest {
val members = Global.content<Name>("test")
assertEquals(3, members.count())
members.forEach {
assertTrue{it.key == it.value.appendLeft("test")}
assertEquals(it.key, it.value.appendLeft("test"))
}
}

Expand Down
Loading

0 comments on commit 5dc7929

Please sign in to comment.