diff --git a/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala b/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala index 42563a74..da3c56ad 100644 --- a/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala +++ b/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala @@ -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])( @@ -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)) @@ -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)) diff --git a/gremlin-scala/src/main/scala/gremlin/scala/ScalaGraph.scala b/gremlin-scala/src/main/scala/gremlin/scala/ScalaGraph.scala index cc8fdfc8..5d2072a9 100644 --- a/gremlin-scala/src/main/scala/gremlin/scala/ScalaGraph.scala +++ b/gremlin-scala/src/main/scala/gremlin/scala/ScalaGraph.scala @@ -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 = @@ -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: _*) @@ -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: _*) diff --git a/gremlin-scala/src/main/scala/gremlin/scala/ScalaVertex.scala b/gremlin-scala/src/main/scala/gremlin/scala/ScalaVertex.scala index 5f3955da..a8a7bb4e 100644 --- a/gremlin-scala/src/main/scala/gremlin/scala/ScalaVertex.scala +++ b/gremlin-scala/src/main/scala/gremlin/scala/ScalaVertex.scala @@ -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) @@ -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] = diff --git a/gremlin-scala/src/main/scala/gremlin/scala/SemiEdge.scala b/gremlin-scala/src/main/scala/gremlin/scala/SemiEdge.scala index 52bbe6ca..5672a396 100644 --- a/gremlin-scala/src/main/scala/gremlin/scala/SemiEdge.scala +++ b/gremlin-scala/src/main/scala/gremlin/scala/SemiEdge.scala @@ -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[_]*) diff --git a/gremlin-scala/src/main/scala/gremlin/scala/package.scala b/gremlin-scala/src/main/scala/gremlin/scala/package.scala index 63ff1ef9..f391e5a4 100644 --- a/gremlin-scala/src/main/scala/gremlin/scala/package.scala +++ b/gremlin-scala/src/main/scala/gremlin/scala/package.scala @@ -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: _*) } } diff --git a/gremlin-scala/src/test/scala/gremlin/scala/ElementSpec.scala b/gremlin-scala/src/test/scala/gremlin/scala/ElementSpec.scala index 153d853a..6db09468 100644 --- a/gremlin-scala/src/test/scala/gremlin/scala/ElementSpec.scala +++ b/gremlin-scala/src/test/scala/gremlin/scala/ElementSpec.scala @@ -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") @@ -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") diff --git a/gremlin-scala/src/test/scala/gremlin/scala/TraversalSpec.scala b/gremlin-scala/src/test/scala/gremlin/scala/TraversalSpec.scala index 6eae4e44..9c8f40ea 100644 --- a/gremlin-scala/src/test/scala/gremlin/scala/TraversalSpec.scala +++ b/gremlin-scala/src/test/scala/gremlin/scala/TraversalSpec.scala @@ -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