Skip to content

Commit

Permalink
use traversal to add elements, mostly to fix remote graph setups
Browse files Browse the repository at this point in the history
when using remote graphs, Graph is actually just an empty shell and
can't be used to e.g. add elements.

open problems:
* marshalled classes can use the @id annotation to specify
the ID of a vertex, but we cannot set the id of a vertex inside a traversal
* same needs to be applied for edges

re #223
  • Loading branch information
mpollmeier committed Mar 24, 2018
1 parent d04d82a commit f87a79f
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 50 deletions.
31 changes: 20 additions & 11 deletions gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala
Original file line number Diff line number Diff line change
Expand Up @@ -669,12 +669,14 @@ class GremlinScala[End](val traversal: GraphTraversal[_, End]) {
// -------------------

/** set the property to the given value */
def property[A](key: Key[A], value: A)(implicit ev: End <:< Element) =
GremlinScala[End, Labels](traversal.property(key.name, value))
def property[A](keyValue: KeyValue[A])(
implicit ev: End <:< Element): GremlinScala.Aux[End, Labels] =
property(keyValue.key, keyValue.value)

/** set the property to the given value */
def property[A](keyValue: KeyValue[A])(implicit ev: End <:< Element) =
GremlinScala[End, Labels](traversal.property(keyValue.key.name, keyValue.value))
def property[A](key: Key[A], value: A)(
implicit ev: End <:< Element): GremlinScala.Aux[End, Labels] =
GremlinScala[End, Labels](traversal.property(key.name, value))

/** set the property to the value determined by the given traversal */
def property[A](key: Key[A])(value: GremlinScala[End] => GremlinScala[A])(
Expand Down Expand Up @@ -859,12 +861,19 @@ class GremlinScala[End](val traversal: GraphTraversal[_, End]) {
GremlinScala[Edge, Labels](traversal.bothE(labels: _*))

/** may be used together with `from` / `to`, see TraversalSpec for examples */
def addE(label: String)(implicit ev: End <:< Vertex): GremlinScala.Aux[Edge, Labels] =
GremlinScala[Edge, Labels](traversal.addE(label))
def addE(label: StepLabel[Vertex])(implicit ev: End <:< Vertex): GremlinScala.Aux[Edge, Labels] =
GremlinScala[Edge, Labels](traversal.addE(label.name))
def addE(label: String, properties: KeyValue[_]*)(
implicit ev: End <:< Vertex): GremlinScala.Aux[Edge, Labels] = {
val newTrav = properties.foldLeft(traversal.addE(label)) { (trav, prop) =>
trav.property(prop.key.name, prop.value)
}
GremlinScala[Edge, Labels](newTrav)
}

/** modulator, use in conjunction with addE()
def addE(label: StepLabel[Vertex], properties: KeyValue[_]*)(
implicit ev: End <:< Vertex): GremlinScala.Aux[Edge, Labels] =
addE(label.name, properties: _*)

/** modulator, use in conjunction with addE
* http://tinkerpop.apache.org/docs/current/reference/#from-step */
def from(vertex: Vertex): GremlinScala.Aux[End, Labels] =
GremlinScala[End, Labels](traversal.from(vertex))
Expand All @@ -884,8 +893,8 @@ class GremlinScala[End](val traversal: GraphTraversal[_, End]) {
GremlinScala[End, Labels](
traversal.from(fromTraversal(start).traversal.asInstanceOf[GraphTraversal[End, Vertex]]))

/** modulator, use in conjunction with addE()
* http://tinkerpop.apache.org/docs/current/reference/#from-step */
/** modulator, use in conjunction with addE
* http://tinkerpop.apache.org/docs/current/reference/#to-step */
def to(vertex: Vertex): GremlinScala.Aux[End, Labels] =
GremlinScala[End, Labels](traversal.to(vertex))

Expand Down
39 changes: 23 additions & 16 deletions gremlin-scala/src/main/scala/gremlin/scala/ScalaGraph.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ case class ScalaGraph(traversalSource: TraversalSource) {
def configure(conf: TraversalSource => TraversalSource) =
ScalaGraph(conf(TraversalSource(graph)))

def addVertex(label: String): Vertex = graph.addVertex(label)
def addVertex(): Vertex =
traversalSource.underlying.addV().next

def addVertex(): Vertex = graph.addVertex()
def addVertex(label: String): Vertex =
traversalSource.underlying.addV(label).next

def addVertex(label: String, properties: (String, Any)*): Vertex = {
val labelParam = Seq(T.label, label)
val params =
properties.flatMap(pair => Seq(pair._1, pair._2.asInstanceOf[AnyRef]))
graph.addVertex(labelParam ++ params: _*)
def addVertex(properties: (String, Any)*): Vertex = {
val traversal = traversalSource.underlying.addV()
properties.foreach { case (key, value) => traversal.property(key, value) }
traversal.next
}

def addVertex(properties: (String, Any)*): Vertex = {
val params =
properties.flatMap(pair => Seq(pair._1, pair._2.asInstanceOf[AnyRef]))
graph.addVertex(params: _*)
def addVertex(label: String, properties: (String, Any)*): Vertex = {
val traversal = traversalSource.underlying.addV(label)
properties.foreach { case (key, value) => traversal.property(key, value) }
traversal.next
}

def addVertex(label: String, properties: Map[String, Any]): Vertex =
Expand All @@ -44,10 +45,13 @@ case class ScalaGraph(traversalSource: TraversalSource) {
/**
* Save an object's values into a new vertex
* @param cc The case class to persist as a vertex
*
* Note: this doesn't work with remote graphs, since remote graphs require you to use
* traversal steps to add a vertex (e.g. addV), but there's no step to set the ID
*/
def addVertex[CC <: Product: Marshallable](cc: CC): Vertex = {
val fromCC = implicitly[Marshallable[CC]].fromCC(cc)
val idParam = fromCC.id.toSeq.flatMap(List(T.id, _))
val idParam = fromCC.id.toSeq.flatMap(List(T.id, _)) //TODO: this will break things
val labelParam = Seq(T.label, fromCC.label)
val params = fromCC.valueMap.toSeq.flatMap(pair => Seq(pair._1, pair._2.asInstanceOf[AnyRef]))
graph.addVertex(idParam ++ labelParam ++ params: _*)
Expand All @@ -60,34 +64,37 @@ case class ScalaGraph(traversalSource: TraversalSource) {
def +(label: String, properties: KeyValue[_]*): Vertex =
addVertex(label, properties.map(v => (v.key.name, v.value)).toMap)

/** start a traversal with `addV` */
@deprecated("use `traversal.addV`", "3.3.1.2")
def addV(): GremlinScala.Aux[Vertex, HNil] =
traversalSource.addV()

/** start a traversal with `addV` */
@deprecated("use `traversal.addV`", "3.3.1.2")
def addV(label: String): GremlinScala.Aux[Vertex, HNil] =
traversalSource.addV(label)

@deprecated("use `traversal.inject`", "3.3.1.2")
/** start a traversal with given `starts`` */
def inject[S](starts: S*): GremlinScala.Aux[S, HNil] =
traversalSource.inject(starts: _*)

// start traversal with all vertices
/** start traversal with all vertices */
@deprecated("use `traversal.V`", "3.3.1.2")
def V(): GremlinScala.Aux[Vertex, HNil] =
traversalSource.V()

// start traversal with all edges
/** start traversal with all edges */
@deprecated("use `traversal.E`", "3.3.1.2")
def E(): GremlinScala.Aux[Edge, HNil] =
traversalSource.E()

// start traversal with some vertices identified by given ids
/** start traversal with some vertices identified by given ids */
@deprecated("use `traversal.V`", "3.3.1.2")
def V(vertexIds: Any*): GremlinScala.Aux[Vertex, HNil] =
traversalSource.V(vertexIds: _*)

// start traversal with some edges identified by given ids
/** start traversal with some edges identified by given ids */
@deprecated("use `traversal.E`", "3.3.1.2")
def E(edgeIds: Any*): GremlinScala.Aux[Edge, HNil] =
traversalSource.E(edgeIds: _*)
Expand Down
23 changes: 8 additions & 15 deletions gremlin-scala/src/main/scala/gremlin/scala/ScalaVertex.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,8 @@ case class ScalaVertex(vertex: Vertex) extends ScalaElement[Vertex] {

def bothE(labels: String*) = start().bothE(labels: _*)

def addEdge(
label: String,
inVertex: Vertex,
properties: Seq[KeyValue[_]] = Nil
): Edge = {
val params =
properties.toSeq.flatMap(pair => Seq(pair.key.name, pair.value.asInstanceOf[AnyRef]))
vertex.addEdge(label, inVertex.vertex, params: _*)
}
def addEdge(label: String, inVertex: Vertex, properties: KeyValue[_]*): Edge =
vertex.start.addE(label, properties: _*).to(inVertex).head

def addEdge[CC <: Product: Marshallable](inVertex: Vertex, cc: CC): Edge = {
val fromCC = implicitly[Marshallable[CC]].fromCC(cc)
Expand All @@ -74,27 +67,27 @@ case class ScalaVertex(vertex: Vertex) extends ScalaElement[Vertex] {
}

def <--(se: SemiEdge): Edge =
se.from.asScala.addEdge(se.label, vertex, se.properties)
se.from.asScala.addEdge(se.label, vertex, se.properties: _*)

def <--(de: SemiDoubleEdge): (Edge, Edge) =
addEdge(de.label, de.right, de.properties) -> de.right.asScala
.addEdge(de.label, vertex, de.properties)
addEdge(de.label, de.right, de.properties: _*) -> de.right.asScala
.addEdge(de.label, vertex, de.properties: _*)

def ---(label: String): SemiEdge = SemiEdge(vertex, label)

def ---(label: String, properties: KeyValue[_]*): SemiEdge =
SemiEdge(vertex, label, properties)
SemiEdge(vertex, label, properties: _*)

def ---(label: String, properties: Map[String, Any]): SemiEdge =
SemiEdge(vertex, label, properties.map {
case (key, value) => Key[Any](key) -> value
}.toSeq)
}.toSeq: _*)

def ---[CC <: Product: Marshallable](cc: CC): SemiEdge = {
val fromCC = implicitly[Marshallable[CC]].fromCC(cc)
SemiEdge(vertex, fromCC.label, fromCC.valueMap.map { r =>
Key[Any](r._1) -> r._2
}.toSeq)
}.toSeq: _*)
}

def vertices(direction: Direction, edgeLabels: String*): util.Iterator[Vertex] =
Expand Down
6 changes: 3 additions & 3 deletions gremlin-scala/src/main/scala/gremlin/scala/SemiEdge.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gremlin.scala

case class SemiEdge(from: Vertex, label: String, properties: Seq[KeyValue[_]] = Nil) {
def -->(to: Vertex) = from.asScala.addEdge(label, to, properties)
case class SemiEdge(from: Vertex, label: String, properties: KeyValue[_]*) {
def -->(to: Vertex) = from.asScala.addEdge(label, to, properties: _*)
}

case class SemiDoubleEdge(right: Vertex, label: String, properties: Seq[KeyValue[_]] = Nil)
case class SemiDoubleEdge(right: Vertex, label: String, properties: KeyValue[_]*)
4 changes: 2 additions & 2 deletions gremlin-scala/src/main/scala/gremlin/scala/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ package object scala {
lazy val keyValues: KeyValues = labelAndValues.tail
lazy val properties: List[KeyValue[_]] = keyValues.toList

def ---(from: Vertex) = SemiEdge(from, label, properties)
def -->(right: Vertex) = SemiDoubleEdge(right, label, properties)
def ---(from: Vertex) = SemiEdge(from, label, properties: _*)
def -->(right: Vertex) = SemiDoubleEdge(right, label, properties: _*)
}
}
5 changes: 2 additions & 3 deletions gremlin-scala/src/test/scala/gremlin/scala/ElementSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ElementSpec extends TestBase {
* TODO: `properties` should take `Key` as well
*/
it("sets a property with multiple values") {
val v = graph.addV().property(Name, "marko").property(Name, "marko a. rodriguez").head
val v = graph.addVertex((Name.name -> "marko"), (Name.name -> "marko a. rodriguez"))
graph.V(v).properties(Name.name).count.head shouldBe 2

v.property(Cardinality.list, Name.name, "m. a. rodriguez")
Expand Down Expand Up @@ -166,8 +166,7 @@ class ElementSpec extends TestBase {
val v1 = graph.addVertex()
val v2 = graph.addVertex()

val e =
v1.asScala.addEdge("testLabel", v2, Seq(TestProperty -> "testValue"))
val e = v1.asScala.addEdge("testLabel", v2, TestProperty -> "testValue")
e.label shouldBe "testLabel"
e.value2(TestProperty) shouldBe "testValue"
e.valueMap(TestProperty.name) shouldBe Map(TestProperty.name -> "testValue")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ class TraversalSpec extends WordSpec with Matchers {
}

"group" should {

"modulate by property key" in new Fixture {
val results: JMap[Int, JCollection[Vertex]] =
graph.V
Expand Down

0 comments on commit f87a79f

Please sign in to comment.