Refactory Factory

This commit is contained in:
Alexander Nozik 2021-12-12 17:58:01 +03:00
parent c480cd8e4d
commit 1e97165328
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
22 changed files with 50 additions and 37 deletions

View File

@ -4,6 +4,7 @@
### Added ### Added
### Changed ### Changed
- `Factory` is now `fun interface` and uses `build` instead of `invoke`. `invoke moved to an extension.
### Deprecated ### Deprecated

View File

@ -4,7 +4,7 @@ plugins {
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.5.2" version = "0.5.3-dev-1"
repositories{ repositories{
mavenCentral() mavenCentral()
} }

View File

@ -68,7 +68,7 @@ public class ContextBuilder internal constructor(
// Add if does not exist // Add if does not exist
if (existing == null) { if (existing == null) {
//TODO bypass if parent already has plugin with given meta? //TODO bypass if parent already has plugin with given meta?
val plugin = factory(meta, parent) val plugin = factory.build(parent, meta)
for ((depFactory, deoMeta) in plugin.dependsOn()) { for ((depFactory, deoMeta) in plugin.dependsOn()) {
addPlugin(depFactory, deoMeta) addPlugin(depFactory, deoMeta)

View File

@ -2,6 +2,11 @@ package space.kscience.dataforge.context
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
public interface Factory<out T : Any> { public fun interface Factory<out T> {
public operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T public fun build(context: Context, meta: Meta): T
} }
public operator fun <T> Factory<T>.invoke(
meta: Meta = Meta.EMPTY,
context: Context = Global,
): T = build(context, meta)

View File

@ -63,7 +63,7 @@ public class DefaultLogManager : AbstractPlugin(), LogManager {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
public companion object : PluginFactory<DefaultLogManager> { public companion object : PluginFactory<DefaultLogManager> {
override fun invoke(meta: Meta, context: Context): DefaultLogManager = DefaultLogManager() override fun build(context: Context, meta: Meta): DefaultLogManager = DefaultLogManager()
override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.default") override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.default")
override val type: KClass<out DefaultLogManager> = DefaultLogManager::class override val type: KClass<out DefaultLogManager> = DefaultLogManager::class
@ -75,7 +75,7 @@ public class DefaultLogManager : AbstractPlugin(), LogManager {
*/ */
public val Context.logger: LogManager public val Context.logger: LogManager
get() = plugins.find(inherit = true) { it is LogManager } as? LogManager get() = plugins.find(inherit = true) { it is LogManager } as? LogManager
?: getGlobalLoggerFactory()(context = Global).apply { attach(Global) } ?: getGlobalLoggerFactory().build(context = Global, meta = Meta.EMPTY).apply { attach(Global) }
/** /**
* The named proxy logger for a context member * The named proxy logger for a context member

View File

@ -18,7 +18,7 @@ public interface PluginFactory<T : Plugin> : Factory<T> {
* Plugin factory created for the specific actual plugin * Plugin factory created for the specific actual plugin
*/ */
internal class DeFactoPluginFactory<T : Plugin>(val plugin: T) : PluginFactory<T> { internal class DeFactoPluginFactory<T : Plugin>(val plugin: T) : PluginFactory<T> {
override fun invoke(meta: Meta, context: Context): T = plugin override fun build(context: Context, meta: Meta): T = plugin
override val tag: PluginTag get() = plugin.tag override val tag: PluginTag get() = plugin.tag
override val type: KClass<out T> get() = plugin::class override val type: KClass<out T> get() = plugin::class
} }

View File

@ -22,7 +22,7 @@ public class ConsoleLogManager : AbstractPlugin(), LogManager {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
public companion object : PluginFactory<ConsoleLogManager> { public companion object : PluginFactory<ConsoleLogManager> {
override fun invoke(meta: Meta, context: Context): ConsoleLogManager = ConsoleLogManager() override fun build(context: Context, meta: Meta): ConsoleLogManager = ConsoleLogManager()
override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.jsConsole") override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.jsConsole")
override val type: KClass<out ConsoleLogManager> = ConsoleLogManager::class override val type: KClass<out ConsoleLogManager> = ConsoleLogManager::class

View File

@ -24,7 +24,7 @@ public class SlfLogManager : AbstractPlugin(), LogManager {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
public companion object : PluginFactory<SlfLogManager> { public companion object : PluginFactory<SlfLogManager> {
override fun invoke(meta: Meta, context: Context): SlfLogManager = SlfLogManager() override fun build(context: Context, meta: Meta): SlfLogManager = SlfLogManager()
override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.kotlinLogging") override val tag: PluginTag = PluginTag(group = PluginTag.DATAFORGE_GROUP, name = "log.kotlinLogging")
override val type: KClass<out SlfLogManager> = SlfLogManager::class override val type: KClass<out SlfLogManager> = SlfLogManager::class

View File

@ -5,6 +5,7 @@ import io.ktor.utils.io.core.Output
import io.ktor.utils.io.core.readBytes import io.ktor.utils.io.core.readBytes
import io.ktor.utils.io.core.readUTF8Line import io.ktor.utils.io.core.readUTF8Line
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.io.* import space.kscience.dataforge.io.*
import space.kscience.dataforge.io.IOFormat.Companion.META_KEY import space.kscience.dataforge.io.IOFormat.Companion.META_KEY
import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY
@ -71,7 +72,7 @@ public class FrontMatterEnvelopeFormat(
metaFormatFactory: MetaFormatFactory, metaFormatFactory: MetaFormatFactory,
formatMeta: Meta, formatMeta: Meta,
) { ) {
val metaFormat = metaFormatFactory(formatMeta, this@FrontMatterEnvelopeFormat.io.context) val metaFormat = metaFormatFactory.build(this@FrontMatterEnvelopeFormat.io.context, formatMeta)
output.writeRawString("$SEPARATOR\r\n") output.writeRawString("$SEPARATOR\r\n")
metaFormat.run { this.writeObject(output, envelope.meta) } metaFormat.run { this.writeObject(output, envelope.meta) }
output.writeRawString("$SEPARATOR\r\n") output.writeRawString("$SEPARATOR\r\n")
@ -91,20 +92,20 @@ public class FrontMatterEnvelopeFormat(
private val metaTypeRegex = "---(\\w*)\\s*".toRegex() private val metaTypeRegex = "---(\\w*)\\s*".toRegex()
override fun invoke(meta: Meta, context: Context): EnvelopeFormat { override fun build(context: Context, meta: Meta): EnvelopeFormat {
return FrontMatterEnvelopeFormat(context.io, meta) return FrontMatterEnvelopeFormat(context.io, meta)
} }
override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? = binary.read { override fun peekFormat(io: IOPlugin, binary: Binary): EnvelopeFormat? = binary.read {
val line = readSafeUtf8Line() val line = readSafeUtf8Line()
return@read if (line.startsWith("---")) { return@read if (line.startsWith("---")) {
invoke() default
} else { } else {
null null
} }
} }
private val default by lazy { invoke() } private val default by lazy { build(Global, Meta.EMPTY) }
override fun readPartial(input: Input): PartialEnvelope = override fun readPartial(input: Input): PartialEnvelope =
default.readPartial(input) default.readPartial(input)

View File

@ -115,13 +115,13 @@ public class YamlMetaFormat(private val meta: Meta) : MetaFormat {
} }
public companion object : MetaFormatFactory { public companion object : MetaFormatFactory {
override fun invoke(meta: Meta, context: Context): MetaFormat = YamlMetaFormat(meta) override fun build(context: Context, meta: Meta): MetaFormat = YamlMetaFormat(meta)
override val shortName: String = "yaml" override val shortName: String = "yaml"
override val key: Short = 0x594d //YM override val key: Short = 0x594d //YM
private val default = YamlMetaFormat() private val default = YamlMetaFormat(Meta.EMPTY)
override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit = override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit =
default.writeMeta(output, meta, descriptor) default.writeMeta(output, meta, descriptor)

View File

@ -27,6 +27,6 @@ public class YamlPlugin(meta: Meta) : AbstractPlugin(meta) {
override val tag: PluginTag = PluginTag("io.yaml", group = PluginTag.DATAFORGE_GROUP) override val tag: PluginTag = PluginTag("io.yaml", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out YamlPlugin> = YamlPlugin::class override val type: KClass<out YamlPlugin> = YamlPlugin::class
override fun invoke(meta: Meta, context: Context): YamlPlugin = YamlPlugin(meta) override fun build(context: Context, meta: Meta): YamlPlugin = YamlPlugin(meta)
} }
} }

View File

@ -33,7 +33,7 @@ public class EnvelopeBuilder : Envelope {
/** /**
* Construct a data binary from given builder * Construct a data binary from given builder
*/ */
public fun data(block: Output.() -> Unit) { public inline fun data(block: Output.() -> Unit) {
data = buildByteArray { block() }.asBinary() data = buildByteArray { block() }.asBinary()
} }

View File

@ -42,7 +42,7 @@ public interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeForm
override val name: Name get() = "envelope".asName() override val name: Name get() = "envelope".asName()
override val type: KType get() = typeOf<Envelope>() override val type: KType get() = typeOf<Envelope>()
override fun invoke(meta: Meta, context: Context): EnvelopeFormat override fun build(context: Context, meta: Meta): EnvelopeFormat
/** /**
* Try to infer specific format from input and return null if the attempt is failed. * Try to infer specific format from input and return null if the attempt is failed.

View File

@ -102,7 +102,7 @@ public interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRep
public fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(this, obj) } public fun <T : Any> IOFormat<T>.toBinary(obj: T): Binary = Binary { writeObject(this, obj) }
public object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> { public object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
override fun invoke(meta: Meta, context: Context): IOFormat<Double> = this override fun build(context: Context, meta: Meta): IOFormat<Double> = this
override val name: Name = "double".asName() override val name: Name = "double".asName()

View File

@ -25,7 +25,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
return ioFormatFactories.find { it.name == name }?.let { return ioFormatFactories.find { it.name == name }?.let {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
if (it.type != type) error("Format type ${it.type} is not the same as requested type $type") if (it.type != type) error("Format type ${it.type} is not the same as requested type $type")
else it.invoke(item[META_KEY] ?: Meta.EMPTY, context) as IOFormat<T> else it.build(context, item[META_KEY] ?: Meta.EMPTY) as IOFormat<T>
} }
} }
@ -34,17 +34,17 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
} }
public fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? = public fun resolveMetaFormat(key: Short, meta: Meta = Meta.EMPTY): MetaFormat? =
metaFormatFactories.find { it.key == key }?.invoke(meta) metaFormatFactories.find { it.key == key }?.build(context, meta)
public fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? = public fun resolveMetaFormat(name: String, meta: Meta = Meta.EMPTY): MetaFormat? =
metaFormatFactories.find { it.shortName == name }?.invoke(meta) metaFormatFactories.find { it.shortName == name }?.build(context, meta)
public val envelopeFormatFactories: Collection<EnvelopeFormatFactory> by lazy { public val envelopeFormatFactories: Collection<EnvelopeFormatFactory> by lazy {
context.gather<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values context.gather<EnvelopeFormatFactory>(ENVELOPE_FORMAT_TYPE).values
} }
private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? = private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
envelopeFormatFactories.find { it.name == name }?.invoke(meta, context) envelopeFormatFactories.find { it.name == name }?.build(context, meta)
public fun resolveEnvelopeFormat(item: Meta): EnvelopeFormat? { public fun resolveEnvelopeFormat(item: Meta): EnvelopeFormat? {
val name = item.string ?: item[NAME_KEY]?.string ?: error("Envelope format name not defined") val name = item.string ?: item[NAME_KEY]?.string ?: error("Envelope format name not defined")
@ -66,7 +66,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP) override val tag: PluginTag = PluginTag("io", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out IOPlugin> = IOPlugin::class override val type: KClass<out IOPlugin> = IOPlugin::class
override fun invoke(meta: Meta, context: Context): IOPlugin = IOPlugin(meta) override fun build(context: Context, meta: Meta): IOPlugin = IOPlugin(meta)
} }
} }

View File

@ -41,7 +41,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
public companion object : MetaFormatFactory { public companion object : MetaFormatFactory {
public val DEFAULT_JSON: Json = Json { prettyPrint = true } public val DEFAULT_JSON: Json = Json { prettyPrint = true }
override fun invoke(meta: Meta, context: Context): MetaFormat = default override fun build(context: Context, meta: Meta): MetaFormat = default
override val shortName: String = "json" override val shortName: String = "json"
override val key: Short = 0x4a53//"JS" override val key: Short = 0x4a53//"JS"

View File

@ -5,6 +5,7 @@ import io.ktor.utils.io.core.Input
import io.ktor.utils.io.core.Output import io.ktor.utils.io.core.Output
import io.ktor.utils.io.core.use import io.ktor.utils.io.core.use
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
@ -46,7 +47,7 @@ public interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
public val key: Short get() = name.hashCode().toShort() public val key: Short get() = name.hashCode().toShort()
override operator fun invoke(meta: Meta, context: Context): MetaFormat override fun build(context: Context, meta: Meta): MetaFormat
public companion object { public companion object {
public const val META_FORMAT_TYPE: String = "io.format.meta" public const val META_FORMAT_TYPE: String = "io.format.meta"
@ -59,12 +60,12 @@ public fun Meta.toString(format: MetaFormat): String = buildByteArray {
} }
}.decodeToString() }.decodeToString()
public fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory()) public fun Meta.toString(formatFactory: MetaFormatFactory): String = toString(formatFactory.build(Global, Meta.EMPTY))
public fun MetaFormat.parse(str: String): Meta { public fun MetaFormat.parse(str: String): Meta {
return ByteReadPacket(str.encodeToByteArray()).use { readObject(it) } return ByteReadPacket(str.encodeToByteArray()).use { readObject(it) }
} }
public fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = invoke(formatMeta).parse(str) public fun MetaFormatFactory.parse(str: String, formatMeta: Meta): Meta = build(Global, formatMeta).parse(str)

View File

@ -2,6 +2,7 @@ package space.kscience.dataforge.io
import io.ktor.utils.io.core.* import io.ktor.utils.io.core.*
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.io.IOFormat.Companion.META_KEY import space.kscience.dataforge.io.IOFormat.Companion.META_KEY
import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
@ -47,7 +48,7 @@ public class TaggedEnvelopeFormat(
metaFormatFactory: MetaFormatFactory, metaFormatFactory: MetaFormatFactory,
formatMeta: Meta, formatMeta: Meta,
) { ) {
val metaFormat = metaFormatFactory.invoke(formatMeta, this@TaggedEnvelopeFormat.io.context) val metaFormat = metaFormatFactory.build(this@TaggedEnvelopeFormat.io.context, formatMeta)
val metaBytes = metaFormat.toBinary(envelope.meta) val metaBytes = metaFormat.toBinary(envelope.meta)
val actualSize: ULong = (envelope.data?.size ?: 0).toULong() val actualSize: ULong = (envelope.data?.size ?: 0).toULong()
val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize) val tag = Tag(metaFormatFactory.key, metaBytes.size.toUInt() + 2u, actualSize)
@ -118,7 +119,7 @@ public class TaggedEnvelopeFormat(
override val name: Name = super.name + "tagged" override val name: Name = super.name + "tagged"
override fun invoke(meta: Meta, context: Context): EnvelopeFormat { override fun build(context: Context, meta: Meta): EnvelopeFormat {
val io = context.io val io = context.io
val metaFormatName = meta["name"].string?.let { Name.parse(it) } ?: JsonMetaFormat.name val metaFormatName = meta["name"].string?.let { Name.parse(it) } ?: JsonMetaFormat.name
@ -161,7 +162,7 @@ public class TaggedEnvelopeFormat(
} }
} }
private val default by lazy { invoke() } private val default by lazy { build(Global, Meta.EMPTY) }
override fun readPartial(input: Input): PartialEnvelope = override fun readPartial(input: Input): PartialEnvelope =
default.run { readPartial(input) } default.run { readPartial(input) }

View File

@ -2,6 +2,7 @@ package space.kscience.dataforge.io
import io.ktor.utils.io.core.* import io.ktor.utils.io.core.*
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.io.IOFormat.Companion.META_KEY import space.kscience.dataforge.io.IOFormat.Companion.META_KEY
import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
@ -34,7 +35,7 @@ public class TaglessEnvelopeFormat(
metaFormatFactory: MetaFormatFactory, metaFormatFactory: MetaFormatFactory,
formatMeta: Meta formatMeta: Meta
) { ) {
val metaFormat = metaFormatFactory(formatMeta, this.io.context) val metaFormat = metaFormatFactory.build(this.io.context, formatMeta)
//printing header //printing header
output.writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n") output.writeRawString(TAGLESS_ENVELOPE_HEADER + "\r\n")
@ -193,9 +194,9 @@ public class TaglessEnvelopeFormat(
override val name: Name = TAGLESS_ENVELOPE_TYPE.asName() override val name: Name = TAGLESS_ENVELOPE_TYPE.asName()
override fun invoke(meta: Meta, context: Context): EnvelopeFormat = TaglessEnvelopeFormat(context.io, meta) override fun build(context: Context, meta: Meta): EnvelopeFormat = TaglessEnvelopeFormat(context.io, meta)
private val default by lazy { invoke() } private val default by lazy { build(Global, Meta.EMPTY) }
override fun readPartial(input: Input): PartialEnvelope = override fun readPartial(input: Input): PartialEnvelope =
default.run { readPartial(input) } default.run { readPartial(input) }

View File

@ -34,7 +34,7 @@ class DataPropagationTestPlugin : WorkspacePlugin() {
override val type: KClass<out DataPropagationTestPlugin> = DataPropagationTestPlugin::class override val type: KClass<out DataPropagationTestPlugin> = DataPropagationTestPlugin::class
override fun invoke(meta: Meta, context: Context): DataPropagationTestPlugin = DataPropagationTestPlugin() override fun build(context: Context, meta: Meta): DataPropagationTestPlugin = DataPropagationTestPlugin()
override val tag: PluginTag = PluginTag("Test") override val tag: PluginTag = PluginTag("Test")
} }

View File

@ -22,7 +22,7 @@ import kotlin.test.assertTrue
* Make a fake-factory for a one single plugin. Useful for unique or test plugins * Make a fake-factory for a one single plugin. Useful for unique or test plugins
*/ */
public inline fun <reified P : Plugin> P.toFactory(): PluginFactory<P> = object : PluginFactory<P> { public inline fun <reified P : Plugin> P.toFactory(): PluginFactory<P> = object : PluginFactory<P> {
override fun invoke(meta: Meta, context: Context): P = this@toFactory override fun build(context: Context, meta: Meta): P = this@toFactory
override val tag: PluginTag = this@toFactory.tag override val tag: PluginTag = this@toFactory.tag
override val type: KClass<out P> = P::class override val type: KClass<out P> = P::class

View File

@ -7,3 +7,6 @@ kotlin.parallel.tasks.in.project=true
#kotlin.mpp.enableGranularSourceSetsMetadata=true #kotlin.mpp.enableGranularSourceSetsMetadata=true
#kotlin.native.enableDependencyPropagation=false #kotlin.native.enableDependencyPropagation=false
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
publishing.github=false
publishing.sonatype=false