Isolate and deprecate Context plugin mutation logic.
This commit is contained in:
parent
9fbc482549
commit
f1f5f7a70c
@ -4,12 +4,16 @@
|
|||||||
### Added
|
### Added
|
||||||
- LogManager plugin
|
- LogManager plugin
|
||||||
- dataforge-context API dependency on SLF4j
|
- dataforge-context API dependency on SLF4j
|
||||||
|
- Context `withEnv` and `fetch` methods to manipulate plugins without changing plugins after creation.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Kotlin-logging moved from common to JVM and JS. Replaced by console for native.
|
- Kotlin-logging moved from common to JVM and JS. Replaced by console for native.
|
||||||
- Package changed to `space.kscience`
|
- Package changed to `space.kscience`
|
||||||
|
- Scheme made observable
|
||||||
|
- Global context is a variable (the singleton is hidden and will be deprecated in future)
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
- Direct use of PluginManager
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Common dependency on Kotlin-logging
|
- Common dependency on Kotlin-logging
|
||||||
|
@ -38,6 +38,7 @@ public final class space/kscience/dataforge/context/ClassLoaderPluginKt {
|
|||||||
public class space/kscience/dataforge/context/Context : kotlinx/coroutines/CoroutineScope, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/misc/Named, space/kscience/dataforge/provider/Provider {
|
public class space/kscience/dataforge/context/Context : kotlinx/coroutines/CoroutineScope, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/misc/Named, space/kscience/dataforge/provider/Provider {
|
||||||
public static final field Companion Lspace/kscience/dataforge/context/Context$Companion;
|
public static final field Companion Lspace/kscience/dataforge/context/Context$Companion;
|
||||||
public static final field PROPERTY_TARGET Ljava/lang/String;
|
public static final field PROPERTY_TARGET Ljava/lang/String;
|
||||||
|
public final fun buildContext (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
|
||||||
public fun close ()V
|
public fun close ()V
|
||||||
public fun content (Ljava/lang/String;)Ljava/util/Map;
|
public fun content (Ljava/lang/String;)Ljava/util/Map;
|
||||||
public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
|
public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
|
||||||
@ -47,6 +48,7 @@ public class space/kscience/dataforge/context/Context : kotlinx/coroutines/Corou
|
|||||||
public final fun getName ()Lspace/kscience/dataforge/names/Name;
|
public final fun getName ()Lspace/kscience/dataforge/names/Name;
|
||||||
public final fun getParent ()Lspace/kscience/dataforge/context/Context;
|
public final fun getParent ()Lspace/kscience/dataforge/context/Context;
|
||||||
public final fun getPlugins ()Lspace/kscience/dataforge/context/PluginManager;
|
public final fun getPlugins ()Lspace/kscience/dataforge/context/PluginManager;
|
||||||
|
public final fun getProperties ()Lspace/kscience/dataforge/meta/Laminate;
|
||||||
public fun toMeta ()Lspace/kscience/dataforge/meta/Meta;
|
public fun toMeta ()Lspace/kscience/dataforge/meta/Meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,24 +60,35 @@ public abstract interface class space/kscience/dataforge/context/ContextAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/dataforge/context/ContextBuilder {
|
public final class space/kscience/dataforge/context/ContextBuilder {
|
||||||
public fun <init> ()V
|
|
||||||
public fun <init> (Lspace/kscience/dataforge/context/Context;Ljava/lang/String;)V
|
|
||||||
public synthetic fun <init> (Lspace/kscience/dataforge/context/Context;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
|
||||||
public final fun build ()Lspace/kscience/dataforge/context/Context;
|
public final fun build ()Lspace/kscience/dataforge/context/Context;
|
||||||
public final fun getName ()Ljava/lang/String;
|
public final fun getName ()Lspace/kscience/dataforge/names/Name;
|
||||||
|
public final fun name (Ljava/lang/String;)V
|
||||||
public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
|
public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
|
||||||
public final fun plugin (Lspace/kscience/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)V
|
public final fun plugin (Lspace/kscience/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)V
|
||||||
|
public final fun plugin (Lspace/kscience/dataforge/context/PluginFactory;Lspace/kscience/dataforge/meta/Meta;)V
|
||||||
public final fun plugin (Lspace/kscience/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;)V
|
public final fun plugin (Lspace/kscience/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;)V
|
||||||
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||||
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Lspace/kscience/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Lspace/kscience/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||||
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Lspace/kscience/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
public static synthetic fun plugin$default (Lspace/kscience/dataforge/context/ContextBuilder;Lspace/kscience/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||||
public final fun properties (Lkotlin/jvm/functions/Function1;)V
|
public final fun properties (Lkotlin/jvm/functions/Function1;)V
|
||||||
public final fun setName (Ljava/lang/String;)V
|
public final fun setName (Lspace/kscience/dataforge/names/Name;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/dataforge/context/ContextKt {
|
public final class space/kscience/dataforge/context/ContextBuilderKt {
|
||||||
public static final fun Context (Ljava/lang/String;Lspace/kscience/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
|
}
|
||||||
public static synthetic fun Context$default (Ljava/lang/String;Lspace/kscience/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Context;
|
|
||||||
|
public final class space/kscience/dataforge/context/DefaultLogManager : space/kscience/dataforge/context/AbstractPlugin, space/kscience/dataforge/context/LogManager {
|
||||||
|
public static final field Companion Lspace/kscience/dataforge/context/DefaultLogManager$Companion;
|
||||||
|
public fun <init> ()V
|
||||||
|
public fun getTag ()Lspace/kscience/dataforge/context/PluginTag;
|
||||||
|
public fun log (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/dataforge/context/DefaultLogManager$Companion : space/kscience/dataforge/context/PluginFactory {
|
||||||
|
public fun getTag ()Lspace/kscience/dataforge/context/PluginTag;
|
||||||
|
public fun getType ()Lkotlin/reflect/KClass;
|
||||||
|
public synthetic fun invoke (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/context/Context;)Ljava/lang/Object;
|
||||||
|
public fun invoke (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/context/Context;)Lspace/kscience/dataforge/context/DefaultLogManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/dataforge/context/Factory {
|
public abstract interface class space/kscience/dataforge/context/Factory {
|
||||||
@ -88,12 +101,13 @@ public final class space/kscience/dataforge/context/Factory$DefaultImpls {
|
|||||||
|
|
||||||
public final class space/kscience/dataforge/context/Global : space/kscience/dataforge/context/Context {
|
public final class space/kscience/dataforge/context/Global : space/kscience/dataforge/context/Context {
|
||||||
public static final field INSTANCE Lspace/kscience/dataforge/context/Global;
|
public static final field INSTANCE Lspace/kscience/dataforge/context/Global;
|
||||||
public fun close ()V
|
|
||||||
public final fun context (Ljava/lang/String;Lspace/kscience/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
|
|
||||||
public static synthetic fun context$default (Lspace/kscience/dataforge/context/Global;Ljava/lang/String;Lspace/kscience/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Context;
|
|
||||||
public final fun getContext (Ljava/lang/String;)Lspace/kscience/dataforge/context/Context;
|
|
||||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||||
public final fun getLogger ()Lspace/kscience/dataforge/context/LogManager;
|
public final fun getDefaultLogger ()Lspace/kscience/dataforge/context/LogManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/dataforge/context/GlobalKt {
|
||||||
|
public static final fun Context (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
|
||||||
|
public static synthetic fun Context$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/dataforge/context/LogManager : space/kscience/dataforge/context/Logable, space/kscience/dataforge/context/Plugin {
|
public abstract interface class space/kscience/dataforge/context/LogManager : space/kscience/dataforge/context/Logable, space/kscience/dataforge/context/Plugin {
|
||||||
@ -128,7 +142,7 @@ public final class space/kscience/dataforge/context/LogManagerKt {
|
|||||||
public static final fun error (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)V
|
public static final fun error (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)V
|
||||||
public static synthetic fun error$default (Lspace/kscience/dataforge/context/Logable;Ljava/lang/Throwable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
public static synthetic fun error$default (Lspace/kscience/dataforge/context/Logable;Ljava/lang/Throwable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
||||||
public static synthetic fun error$default (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
public static synthetic fun error$default (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
||||||
public static final fun getLogger (Lspace/kscience/dataforge/context/Context;)Lspace/kscience/dataforge/context/LogManager;
|
public static final fun getLogger (Lspace/kscience/dataforge/context/Context;)Lspace/kscience/dataforge/context/Logable;
|
||||||
public static final fun getLogger (Lspace/kscience/dataforge/context/ContextAware;)Lspace/kscience/dataforge/context/Logable;
|
public static final fun getLogger (Lspace/kscience/dataforge/context/ContextAware;)Lspace/kscience/dataforge/context/Logable;
|
||||||
public static final fun info (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)V
|
public static final fun info (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)V
|
||||||
public static synthetic fun info$default (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
public static synthetic fun info$default (Lspace/kscience/dataforge/context/Logable;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
|
||||||
|
@ -11,6 +11,7 @@ import space.kscience.dataforge.misc.Named
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.provider.Provider
|
import space.kscience.dataforge.provider.Provider
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.jvm.Synchronized
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top.
|
* The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top.
|
||||||
@ -31,12 +32,13 @@ public open class Context internal constructor(
|
|||||||
/**
|
/**
|
||||||
* Context properties. Working as substitute for environment variables
|
* Context properties. Working as substitute for environment variables
|
||||||
*/
|
*/
|
||||||
private val properties: Laminate = if (parent == null) {
|
public val properties: Laminate = if (parent == null) {
|
||||||
Laminate(meta)
|
Laminate(meta)
|
||||||
} else {
|
} else {
|
||||||
Laminate(meta, parent.properties)
|
Laminate(meta, parent.properties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [PluginManager] for current context
|
* A [PluginManager] for current context
|
||||||
*/
|
*/
|
||||||
@ -68,10 +70,24 @@ public open class Context internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val childrenContexts = HashMap<Name, Context>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach all plugins and terminate context
|
* Build and register a child context
|
||||||
|
*/
|
||||||
|
@Synchronized
|
||||||
|
public fun buildContext(block: ContextBuilder.() -> Unit): Context{
|
||||||
|
val newContext = ContextBuilder(this).apply(block).build()
|
||||||
|
childrenContexts[newContext.name] = newContext
|
||||||
|
return newContext
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detach all plugins, and close child contexts
|
||||||
*/
|
*/
|
||||||
public open fun close() {
|
public open fun close() {
|
||||||
|
//recursively closed child context
|
||||||
|
childrenContexts.forEach { it.value.close() }
|
||||||
//detach all plugins
|
//detach all plugins
|
||||||
plugins.forEach { it.detach() }
|
plugins.forEach { it.detach() }
|
||||||
}
|
}
|
||||||
@ -87,9 +103,6 @@ public open class Context internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Context(name: String, parent: Context = Global, block: ContextBuilder.() -> Unit = {}): Context =
|
|
||||||
Global.context(name, parent, block)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface for something that encapsulated in context
|
* The interface for something that encapsulated in context
|
||||||
*
|
*
|
||||||
|
@ -3,8 +3,11 @@ package space.kscience.dataforge.context
|
|||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.MetaBuilder
|
import space.kscience.dataforge.meta.MetaBuilder
|
||||||
import space.kscience.dataforge.meta.seal
|
import space.kscience.dataforge.meta.seal
|
||||||
|
import space.kscience.dataforge.meta.toMutableMeta
|
||||||
import space.kscience.dataforge.misc.DFBuilder
|
import space.kscience.dataforge.misc.DFBuilder
|
||||||
import space.kscience.dataforge.misc.DFExperimental
|
import space.kscience.dataforge.misc.DFExperimental
|
||||||
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.names.toName
|
import space.kscience.dataforge.names.toName
|
||||||
import kotlin.collections.component1
|
import kotlin.collections.component1
|
||||||
import kotlin.collections.component2
|
import kotlin.collections.component2
|
||||||
@ -14,14 +17,22 @@ import kotlin.collections.set
|
|||||||
* A convenience builder for context
|
* A convenience builder for context
|
||||||
*/
|
*/
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
|
public class ContextBuilder internal constructor(
|
||||||
private val factories = HashMap<PluginFactory<*>, Meta>()
|
private val parent: Context,
|
||||||
private var meta = MetaBuilder()
|
public var name: Name? = null,
|
||||||
|
meta: Meta = Meta.EMPTY,
|
||||||
|
) {
|
||||||
|
internal val factories = HashMap<PluginFactory<*>, Meta>()
|
||||||
|
internal var meta = meta.toMutableMeta()
|
||||||
|
|
||||||
public fun properties(action: MetaBuilder.() -> Unit) {
|
public fun properties(action: MetaBuilder.() -> Unit) {
|
||||||
meta.action()
|
meta.action()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun name(string: String){
|
||||||
|
this.name = string.toName()
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
|
private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
|
||||||
parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
|
parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
|
||||||
@ -32,6 +43,10 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
|||||||
factories[factory] = Meta(metaBuilder)
|
factories[factory] = Meta(metaBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun plugin(factory: PluginFactory<*>, meta: Meta){
|
||||||
|
factories[factory] = meta
|
||||||
|
}
|
||||||
|
|
||||||
public fun plugin(factory: PluginFactory<*>, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
public fun plugin(factory: PluginFactory<*>, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
||||||
factories[factory] = Meta(metaBuilder)
|
factories[factory] = Meta(metaBuilder)
|
||||||
}
|
}
|
||||||
@ -41,10 +56,29 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun build(): Context {
|
public fun build(): Context {
|
||||||
return Context(name.toName(), parent, meta.seal()).apply {
|
val contextName = name ?: "@auto[${hashCode().toUInt().toString(16)}]".toName()
|
||||||
|
return Context(contextName, parent, meta.seal()).apply {
|
||||||
factories.forEach { (factory, meta) ->
|
factories.forEach { (factory, meta) ->
|
||||||
plugins.load(factory, meta)
|
plugins.load(factory, meta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if current context contains all plugins required by the builder and return it it does or forks to a new context
|
||||||
|
* if it does not.
|
||||||
|
*/
|
||||||
|
public fun Context.withEnv(block: ContextBuilder.() -> Unit): Context {
|
||||||
|
|
||||||
|
fun Context.contains(factory: PluginFactory<*>, meta: Meta): Boolean {
|
||||||
|
val loaded = plugins[factory.tag] ?: return false
|
||||||
|
return loaded.meta == meta
|
||||||
|
}
|
||||||
|
|
||||||
|
val builder = ContextBuilder(this, name + "env", properties).apply(block)
|
||||||
|
val requiresFork = builder.factories.any { (factory, meta) ->
|
||||||
|
!contains(factory, meta)
|
||||||
|
} || ((properties as Meta) == builder.meta)
|
||||||
|
return if (requiresFork) builder.build() else this
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package space.kscience.dataforge.context
|
package space.kscience.dataforge.context
|
||||||
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.Job
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -13,43 +13,10 @@ internal expect val globalLoggerFactory: PluginFactory<out LogManager>
|
|||||||
* A global root context. Closing [Global] terminates the framework.
|
* A global root context. Closing [Global] terminates the framework.
|
||||||
*/
|
*/
|
||||||
@ThreadLocal
|
@ThreadLocal
|
||||||
public object Global : Context("GLOBAL".asName(), null, Meta.EMPTY) {
|
private object GlobalContext : Context("GLOBAL".asName(), null, Meta.EMPTY) {
|
||||||
|
override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + Job()
|
||||||
override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + SupervisorJob()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default logging manager
|
|
||||||
*/
|
|
||||||
public val logger: LogManager by lazy { globalLoggerFactory.invoke(context = this).apply { attach(this@Global) } }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closing all contexts
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
override fun close() {
|
|
||||||
logger.info { "Shutting down GLOBAL" }
|
|
||||||
for (ctx in contextRegistry.values) {
|
|
||||||
ctx.close()
|
|
||||||
}
|
|
||||||
super.close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val contextRegistry = HashMap<String, Context>()
|
public val Global: Context get() = GlobalContext
|
||||||
|
|
||||||
/**
|
public fun Context(block: ContextBuilder.() -> Unit = {}): Context = Global.buildContext(block)
|
||||||
* Get previously built context
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public fun getContext(name: String): Context? {
|
|
||||||
return contextRegistry[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun context(name: String, parent: Context = this, block: ContextBuilder.() -> Unit = {}): Context =
|
|
||||||
ContextBuilder(parent, name).apply(block).build().also {
|
|
||||||
contextRegistry[name] = it
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +1,16 @@
|
|||||||
package space.kscience.dataforge.context
|
package space.kscience.dataforge.context
|
||||||
|
|
||||||
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.misc.Named
|
import space.kscience.dataforge.misc.Named
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public interface Logable {
|
public fun interface Logable {
|
||||||
public fun log(name: Name, tag: String, body: () -> String)
|
public fun log(name: Name, tag: String, body: () -> String)
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface LogManager : Plugin, Logable {
|
public interface LogManager : Plugin, Logable {
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public const val TRACE: String = "TRACE"
|
public const val TRACE: String = "TRACE"
|
||||||
public const val INFO: String = "INFO"
|
public const val INFO: String = "INFO"
|
||||||
@ -41,11 +42,30 @@ public fun Logable.error(throwable: Throwable?, name: Name = Name.EMPTY, body: (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DefaultLogManager : AbstractPlugin(), LogManager {
|
||||||
|
|
||||||
|
override fun log(name: Name, tag: String, body: () -> String) {
|
||||||
|
val message: String = body.safe
|
||||||
|
println("[${context.name}] $name: $message")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
|
public companion object : PluginFactory<DefaultLogManager> {
|
||||||
|
override fun invoke(meta: Meta, context: Context): DefaultLogManager = DefaultLogManager()
|
||||||
|
|
||||||
|
override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.default")
|
||||||
|
override val type: KClass<out DefaultLogManager> = DefaultLogManager::class
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context log manager inherited from parent
|
* Context log manager inherited from parent
|
||||||
*/
|
*/
|
||||||
public val Context.logger: LogManager
|
public val Context.logger: Logable
|
||||||
get() = plugins.find(inherit = true) { it is LogManager } as? LogManager ?: Global.logger
|
get() = plugins.find(inherit = true) { it is LogManager } as? LogManager
|
||||||
|
?: globalLoggerFactory(context = Global).apply { attach(Global) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The named proxy logger for a context member
|
* The named proxy logger for a context member
|
||||||
|
@ -63,5 +63,4 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
|||||||
public companion object {
|
public companion object {
|
||||||
public const val TARGET: String = "plugin"
|
public const val TARGET: String = "plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,8 +13,6 @@ import kotlin.reflect.KClass
|
|||||||
*/
|
*/
|
||||||
public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
||||||
|
|
||||||
//TODO refactor to read-only container
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of loaded plugins
|
* A set of loaded plugins
|
||||||
*/
|
*/
|
||||||
@ -85,6 +83,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
* @param plugin
|
* @param plugin
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun <T : Plugin> load(plugin: T): T {
|
public fun <T : Plugin> load(plugin: T): T {
|
||||||
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
||||||
error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
|
error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
|
||||||
@ -93,7 +92,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
fetch(factory, meta, true)
|
fetch(factory, meta, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.logger.info { "Loading plugin ${plugin.name} into ${context.name}" }
|
logger.info { "Loading plugin ${plugin.name} into ${context.name}" }
|
||||||
plugin.attach(context)
|
plugin.attach(context)
|
||||||
plugins.add(plugin)
|
plugins.add(plugin)
|
||||||
return plugin
|
return plugin
|
||||||
@ -103,15 +102,18 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
/**
|
/**
|
||||||
* Load a plugin using its factory
|
* Load a plugin using its factory
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
|
public fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
|
||||||
load(factory(meta, context))
|
load(factory(meta, context))
|
||||||
|
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
|
public fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
|
||||||
load(factory, Meta(metaBuilder))
|
load(factory, Meta(metaBuilder))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a plugin from [PluginManager]
|
* Remove a plugin from [PluginManager]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun remove(plugin: Plugin) {
|
public fun remove(plugin: Plugin) {
|
||||||
if (plugins.contains(plugin)) {
|
if (plugins.contains(plugin)) {
|
||||||
Global.logger.info { "Removing plugin ${plugin.name} from ${context.name}" }
|
Global.logger.info { "Removing plugin ${plugin.name} from ${context.name}" }
|
||||||
@ -123,6 +125,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
/**
|
/**
|
||||||
* Get an existing plugin with given meta or load new one using provided factory
|
* Get an existing plugin with given meta or load new one using provided factory
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun <T : Plugin> fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY, recursive: Boolean = true): T {
|
public fun <T : Plugin> fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY, recursive: Boolean = true): T {
|
||||||
val loaded = get(factory.type, factory.tag, recursive)
|
val loaded = get(factory.type, factory.tag, recursive)
|
||||||
return when {
|
return when {
|
||||||
@ -132,6 +135,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use immutable contexts instead")
|
||||||
public fun <T : Plugin> fetch(
|
public fun <T : Plugin> fetch(
|
||||||
factory: PluginFactory<T>,
|
factory: PluginFactory<T>,
|
||||||
recursive: Boolean = true,
|
recursive: Boolean = true,
|
||||||
@ -141,3 +145,17 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
|||||||
override fun iterator(): Iterator<Plugin> = plugins.iterator()
|
override fun iterator(): Iterator<Plugin> = plugins.iterator()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a plugin with given meta from the context. If the plugin (with given meta) is already registered, it is returned.
|
||||||
|
* Otherwise, new child context with the plugin is created. In the later case the context could be retrieved from the plugin.
|
||||||
|
*/
|
||||||
|
public inline fun <reified T : Plugin> Context.fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T {
|
||||||
|
val existing = plugins[factory]
|
||||||
|
return if (existing != null && existing.meta == meta) existing
|
||||||
|
else {
|
||||||
|
buildContext {
|
||||||
|
plugin(factory, meta)
|
||||||
|
}.plugins[factory]!!
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,9 @@ class ContextTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPluginManager() {
|
fun testPluginManager() {
|
||||||
val context = Global.context("test")
|
val context = Global.buildContext{
|
||||||
|
name("test")
|
||||||
|
}
|
||||||
context.plugins.load(DummyPlugin())
|
context.plugins.load(DummyPlugin())
|
||||||
//Global.plugins.load(DummyPlugin())
|
//Global.plugins.load(DummyPlugin())
|
||||||
val members = context.gather<Name>("test")
|
val members = context.gather<Name>("test")
|
||||||
|
@ -1,25 +1,4 @@
|
|||||||
package space.kscience.dataforge.context
|
package space.kscience.dataforge.context
|
||||||
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
|
internal actual val globalLoggerFactory: PluginFactory<out LogManager> = DefaultLogManager
|
||||||
public class NativeLogManager : AbstractPlugin(), LogManager {
|
|
||||||
|
|
||||||
override fun log(name: Name, tag: String, body: () -> String) {
|
|
||||||
val message: String = body.safe
|
|
||||||
println("[${context.name}] $name: $message")
|
|
||||||
}
|
|
||||||
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
|
||||||
|
|
||||||
public companion object : PluginFactory<NativeLogManager> {
|
|
||||||
override fun invoke(meta: Meta, context: Context): NativeLogManager = NativeLogManager()
|
|
||||||
|
|
||||||
override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.native")
|
|
||||||
override val type: KClass<out NativeLogManager> = NativeLogManager::class
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual val globalLoggerFactory: PluginFactory<out LogManager> = NativeLogManager
|
|
||||||
|
@ -9,6 +9,7 @@ import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
|
|||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.toName
|
import space.kscience.dataforge.names.toName
|
||||||
|
import kotlin.native.concurrent.ThreadLocal
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||||
@ -62,7 +63,8 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
|
|
||||||
public companion object : PluginFactory<IOPlugin> {
|
public companion object : PluginFactory<IOPlugin> {
|
||||||
public val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
|
public val defaultMetaFormats: List<MetaFormatFactory> = listOf(JsonMetaFormat, BinaryMetaFormat)
|
||||||
public val defaultEnvelopeFormats: List<EnvelopeFormatFactory> = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
|
public val defaultEnvelopeFormats: List<EnvelopeFormatFactory> =
|
||||||
|
listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat)
|
||||||
|
|
||||||
override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
|
override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
|
||||||
|
|
||||||
@ -71,4 +73,10 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public val Context.io: IOPlugin get() = plugins.fetch(IOPlugin)
|
@ThreadLocal
|
||||||
|
internal val ioContext = Global.withEnv {
|
||||||
|
name("IO")
|
||||||
|
plugin(IOPlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
public val Context.io: IOPlugin get() = (if (this == Global) ioContext else this).fetch(IOPlugin)
|
@ -161,7 +161,7 @@ public class TaggedEnvelopeFormat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val default by lazy { invoke() }
|
private val default by lazy { invoke(context = ioContext) }
|
||||||
|
|
||||||
override fun readPartial(input: Input): PartialEnvelope =
|
override fun readPartial(input: Input): PartialEnvelope =
|
||||||
default.run { readPartial(input) }
|
default.run { readPartial(input) }
|
||||||
|
@ -197,7 +197,7 @@ public class TaglessEnvelopeFormat(
|
|||||||
return TaglessEnvelopeFormat(context.io, meta)
|
return TaglessEnvelopeFormat(context.io, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val default by lazy { invoke() }
|
private val default by lazy { invoke(context = ioContext) }
|
||||||
|
|
||||||
override fun readPartial(input: Input): PartialEnvelope =
|
override fun readPartial(input: Input): PartialEnvelope =
|
||||||
default.run { readPartial(input) }
|
default.run { readPartial(input) }
|
||||||
|
@ -193,6 +193,7 @@ public abstract interface class space/kscience/dataforge/meta/Meta : space/kscie
|
|||||||
public final class space/kscience/dataforge/meta/Meta$Companion {
|
public final class space/kscience/dataforge/meta/Meta$Companion {
|
||||||
public static final field TYPE Ljava/lang/String;
|
public static final field TYPE Ljava/lang/String;
|
||||||
public static final field VALUE_KEY Ljava/lang/String;
|
public static final field VALUE_KEY Ljava/lang/String;
|
||||||
|
public final fun equals (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/Meta;)Z
|
||||||
public final fun getEMPTY ()Lspace/kscience/dataforge/meta/Meta;
|
public final fun getEMPTY ()Lspace/kscience/dataforge/meta/Meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,8 @@ public interface Meta : MetaRepr, ItemProvider {
|
|||||||
*/
|
*/
|
||||||
public const val VALUE_KEY: String = "@value"
|
public const val VALUE_KEY: String = "@value"
|
||||||
|
|
||||||
|
public fun equals(meta1: Meta, meta2: Meta): Boolean = meta1.items == meta2.items
|
||||||
|
|
||||||
public val EMPTY: Meta = object : MetaBase() {
|
public val EMPTY: Meta = object : MetaBase() {
|
||||||
override val items: Map<NameToken, MetaItem> = emptyMap()
|
override val items: Map<NameToken, MetaItem> = emptyMap()
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public operator fun <M : TypedMeta<M>> M.get(key: NameToken): TypedMetaItem<M>?
|
|||||||
public abstract class MetaBase : Meta {
|
public abstract class MetaBase : Meta {
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = if (other is Meta) {
|
override fun equals(other: Any?): Boolean = if (other is Meta) {
|
||||||
this.items == other.items
|
Meta.equals(this, other)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import space.kscience.dataforge.context.Global
|
|||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.int
|
import space.kscience.dataforge.meta.int
|
||||||
import space.kscience.dataforge.workspace.WorkspaceBuilder
|
import space.kscience.dataforge.workspace.WorkspaceBuilder
|
||||||
|
|
||||||
import space.kscience.dataforge.workspace.target
|
import space.kscience.dataforge.workspace.target
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -16,7 +15,7 @@ class BuildersKtTest {
|
|||||||
val workspace = WorkspaceBuilder(Global).apply {
|
val workspace = WorkspaceBuilder(Global).apply {
|
||||||
println("I am working")
|
println("I am working")
|
||||||
|
|
||||||
context("test")
|
context { name("test") }
|
||||||
|
|
||||||
target("testTarget") {
|
target("testTarget") {
|
||||||
"a" put 12
|
"a" put 12
|
||||||
@ -29,7 +28,7 @@ class BuildersKtTest {
|
|||||||
val script = """
|
val script = """
|
||||||
println("I am working")
|
println("I am working")
|
||||||
|
|
||||||
context("test")
|
context{ name("test") }
|
||||||
|
|
||||||
target("testTarget"){
|
target("testTarget"){
|
||||||
"a" put 12
|
"a" put 12
|
||||||
|
@ -50,8 +50,8 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas
|
|||||||
/**
|
/**
|
||||||
* Define a context for the workspace
|
* Define a context for the workspace
|
||||||
*/
|
*/
|
||||||
public fun context(name: String = "workspace", block: ContextBuilder.() -> Unit = {}) {
|
public fun context(block: ContextBuilder.() -> Unit = {}) {
|
||||||
this.context = ContextBuilder(parentContext, name).apply(block).build()
|
this.context = parentContext.buildContext(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user