Explicit API mode
This commit is contained in:
parent
606faa5e1b
commit
d170f5d60c
@ -2,6 +2,6 @@ package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
|
||||
interface Factory<out T : Any> {
|
||||
operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
|
||||
public interface Factory<out T : Any> {
|
||||
public operator fun invoke(meta: Meta = Meta.EMPTY, context: Context = Global): T
|
||||
}
|
@ -24,16 +24,14 @@ import hep.dataforge.names.isEmpty
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
interface Named {
|
||||
public interface Named {
|
||||
|
||||
/**
|
||||
* The name of this object instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val name: Name
|
||||
public val name: Name
|
||||
|
||||
companion object {
|
||||
public companion object {
|
||||
|
||||
/**
|
||||
* Get the name of given object. If object is Named its name is used,
|
||||
@ -42,7 +40,7 @@ interface Named {
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
fun nameOf(obj: Any): Name {
|
||||
public fun nameOf(obj: Any): Name {
|
||||
return if (obj is Named) {
|
||||
obj.name
|
||||
} else {
|
||||
@ -56,5 +54,4 @@ interface Named {
|
||||
* Check if this object has an empty name and therefore is anonymous.
|
||||
* @return
|
||||
*/
|
||||
val Named.isAnonymous: Boolean
|
||||
get() = this.name.isEmpty()
|
||||
public val Named.isAnonymous: Boolean get() = this.name.isEmpty()
|
||||
|
@ -22,21 +22,17 @@ import hep.dataforge.provider.Provider
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
public interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
|
||||
/**
|
||||
* Get tag for this plugin
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val tag: PluginTag
|
||||
public val tag: PluginTag
|
||||
|
||||
val meta: Meta
|
||||
public val meta: Meta
|
||||
|
||||
/**
|
||||
* The name of this plugin ignoring version and group
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
override val name: Name get() = tag.name.toName()
|
||||
|
||||
@ -44,25 +40,21 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
* Plugin dependencies which are required to attach this plugin. Plugin
|
||||
* dependencies must be initialized and enabled in the Context before this
|
||||
* plugin is enabled.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun dependsOn(): Collection<PluginFactory<*>>
|
||||
public fun dependsOn(): Collection<PluginFactory<*>>
|
||||
|
||||
/**
|
||||
* Start this plugin and attach registration info to the context. This method
|
||||
* should be called only via PluginManager to avoid dependency issues.
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
fun attach(context: Context)
|
||||
public fun attach(context: Context)
|
||||
|
||||
/**
|
||||
* Stop this plugin and remove registration info from context and other
|
||||
* plugins. This method should be called only via PluginManager to avoid
|
||||
* dependency issues.
|
||||
*/
|
||||
fun detach()
|
||||
public fun detach()
|
||||
|
||||
override fun toMeta(): Meta = Meta {
|
||||
"context" put context.name.toString()
|
||||
@ -71,9 +63,9 @@ interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
"meta" put meta
|
||||
}
|
||||
|
||||
companion object {
|
||||
public companion object {
|
||||
|
||||
const val PLUGIN_TARGET = "plugin"
|
||||
public const val PLUGIN_TARGET = "plugin"
|
||||
}
|
||||
|
||||
}
|
@ -5,12 +5,12 @@ import hep.dataforge.meta.MetaBuilder
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
val tag: PluginTag
|
||||
val type: KClass<out T>
|
||||
public interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
public val tag: PluginTag
|
||||
public val type: KClass<out T>
|
||||
|
||||
companion object{
|
||||
const val TYPE = "pluginFactory"
|
||||
public companion object{
|
||||
public const val TYPE: String = "pluginFactory"
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
* @property context A context for this plugin manager
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
||||
public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
||||
|
||||
/**
|
||||
* A set of loaded plugins
|
||||
@ -34,7 +34,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
private val parent: PluginManager? = context.parent?.plugins
|
||||
|
||||
|
||||
fun sequence(recursive: Boolean): Sequence<Plugin> {
|
||||
public fun sequence(recursive: Boolean): Sequence<Plugin> {
|
||||
return if (recursive && parent != null) {
|
||||
plugins.asSequence() + parent.sequence(true)
|
||||
} else {
|
||||
@ -47,7 +47,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
* @param recursive search for parent [PluginManager] plugins
|
||||
* @param predicate condition for the plugin
|
||||
*/
|
||||
fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
|
||||
public fun find(recursive: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? = sequence(recursive).find(predicate)
|
||||
|
||||
|
||||
/**
|
||||
@ -56,7 +56,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
|
||||
public operator fun get(tag: PluginTag, recursive: Boolean = true): Plugin? = find(recursive) { tag.matches(it.tag) }
|
||||
|
||||
|
||||
/**
|
||||
@ -71,13 +71,13 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
* @return
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
|
||||
public operator fun <T : Any> get(type: KClass<out T>, tag: PluginTag? = null, recursive: Boolean = true): T? =
|
||||
find(recursive) { type.isInstance(it) && (tag == null || tag.matches(it.tag)) } as T?
|
||||
|
||||
inline operator fun <reified T : Any> get(tag: PluginTag? = null, recursive: Boolean = true): T? =
|
||||
public 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? =
|
||||
public inline operator fun <reified T : Plugin> get(factory: PluginFactory<T>, recursive: Boolean = true): T? =
|
||||
get(factory.type, factory.tag, recursive)
|
||||
|
||||
/**
|
||||
@ -87,7 +87,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
* @param plugin
|
||||
* @return
|
||||
*/
|
||||
fun <T : Plugin> load(plugin: T): T {
|
||||
public fun <T : Plugin> load(plugin: T): T {
|
||||
if (context.isActive) error("Can't load plugin into active context")
|
||||
|
||||
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
||||
@ -107,16 +107,16 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
/**
|
||||
* Load a plugin using its factory
|
||||
*/
|
||||
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))
|
||||
|
||||
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))
|
||||
|
||||
/**
|
||||
* Remove a plugin from [PluginManager]
|
||||
*/
|
||||
fun remove(plugin: Plugin) {
|
||||
public fun remove(plugin: Plugin) {
|
||||
if (context.isActive) error("Can't remove plugin from active context")
|
||||
|
||||
if (plugins.contains(plugin)) {
|
||||
@ -130,7 +130,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
* Get an existing plugin with given meta or load new one using provided factory
|
||||
*
|
||||
*/
|
||||
fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
|
||||
public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
|
||||
val loaded = get(factory.type, factory.tag, recursive)
|
||||
return when {
|
||||
loaded == null -> load(factory(meta, context))
|
||||
@ -139,7 +139,7 @@ class PluginManager(override val context: Context) : ContextAware, Iterable<Plug
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Plugin> fetch(
|
||||
public fun <T : Plugin> fetch(
|
||||
factory: PluginFactory<T>,
|
||||
recursive: Boolean = true,
|
||||
metaBuilder: MetaBuilder.() -> Unit
|
||||
|
@ -26,25 +26,25 @@ import hep.dataforge.names.toName
|
||||
* @author Alexander Nozik
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
|
||||
public inline class Path(public val tokens: List<PathToken>) : Iterable<PathToken> {
|
||||
|
||||
val head: PathToken? get() = tokens.firstOrNull()
|
||||
public val head: PathToken? get() = tokens.firstOrNull()
|
||||
|
||||
val length: Int get() = tokens.size
|
||||
public val length: Int get() = tokens.size
|
||||
|
||||
/**
|
||||
* Returns non-empty optional containing the chain without first segment in case of chain path.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
|
||||
public val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
|
||||
|
||||
override fun iterator(): Iterator<PathToken> = tokens.iterator()
|
||||
|
||||
companion object {
|
||||
const val PATH_SEGMENT_SEPARATOR = "/"
|
||||
public companion object {
|
||||
public const val PATH_SEGMENT_SEPARATOR = "/"
|
||||
|
||||
fun parse(path: String): Path {
|
||||
public fun parse(path: String): Path {
|
||||
val head = path.substringBefore(PATH_SEGMENT_SEPARATOR)
|
||||
val tail = path.substringAfter(PATH_SEGMENT_SEPARATOR)
|
||||
return PathToken.parse(head).toPath() + parse(tail)
|
||||
@ -52,18 +52,18 @@ inline class Path(val tokens: List<PathToken>) : Iterable<PathToken> {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Path.plus(path: Path) = Path(this.tokens + path.tokens)
|
||||
public operator fun Path.plus(path: Path): Path = Path(this.tokens + path.tokens)
|
||||
|
||||
data class PathToken(val name: Name, val target: String? = null) {
|
||||
public data class PathToken(val name: Name, val target: String? = null) {
|
||||
override fun toString(): String = if (target == null) {
|
||||
name.toString()
|
||||
} else {
|
||||
"$target$TARGET_SEPARATOR$name"
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TARGET_SEPARATOR = "::"
|
||||
fun parse(token: String): PathToken {
|
||||
public companion object {
|
||||
public const val TARGET_SEPARATOR: String = "::"
|
||||
public fun parse(token: String): PathToken {
|
||||
val target = token.substringBefore(TARGET_SEPARATOR, "")
|
||||
val name = token.substringAfter(TARGET_SEPARATOR).toName()
|
||||
if (target.contains("[")) TODO("target separators in queries are not supported")
|
||||
@ -72,4 +72,4 @@ data class PathToken(val name: Name, val target: String? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
fun PathToken.toPath() = Path(listOf(this))
|
||||
public fun PathToken.toPath(): Path = Path(listOf(this))
|
||||
|
@ -22,29 +22,25 @@ import hep.dataforge.names.Name
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
interface Provider {
|
||||
public interface Provider {
|
||||
|
||||
/**
|
||||
* Default target for this provider
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val defaultTarget: String get() = ""
|
||||
public val defaultTarget: String get() = ""
|
||||
|
||||
/**
|
||||
* Default target for next chain segment
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val defaultChainTarget: String get() = ""
|
||||
public val defaultChainTarget: String get() = ""
|
||||
|
||||
/**
|
||||
* A map of direct children for specific target
|
||||
*/
|
||||
fun provideTop(target: String): Map<Name, Any> = emptyMap()
|
||||
public fun provideTop(target: String): Map<Name, Any> = emptyMap()
|
||||
}
|
||||
|
||||
fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
|
||||
public fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
|
||||
if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
|
||||
val first = path.first()
|
||||
val target = targetOverride ?: first.target ?: defaultTarget
|
||||
@ -63,7 +59,7 @@ fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
|
||||
/**
|
||||
* Type checked provide
|
||||
*/
|
||||
inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
|
||||
public inline fun <reified T : Any> Provider.provide(path: String, targetOverride: String? = null): T? {
|
||||
return provide(Path.parse(path), targetOverride) as? T
|
||||
}
|
||||
//
|
||||
@ -77,7 +73,7 @@ inline fun <reified T : Any> Provider.provide(path: String, targetOverride: Stri
|
||||
/**
|
||||
* Typed top level content
|
||||
*/
|
||||
inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
|
||||
public inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
|
||||
return provideTop(target).mapValues {
|
||||
it.value as? T ?: error("The type of element $it is ${it::class} but ${T::class} is expected")
|
||||
}
|
||||
|
@ -7,4 +7,4 @@ package hep.dataforge.provider
|
||||
*/
|
||||
@MustBeDocumented
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class Type(val id: String)
|
||||
public annotation class Type(val id: String)
|
||||
|
@ -5,23 +5,23 @@ import hep.dataforge.meta.Meta
|
||||
/**
|
||||
* A simple data transformation on a data node
|
||||
*/
|
||||
interface Action<in T : Any, out R : Any> {
|
||||
public interface Action<in T : Any, out R : Any> {
|
||||
/**
|
||||
* Transform the data in the node, producing a new node. By default it is assumed that all calculations are lazy
|
||||
* so not actual computation is started at this moment
|
||||
*/
|
||||
operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
|
||||
public operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
|
||||
|
||||
/**
|
||||
* Terminal action is the one that could not be invoked lazily and requires some kind of blocking computation to invoke
|
||||
*/
|
||||
val isTerminal: Boolean get() = false
|
||||
public val isTerminal: Boolean get() = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Action composition. The result is terminal if one of its parts is terminal
|
||||
*/
|
||||
infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
||||
public infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
||||
// TODO introduce composite action and add optimize by adding action to the list
|
||||
return object : Action<T, R> {
|
||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||
|
@ -1,48 +1,58 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A monitor of goal state that could be accessed only form inside the goal
|
||||
*/
|
||||
class CoroutineMonitor : CoroutineContext.Element {
|
||||
@DFExperimental
|
||||
public class CoroutineMonitor : CoroutineContext.Element {
|
||||
override val key: CoroutineContext.Key<*> get() = CoroutineMonitor
|
||||
|
||||
var totalWork: Double = 1.0
|
||||
var workDone: Double = 0.0
|
||||
var status: String = ""
|
||||
public var totalWork: Double = 1.0
|
||||
public var workDone: Double = 0.0
|
||||
public var status: String = ""
|
||||
|
||||
/**
|
||||
* Mark the goal as started
|
||||
*/
|
||||
fun start() {
|
||||
public fun start() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the goal as completed
|
||||
*/
|
||||
fun finish() {
|
||||
public fun finish() {
|
||||
workDone = totalWork
|
||||
}
|
||||
|
||||
companion object : CoroutineContext.Key<CoroutineMonitor>
|
||||
public companion object : CoroutineContext.Key<CoroutineMonitor>
|
||||
}
|
||||
|
||||
class Dependencies(val values: Collection<Job>) : CoroutineContext.Element {
|
||||
public class Dependencies(public val values: Collection<Job>) : CoroutineContext.Element {
|
||||
override val key: CoroutineContext.Key<*> get() = Dependencies
|
||||
|
||||
companion object : CoroutineContext.Key<Dependencies>
|
||||
public companion object : CoroutineContext.Key<Dependencies>
|
||||
}
|
||||
|
||||
val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
|
||||
val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
|
||||
@DFExperimental
|
||||
public val CoroutineContext.monitor: CoroutineMonitor? get() = this[CoroutineMonitor]
|
||||
@DFExperimental
|
||||
public val CoroutineScope.monitor: CoroutineMonitor? get() = coroutineContext.monitor
|
||||
|
||||
val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
|
||||
public val Job.dependencies: Collection<Job> get() = this[Dependencies]?.values ?: emptyList()
|
||||
|
||||
val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
|
||||
val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
|
||||
val Job.status: String get() = monitor?.status ?: ""
|
||||
val Job.progress: Double get() = workDone / totalWork
|
||||
@DFExperimental
|
||||
public val Job.totalWork: Double get() = dependencies.sumByDouble { totalWork } + (monitor?.totalWork ?: 0.0)
|
||||
@DFExperimental
|
||||
public val Job.workDone: Double get() = dependencies.sumByDouble { workDone } + (monitor?.workDone ?: 0.0)
|
||||
@DFExperimental
|
||||
public val Job.status: String get() = monitor?.status ?: ""
|
||||
@DFExperimental
|
||||
public val Job.progress: Double get() = workDone / totalWork
|
@ -11,7 +11,7 @@ import kotlin.reflect.KClass
|
||||
/**
|
||||
* A data element characterized by its meta
|
||||
*/
|
||||
interface Data<out T : Any> : Goal<T>, MetaRepr{
|
||||
public interface Data<out T : Any> : Goal<T>, MetaRepr{
|
||||
/**
|
||||
* Type marker for the data. The type is known before the calculation takes place so it could be checked.
|
||||
*/
|
||||
|
@ -6,18 +6,18 @@ import hep.dataforge.values.*
|
||||
/**
|
||||
* A converter of generic object to and from [MetaItem]
|
||||
*/
|
||||
interface MetaConverter<T : Any> {
|
||||
fun itemToObject(item: MetaItem<*>): T
|
||||
fun objectToMetaItem(obj: T): MetaItem<*>
|
||||
public interface MetaConverter<T : Any> {
|
||||
public fun itemToObject(item: MetaItem<*>): T
|
||||
public fun objectToMetaItem(obj: T): MetaItem<*>
|
||||
|
||||
companion object {
|
||||
public companion object {
|
||||
|
||||
val item = object : MetaConverter<MetaItem<*>> {
|
||||
public val item: MetaConverter<MetaItem<*>> = object : MetaConverter<MetaItem<*>> {
|
||||
override fun itemToObject(item: MetaItem<*>): MetaItem<*> = item
|
||||
override fun objectToMetaItem(obj: MetaItem<*>): MetaItem<*> = obj
|
||||
}
|
||||
|
||||
val meta = object : MetaConverter<Meta> {
|
||||
public val meta: MetaConverter<Meta> = object : MetaConverter<Meta> {
|
||||
override fun itemToObject(item: MetaItem<*>): Meta = when (item) {
|
||||
is MetaItem.NodeItem -> item.node
|
||||
is MetaItem.ValueItem -> item.value.toMeta()
|
||||
@ -26,7 +26,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Meta): MetaItem<*> = MetaItem.NodeItem(obj)
|
||||
}
|
||||
|
||||
val value = object : MetaConverter<Value> {
|
||||
public val value: MetaConverter<Value> = object : MetaConverter<Value> {
|
||||
override fun itemToObject(item: MetaItem<*>): Value = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -35,7 +35,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Value): MetaItem<*> = MetaItem.ValueItem(obj)
|
||||
}
|
||||
|
||||
val string = object : MetaConverter<String> {
|
||||
public val string: MetaConverter<String> = object : MetaConverter<String> {
|
||||
override fun itemToObject(item: MetaItem<*>): String = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -44,7 +44,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: String): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val boolean = object : MetaConverter<Boolean> {
|
||||
public val boolean: MetaConverter<Boolean> = object : MetaConverter<Boolean> {
|
||||
override fun itemToObject(item: MetaItem<*>): Boolean = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -53,7 +53,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Boolean): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val number = object : MetaConverter<Number> {
|
||||
public val number: MetaConverter<Number> = object : MetaConverter<Number> {
|
||||
override fun itemToObject(item: MetaItem<*>): Number = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -62,7 +62,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Number): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val double = object : MetaConverter<Double> {
|
||||
public val double: MetaConverter<Double> = object : MetaConverter<Double> {
|
||||
override fun itemToObject(item: MetaItem<*>): Double = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -71,7 +71,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Double): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val float = object : MetaConverter<Float> {
|
||||
public val float: MetaConverter<Float> = object : MetaConverter<Float> {
|
||||
override fun itemToObject(item: MetaItem<*>): Float = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -80,7 +80,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Float): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val int = object : MetaConverter<Int> {
|
||||
public val int: MetaConverter<Int> = object : MetaConverter<Int> {
|
||||
override fun itemToObject(item: MetaItem<*>): Int = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -89,7 +89,7 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Int): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
val long = object : MetaConverter<Long> {
|
||||
public val long: MetaConverter<Long> = object : MetaConverter<Long> {
|
||||
override fun itemToObject(item: MetaItem<*>): Long = when (item) {
|
||||
is MetaItem.NodeItem -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value")
|
||||
is MetaItem.ValueItem -> item.value
|
||||
@ -98,14 +98,14 @@ interface MetaConverter<T : Any> {
|
||||
override fun objectToMetaItem(obj: Long): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
|
||||
public inline fun <reified E : Enum<E>> enum(): MetaConverter<E> = object : MetaConverter<E> {
|
||||
@Suppress("USELESS_CAST")
|
||||
override fun itemToObject(item: MetaItem<*>): E = item.enum<E>() as? E ?: error("The Item is not a Enum")
|
||||
|
||||
override fun objectToMetaItem(obj: E): MetaItem<*> = MetaItem.ValueItem(obj.asValue())
|
||||
}
|
||||
|
||||
fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
|
||||
public fun <T> valueList(writer: (T) -> Value = {Value.of(it)}, reader: (Value) -> T): MetaConverter<List<T>> =
|
||||
object : MetaConverter<List<T>> {
|
||||
override fun itemToObject(item: MetaItem<*>): List<T> =
|
||||
item.value?.list?.map(reader) ?: error("The item is not a value list")
|
||||
@ -117,8 +117,8 @@ interface MetaConverter<T : Any> {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
|
||||
fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
|
||||
public fun <T : Any> MetaConverter<T>.nullableItemToObject(item: MetaItem<*>?): T? = item?.let { itemToObject(it) }
|
||||
public fun <T : Any> MetaConverter<T>.nullableObjectToMetaItem(obj: T?): MetaItem<*>? = obj?.let { objectToMetaItem(it) }
|
||||
|
||||
fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
|
||||
fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
|
||||
public fun <T : Any> MetaConverter<T>.metaToObject(meta: Meta): T = itemToObject(MetaItem.NodeItem(meta))
|
||||
public fun <T : Any> MetaConverter<T>.valueToObject(value: Value): T = itemToObject(MetaItem.ValueItem(value))
|
||||
|
@ -6,31 +6,31 @@ import hep.dataforge.names.Name
|
||||
/**
|
||||
* A transformation for meta item or a group of items
|
||||
*/
|
||||
interface TransformationRule {
|
||||
public interface TransformationRule {
|
||||
|
||||
/**
|
||||
* Check if this transformation should be applied to a node with given name and value
|
||||
*/
|
||||
fun matches(name: Name, item: MetaItem<*>?): Boolean
|
||||
public fun matches(name: Name, item: MetaItem<*>?): Boolean
|
||||
|
||||
/**
|
||||
* Select all items to be transformed. Item could be a value as well as node
|
||||
*
|
||||
* @return a sequence of item paths to be transformed
|
||||
*/
|
||||
fun selectItems(meta: Meta): Sequence<Name> =
|
||||
public fun selectItems(meta: Meta): Sequence<Name> =
|
||||
meta.sequence().filter { matches(it.first, it.second) }.map { it.first }
|
||||
|
||||
/**
|
||||
* Apply transformation for a single item (Node or Value) to the target
|
||||
*/
|
||||
fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
|
||||
public fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
|
||||
}
|
||||
|
||||
/**
|
||||
* A transformation which keeps all elements, matching [selector] unchanged.
|
||||
*/
|
||||
data class KeepTransformationRule(val selector: (Name) -> Boolean) :
|
||||
public data class KeepTransformationRule(val selector: (Name) -> Boolean) :
|
||||
TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return selector(name)
|
||||
@ -47,7 +47,7 @@ data class KeepTransformationRule(val selector: (Name) -> Boolean) :
|
||||
/**
|
||||
* A transformation which transforms element with specific name
|
||||
*/
|
||||
data class SingleItemTransformationRule(
|
||||
public data class SingleItemTransformationRule(
|
||||
val from: Name,
|
||||
val transform: MutableMeta<*>.(Name, MetaItem<*>?) -> Unit
|
||||
) : TransformationRule {
|
||||
@ -64,7 +64,7 @@ data class SingleItemTransformationRule(
|
||||
}
|
||||
}
|
||||
|
||||
data class RegexItemTransformationRule(
|
||||
public data class RegexItemTransformationRule(
|
||||
val from: Regex,
|
||||
val transform: MutableMeta<*>.(name: Name, MatchResult, MetaItem<*>?) -> Unit
|
||||
) : TransformationRule {
|
||||
@ -84,12 +84,12 @@ data class RegexItemTransformationRule(
|
||||
/**
|
||||
* A set of [TransformationRule] to either transform static meta or create dynamically updated [MutableMeta]
|
||||
*/
|
||||
inline class MetaTransformation(val transformations: Collection<TransformationRule>) {
|
||||
public inline class MetaTransformation(public val transformations: Collection<TransformationRule>) {
|
||||
|
||||
/**
|
||||
* Produce new meta using only those items that match transformation rules
|
||||
*/
|
||||
fun generate(source: Meta): Meta =
|
||||
public fun generate(source: Meta): Meta =
|
||||
Meta {
|
||||
transformations.forEach { rule ->
|
||||
rule.selectItems(source).forEach { name ->
|
||||
@ -102,7 +102,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
* Generate an observable configuration that contains only elements defined by transformation rules and changes with the source
|
||||
*/
|
||||
@DFExperimental
|
||||
fun generate(source: Config): ObservableMeta = Config().apply {
|
||||
public fun generate(source: Config): ObservableMeta = Config().apply {
|
||||
transformations.forEach { rule ->
|
||||
rule.selectItems(source).forEach { name ->
|
||||
rule.transformItem(name, source[name], this)
|
||||
@ -115,7 +115,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
/**
|
||||
* Transform a meta, replacing all elements found in rules with transformed entries
|
||||
*/
|
||||
fun apply(source: Meta): Meta =
|
||||
public fun apply(source: Meta): Meta =
|
||||
source.edit {
|
||||
transformations.forEach { rule ->
|
||||
rule.selectItems(source).forEach { name ->
|
||||
@ -128,7 +128,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
/**
|
||||
* Listens for changes in the source node and translates them into second node if transformation set contains a corresponding rule.
|
||||
*/
|
||||
fun <M : MutableMeta<M>> bind(source: Config, target: M) {
|
||||
public fun <M : MutableMeta<M>> bind(source: Config, target: M) {
|
||||
source.onChange(target) { name, _, newItem ->
|
||||
transformations.forEach { t ->
|
||||
if (t.matches(name, newItem)) {
|
||||
@ -147,27 +147,27 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
/**
|
||||
* A builder for a set of transformation rules
|
||||
*/
|
||||
class MetaTransformationBuilder {
|
||||
val transformations = HashSet<TransformationRule>()
|
||||
public class MetaTransformationBuilder {
|
||||
private val transformations = HashSet<TransformationRule>()
|
||||
|
||||
/**
|
||||
* Keep all items with name satisfying the criteria
|
||||
*/
|
||||
fun keep(selector: (Name) -> Boolean) {
|
||||
public fun keep(selector: (Name) -> Boolean) {
|
||||
transformations.add(KeepTransformationRule(selector))
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep specific item (including its descendants)
|
||||
*/
|
||||
fun keep(name: Name) {
|
||||
public fun keep(name: Name) {
|
||||
keep { it == name }
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep nodes by regex
|
||||
*/
|
||||
fun keep(regex: String) {
|
||||
public fun keep(regex: String) {
|
||||
transformations.add(
|
||||
RegexItemTransformationRule(regex.toRegex()) { name, _, metaItem ->
|
||||
setItem(name, metaItem)
|
||||
@ -177,7 +177,7 @@ class MetaTransformationBuilder {
|
||||
/**
|
||||
* Move an item from [from] to [to], optionally applying [operation] it defined
|
||||
*/
|
||||
fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
|
||||
public fun move(from: Name, to: Name, operation: (MetaItem<*>?) -> Any? = { it }) {
|
||||
transformations.add(
|
||||
SingleItemTransformationRule(from) { _, item ->
|
||||
set(to, operation(item))
|
||||
@ -185,5 +185,5 @@ class MetaTransformationBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
fun build() = MetaTransformation(transformations)
|
||||
public fun build(): MetaTransformation = MetaTransformation(transformations)
|
||||
}
|
@ -13,7 +13,7 @@ public fun Value.isNull(): Boolean = this == Null
|
||||
*/
|
||||
public fun Value.isList(): Boolean = this.list.size > 1
|
||||
|
||||
public val Value.boolean
|
||||
public val Value.boolean: Boolean
|
||||
get() = this == True
|
||||
|| this.list.firstOrNull() == True
|
||||
|| (type == ValueType.STRING && string.toBoolean())
|
||||
|
@ -35,7 +35,7 @@ public abstract class WorkspacePlugin : AbstractPlugin() {
|
||||
public inline fun <reified T : Any> task(
|
||||
name: String,
|
||||
noinline builder: TaskBuilder<T>.() -> Unit
|
||||
) = task(name, T::class, builder)
|
||||
): GenericTask<T> = task(name, T::class, builder)
|
||||
|
||||
//
|
||||
////TODO add delegates to build gradle-like tasks
|
||||
|
Loading…
Reference in New Issue
Block a user