fix some tinkerpop logic and add attribute test
This commit is contained in:
@@ -26,6 +26,7 @@ public interface ConnectionAttribute : Attribute<NodeConnection>
|
||||
|
||||
|
||||
public interface StateNode : AttributeContainer {
|
||||
public val id: NodeId
|
||||
|
||||
public val type: NodeType
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@ package center.sciprog.workflow.state
|
||||
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal
|
||||
import org.apache.tinkerpop.gremlin.structure.Edge
|
||||
import org.apache.tinkerpop.gremlin.structure.Element
|
||||
import org.apache.tinkerpop.gremlin.structure.Vertex
|
||||
import space.kscience.attributes.Attribute
|
||||
import space.kscience.attributes.Attributes
|
||||
import space.kscience.attributes.UnsafeAPI
|
||||
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ as TinkerPop
|
||||
|
||||
public interface TinkerAttributeAccessor<T> {
|
||||
/**
|
||||
@@ -53,7 +55,7 @@ public class SimpleTinkerAttributeAccessor<T>(
|
||||
|
||||
override fun Element.readAttribute(): T = this.value<T>(key)
|
||||
|
||||
override fun <E : Element> GraphTraversal<*, E>.readAttribute(): GraphTraversal<*, T?> = values<T>(key)
|
||||
override fun <E : Element> GraphTraversal<*, E>.readAttribute(): GraphTraversal<*, T?> = valueOrNull(key)
|
||||
|
||||
override fun <E : Element> GraphTraversal<*, E>.writeAttribute(
|
||||
attribute: Attribute<T>,
|
||||
@@ -87,7 +89,7 @@ public interface TinkerConnectionAttributeAccessor<T : NodeConnection> : TinkerA
|
||||
|
||||
override fun <E : Element> GraphTraversal<*, E>.writeAttributeFrom(
|
||||
attributes: Attributes
|
||||
): GraphTraversal<*, E> = writeAttribute(attribute,attributes[attribute])
|
||||
): GraphTraversal<*, E> = writeAttribute(attribute, attributes[attribute])
|
||||
}
|
||||
|
||||
public class SimpleTinkerConnectionAttributeAccessor(
|
||||
@@ -159,3 +161,9 @@ public class TinkerAttributes(
|
||||
|
||||
public companion object
|
||||
}
|
||||
|
||||
public fun <E, T> GraphTraversal<E, *>.valueOrNull(propertyKey: String): GraphTraversal<E, T?> = choose<T>(
|
||||
TinkerPop.has<Vertex>(propertyKey),
|
||||
TinkerPop.values<Vertex, T>(propertyKey),
|
||||
TinkerPop.constant(null)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package center.sciprog.workflow.state
|
||||
|
||||
import space.kscience.attributes.Attribute
|
||||
|
||||
public interface TinkerRegistry {
|
||||
public fun attributePipeByLabel(label: String): TinkerAttributeAccessor<*>
|
||||
public fun <T> attributePipeByAttribute(attribute: Attribute<T>): TinkerAttributeAccessor<T>
|
||||
}
|
||||
|
||||
private class SimpleTinkerRegistry(val accessors: Set<TinkerAttributeAccessor<*>>) : TinkerRegistry {
|
||||
override fun attributePipeByLabel(label: String): TinkerAttributeAccessor<*> = accessors.single { it.key == label }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T> attributePipeByAttribute(attribute: Attribute<T>): TinkerAttributeAccessor<T> = accessors.single {
|
||||
it.attribute == attribute
|
||||
} as TinkerAttributeAccessor<T>
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a TinkerRegistry with the provided set of attribute accessors.
|
||||
*
|
||||
* @param accessors A set of TinkerAttributeAccessor objects that define the mapping
|
||||
* between graph elements and their corresponding attributes.
|
||||
* @return A TinkerRegistry instance that maps attributes to their corresponding keys or labels.
|
||||
*/
|
||||
public fun TinkerRegistry(
|
||||
accessors: Set<TinkerAttributeAccessor<*>>
|
||||
): TinkerRegistry = SimpleTinkerRegistry(accessors)
|
||||
|
||||
public fun <T> MutableSet<TinkerAttributeAccessor<*>>.attribute(
|
||||
key: String,
|
||||
attribute: Attribute<T>
|
||||
) {
|
||||
add(SimpleTinkerAttributeAccessor(key, attribute))
|
||||
}
|
||||
|
||||
public fun TinkerRegistry(
|
||||
registryBuilder: MutableSet<TinkerAttributeAccessor<*>>.() -> Unit
|
||||
): TinkerRegistry = TinkerRegistry(buildSet(registryBuilder))
|
||||
|
||||
@@ -14,18 +14,12 @@ import space.kscience.attributes.Attributes
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
public interface TinkerRegistry {
|
||||
public fun attributePipeByLabel(label: String): TinkerAttributeAccessor<*>
|
||||
public fun <T> attributePipeByAttribute(attribute: Attribute<T>): TinkerAttributeAccessor<T>
|
||||
}
|
||||
|
||||
|
||||
public class TinkerNode(
|
||||
private val vertex: Vertex,
|
||||
private val registry: TinkerRegistry
|
||||
) : StateNode {
|
||||
|
||||
public val id: NodeId get() = vertex.id().toString()
|
||||
override val id: NodeId get() = vertex.id().toString()
|
||||
|
||||
override val type: NodeType get() = vertex.label()
|
||||
|
||||
@@ -36,7 +30,7 @@ public class TinkerStateGraph(
|
||||
private val ts: GraphTraversalSource,
|
||||
public val registry: TinkerRegistry,
|
||||
override val clock: Clock = Clock.System,
|
||||
) : MutableStateGraph {
|
||||
) : MutableStateGraph, AutoCloseable by ts.graph {
|
||||
|
||||
private val sharedEventFlow = MutableSharedFlow<GraphHistoryEvent>()
|
||||
|
||||
@@ -97,7 +91,7 @@ public class TinkerStateGraph(
|
||||
value: T,
|
||||
time: Instant
|
||||
): Unit = with(registry.attributePipeByAttribute(attribute)) {
|
||||
val oldValue = ts.V(nodeId)
|
||||
val oldValue: T? = ts.V(nodeId)
|
||||
.readAttribute()
|
||||
.choose<T>(
|
||||
P.neq(value),
|
||||
|
||||
@@ -1,4 +1,37 @@
|
||||
package center.sciprog.workflow.state
|
||||
|
||||
class AttributesTest {
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory
|
||||
import space.kscience.attributes.Attribute
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class AttributesTest {
|
||||
|
||||
object AttributeA : Attribute<Double>
|
||||
object AttributeB : Attribute<String>
|
||||
|
||||
@Test
|
||||
fun tinkerAttributesWriteRead() = runTest {
|
||||
val graph = TinkerFactory.createModern()
|
||||
|
||||
val registry = TinkerRegistry {
|
||||
attribute("a", AttributeA)
|
||||
attribute("b", AttributeB)
|
||||
}
|
||||
|
||||
TinkerStateGraph(graph.traversal(), registry).use { state ->
|
||||
val node = state.createNode("test")
|
||||
|
||||
state.setAttribute(node.id, AttributeA, 1.0)
|
||||
|
||||
assertEquals(1.0, node.attributes[AttributeA])
|
||||
|
||||
state.removeAttribute(node.id, AttributeA)
|
||||
|
||||
assertEquals(null, node.attributes[AttributeA])
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user