Updated plugin management

This commit is contained in:
Alexander Nozik 2019-03-23 11:28:24 +03:00
parent 16d263dc0b
commit ad23478a79
6 changed files with 46 additions and 26 deletions

View File

@ -46,7 +46,7 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr, Configurable {
* *
* @return * @return
*/ */
fun dependsOn(): List<PluginTag> = emptyList() fun dependsOn(): List<PluginFactory<*>> = emptyList()
/** /**
* Start this plugin and attach registration info to the context. This method * Start this plugin and attach registration info to the context. This method

View File

@ -118,6 +118,15 @@ 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.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.")
}
}
/** /**
* Load plugin by its class and meta. Ignore if plugin with this meta is already loaded. * Load plugin by its class and meta. Ignore if plugin with this meta is already loaded.
* Throw an exception if there exists plugin with the same type, but different meta * Throw an exception if there exists plugin with the same type, but different meta

View File

@ -4,23 +4,23 @@ import hep.dataforge.meta.Meta
import hep.dataforge.meta.configure import hep.dataforge.meta.configure
import kotlin.reflect.KClass import kotlin.reflect.KClass
interface PluginFactory { interface PluginFactory<T: Plugin> {
val tag: PluginTag val tag: PluginTag
val type: KClass<out Plugin> val type: KClass<out T>
fun build(): Plugin fun build(): T
} }
fun PluginFactory.build(meta: Meta) = build().configure(meta) fun PluginFactory<*>.build(meta: Meta) = build().configure(meta)
expect object PluginRepository { expect object PluginRepository {
fun register(factory: PluginFactory) fun register(factory: PluginFactory<*>)
/** /**
* List plugins available in the repository * List plugins available in the repository
*/ */
fun list(): Sequence<PluginFactory> fun list(): Sequence<PluginFactory<*>>
} }
@ -31,15 +31,16 @@ fun PluginRepository.fetch(tag: PluginTag): Plugin =
PluginRepository.list().find { it.tag.matches(tag) }?.build() PluginRepository.list().find { it.tag.matches(tag) }?.build()
?: error("Plugin with tag $tag not found in the repository") ?: error("Plugin with tag $tag not found in the repository")
fun PluginRepository.register(tag: PluginTag, type: KClass<out Plugin>, constructor: () -> Plugin) { fun <T: Plugin> PluginRepository.register(tag: PluginTag, type: KClass<out T>, constructor: () -> T): PluginFactory<T> {
val factory = object : PluginFactory { val factory = object : PluginFactory<T> {
override val tag: PluginTag = tag override val tag: PluginTag = tag
override val type: KClass<out Plugin> = type override val type: KClass<out T> = type
override fun build(): Plugin = constructor() override fun build(): T = constructor()
} }
PluginRepository.register(factory) PluginRepository.register(factory)
return factory
} }
inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: () -> T) = inline fun <reified T : Plugin> PluginRepository.register(tag: PluginTag, noinline constructor: () -> T) =

View File

@ -3,14 +3,14 @@ package hep.dataforge.context
actual object PluginRepository { actual object PluginRepository {
private val factories: MutableSet<PluginFactory> = HashSet() private val factories: MutableSet<PluginFactory<*>> = HashSet()
actual fun register(factory: PluginFactory) { actual fun register(factory: PluginFactory<*>) {
factories.add(factory) factories.add(factory)
} }
/** /**
* List plugins available in the repository * List plugins available in the repository
*/ */
actual fun list(): Sequence<PluginFactory> = factories.asSequence() actual fun list(): Sequence<PluginFactory<*>> = factories.asSequence()
} }

View File

@ -2,16 +2,16 @@ package hep.dataforge.context
actual object PluginRepository { actual object PluginRepository {
private val factories: MutableSet<PluginFactory> = HashSet() private val factories: MutableSet<PluginFactory<*>> = HashSet()
actual fun register(factory: PluginFactory) { actual fun register(factory: PluginFactory<*>) {
factories.add(factory) factories.add(factory)
} }
/** /**
* List plugins available in the repository * List plugins available in the repository
*/ */
actual fun list(): Sequence<PluginFactory> = actual fun list(): Sequence<PluginFactory<*>> =
factories.asSequence() + Global.services() factories.asSequence() + Global.services()
} }

View File

@ -1,9 +1,6 @@
package hep.dataforge.output package hep.dataforge.output
import hep.dataforge.context.AbstractPlugin import hep.dataforge.context.*
import hep.dataforge.context.Context
import hep.dataforge.context.Plugin
import hep.dataforge.context.PluginTag
import hep.dataforge.context.PluginTag.Companion.DATAFORGE_GROUP import hep.dataforge.context.PluginTag.Companion.DATAFORGE_GROUP
import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
@ -24,13 +21,18 @@ interface OutputManager : Plugin {
* @param name represents the name inside the node. * @param name represents the name inside the node.
* @param meta configuration for [Output] (not for rendered object) * @param meta configuration for [Output] (not for rendered object)
*/ */
operator fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name = EmptyName, meta: Meta = EmptyMeta): Output<T> operator fun <T : Any> get(
type: KClass<out T>,
name: Name,
stage: Name = EmptyName,
meta: Meta = EmptyMeta
): Output<T>
} }
/** /**
* Get an output manager for a context * Get an output manager for a context
*/ */
val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager val Context.output: OutputManager get() = plugins.get() ?: ConsoleOutputManager()
/** /**
* Get an output with given [name], [stage] and reified content type * Get an output with given [name], [stage] and reified content type
@ -47,7 +49,7 @@ inline operator fun <reified T : Any> OutputManager.get(
* Directly render an object using the most suitable renderer * Directly render an object using the most suitable renderer
*/ */
fun OutputManager.render(obj: Any, name: Name, stage: Name = EmptyName, meta: Meta = EmptyMeta) = fun OutputManager.render(obj: Any, name: Name, stage: Name = EmptyName, meta: Meta = EmptyMeta) =
get(obj::class, name,stage).render(obj,meta) get(obj::class, name, stage).render(obj, meta)
/** /**
* System console output. * System console output.
@ -55,10 +57,18 @@ fun OutputManager.render(obj: Any, name: Name, stage: Name = EmptyName, meta: Me
*/ */
expect val ConsoleOutput: Output<Any> expect val ConsoleOutput: Output<Any>
object ConsoleOutputManager : AbstractPlugin(), OutputManager { class ConsoleOutputManager : AbstractPlugin(), OutputManager {
override val tag: PluginTag = PluginTag("output.console", group = DATAFORGE_GROUP) override val tag: PluginTag get() = ConsoleOutputManager.tag
override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> = ConsoleOutput override fun <T : Any> get(type: KClass<out T>, name: Name, stage: Name, meta: Meta): Output<T> = ConsoleOutput
companion object : PluginFactory<ConsoleOutputManager> {
override val tag = PluginTag("output.console", group = DATAFORGE_GROUP)
override val type = ConsoleOutputManager::class
override fun build() = ConsoleOutputManager()
}
} }
/** /**