You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2019/09/09 13:15:00 UTC
[tinkerpop] 01/01: TINKERPOP-2284 wip
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2284
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 051ae70860e585df2ee68ba27e5b63e6a9f97817
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Mon Sep 9 09:14:37 2019 -0400
TINKERPOP-2284 wip
---
CHANGELOG.asciidoc | 3 +
.../traversal/dsl/graph/GraphTraversal.java | 27 ++-
.../gremlin/process/traversal/dsl/graph/__.java | 7 +
.../process/traversal/step/map/ElementMapStep.java | 111 +++++++++++++
.../org/apache/tinkerpop/gremlin/structure/T.java | 8 +
.../traversal/step/map/ElementMapStepTest.java | 42 +++++
.../Process/Traversal/GraphTraversal.cs | 11 ++
.../src/Gremlin.Net/Process/Traversal/__.cs | 10 ++
.../Structure/IO/GraphSON/DirectionDeserializer.cs | 36 ++++
.../Structure/IO/GraphSON/GraphSONReader.cs | 1 +
.../Gherkin/CommonSteps.cs | 15 +-
.../Structure/IO/GraphSON/GraphSONReaderTests.cs | 12 ++
.../lib/process/graph-traversal.js | 11 ++
.../lib/structure/io/graph-serializer.js | 1 +
.../lib/structure/io/type-serializers.js | 7 +
.../test/cucumber/feature-steps.js | 8 +-
.../gremlin_python/process/graph_traversal.py | 14 ++
.../gremlin_python/structure/io/graphsonV3d0.py | 16 +-
.../src/main/jython/radish/feature_steps.py | 8 +-
gremlin-test/features/map/ElementMap.feature | 62 +++++++
.../tinkerpop/gremlin/AbstractGremlinTest.java | 4 +-
.../gremlin/process/ProcessComputerSuite.java | 3 +
.../gremlin/process/ProcessStandardSuite.java | 3 +
.../process/traversal/step/map/ElementMapTest.java | 183 +++++++++++++++++++++
24 files changed, 590 insertions(+), 13 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 3d61b53..8ee342e 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -24,6 +24,9 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
=== TinkerPop 3.4.4 (Release Date: NOT OFFICIALLY RELEASED YET)
* Provided support for DSLs by way of remote connections through `AnonymousTraversalSource`.
+* Added `elementMap()` step.
+* Allowed for embedded map assertions in GLV tests.
+* Added `Direction` deserialization support in GLVs.
[[release-3-4-3]]
=== TinkerPop 3.4.3 (Release Date: August 5, 2019)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index ce445c4..5a932c3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -80,6 +80,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountLocalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.DedupLocalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
@@ -553,7 +554,26 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
- * Map the {@link Element} to a {@link Map} of the property values key'd according to their {@link Property#key}.
+ * Map the {@link Element} to a {@code Map} of the property values key'd according to their {@link Property#key}.
+ * If no property keys are provided, then all property values are retrieved. For vertices, the {@code Map} will
+ * be returned with the assumption of single property values along with {@link T#id} and {@link T#label}. Prefer
+ * {@link #valueMap(String...)} if multi-property processing is required. For edges, keys will include additional
+ * related edge structure of {@link Direction#IN} and {@link Direction#OUT} which themselves are {@code Map}
+ * instances of the particular {@link Vertex} represented by {@link T#id} and {@link T#label}.
+ *
+ * @param propertyKeys the properties to retrieve
+ * @param <E2> the value type of the returned properties
+ * @return the traversal with an appended {@link ElementMapStep}.
+ * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#elementmap-step" target="_blank">Reference Documentation - ElementMap Step</a>
+ * @since 3.4.4
+ */
+ public default <E2> GraphTraversal<S, Map<Object, E2>> elementMap(final String... propertyKeys) {
+ this.asAdmin().getBytecode().addStep(Symbols.elementMap, propertyKeys);
+ return this.asAdmin().addStep(new ElementMapStep<>(this.asAdmin(), propertyKeys));
+ }
+
+ /**
+ * Map the {@link Element} to a {@code Map} of the property values key'd according to their {@link Property#key}.
* If no property keys are provided, then all property values are retrieved.
*
* @param propertyKeys the properties to retrieve
@@ -568,7 +588,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
}
/**
- * Map the {@link Element} to a {@link Map} of the property values key'd according to their {@link Property#key}.
+ * Map the {@link Element} to a {@code Map} of the property values key'd according to their {@link Property#key}.
* If no property keys are provided, then all property values are retrieved.
*
* @param includeTokens whether to include {@link T} tokens in the emitted map.
@@ -578,7 +598,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
* @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#valuemap-step" target="_blank">Reference Documentation - ValueMap Step</a>
* @since 3.0.0-incubating
* @deprecated As of release 3.4.0, deprecated in favor of {@link GraphTraversal#valueMap(String...)} in conjunction with
- * {@link GraphTraversal#with(String, Object)}.
+ * {@link GraphTraversal#with(String, Object)} or simple prefer {@link #elementMap(String...)}.
*/
@Deprecated
public default <E2> GraphTraversal<S, Map<Object, E2>> valueMap(final boolean includeTokens, final String... propertyKeys) {
@@ -2946,6 +2966,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
public static final String values = "values";
public static final String propertyMap = "propertyMap";
public static final String valueMap = "valueMap";
+ public static final String elementMap = "elementMap";
public static final String select = "select";
public static final String key = "key";
public static final String value = "value";
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index ab98930..aab83f4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -254,6 +254,13 @@ public class __ {
}
/**
+ * @see GraphTraversal#elementMap(String...)
+ */
+ public static <A extends Element, B> GraphTraversal<A, Map<Object, B>> elementMap(final String... propertyKeys) {
+ return __.<A>start().elementMap(propertyKeys);
+ }
+
+ /**
* @see GraphTraversal#valueMap(String...)
*/
public static <A extends Element, B> GraphTraversal<A, Map<Object, B>> valueMap(final String... propertyKeys) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
new file mode 100644
index 0000000..c2a2c76
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStep.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Property;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Converts a {@link Element} to a {@code Map}.
+ *
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class ElementMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent {
+
+ protected final String[] propertyKeys;
+
+ public ElementMapStep(final Traversal.Admin traversal, final String... propertyKeys) {
+ super(traversal);
+ this.propertyKeys = propertyKeys;
+ }
+
+ @Override
+ protected Map<K, E> map(final Traverser.Admin<Element> traverser) {
+ final Map<Object, Object> map = new LinkedHashMap<>();
+ final Element element = traverser.get();
+ map.put(T.id, element.id());
+ if (element instanceof VertexProperty) {
+ map.put(T.key, ((VertexProperty<?>) element).key());
+ map.put(T.value, ((VertexProperty<?>) element).value());
+ } else {
+ map.put(T.label, element.label());
+ }
+
+ if (element instanceof Edge) {
+ final Edge e = (Edge) element;
+ map.put(Direction.IN, getVertexStructure(e.inVertex()));
+ map.put(Direction.OUT, getVertexStructure(e.outVertex()));
+ }
+
+ final Iterator<? extends Property> properties = element.properties(this.propertyKeys);
+ while (properties.hasNext()) {
+ final Property<?> property = properties.next();
+ map.put(property.key(), property.value());
+ }
+
+ return (Map) map;
+ }
+
+ protected Map<Object, Object> getVertexStructure(final Vertex v) {
+ final Map<Object, Object> m = new LinkedHashMap<>();
+ m.put(T.id, v.id());
+ m.put(T.label, v.label());
+ return m;
+ }
+
+ public String[] getPropertyKeys() {
+ return propertyKeys;
+ }
+
+ public String toString() {
+ return StringFactory.stepString(this, Arrays.asList(this.propertyKeys));
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ for (final String propertyKey : this.propertyKeys) {
+ result ^= propertyKey.hashCode();
+ }
+ return result;
+ }
+
+ @Override
+ public Set<TraverserRequirement> getRequirements() {
+ return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT);
+ }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/T.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/T.java
index a836840..2d67d6b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/T.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/T.java
@@ -30,6 +30,8 @@ import java.util.function.Function;
public enum T implements Function<Element, Object> {
/**
* Label (representing Element.label())
+ *
+ * @since 3.0.0-incubating
*/
label {
@Override
@@ -44,6 +46,8 @@ public enum T implements Function<Element, Object> {
},
/**
* Id (representing Element.id())
+ *
+ * @since 3.0.0-incubating
*/
id {
@Override
@@ -58,6 +62,8 @@ public enum T implements Function<Element, Object> {
},
/**
* Key (representing Property.key())
+ *
+ * @since 3.0.0-incubating
*/
key {
@Override
@@ -72,6 +78,8 @@ public enum T implements Function<Element, Object> {
},
/**
* Value (representing Property.value())
+ *
+ * @since 3.0.0-incubating
*/
value {
@Override
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStepTest.java
new file mode 100644
index 0000000..3bffbe0
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapStepTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class ElementMapStepTest extends StepTest {
+
+ @Override
+ protected List<Traversal> getTraversals() {
+ return Arrays.asList(
+ __.elementMap(),
+ __.elementMap("name"),
+ __.elementMap("age"),
+ __.elementMap("name", "age")
+ );
+ }
+}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index f22ee8c..f65276b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -487,6 +487,17 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
+ /// Adds the elementMap step to this <see cref="GraphTraversal{SType, EType}" />.
+ /// </summary>
+ public GraphTraversal<S, IDictionary<object, E2>> ElementMap<E2> (params string[] propertyKeys)
+ {
+ var args = new List<object>(0 + propertyKeys.Length) {};
+ args.AddRange(propertyKeys);
+ Bytecode.AddStep("elementMap", args.ToArray());
+ return Wrap<S, IDictionary<object, E2>>(this);
+ }
+
+ /// <summary>
/// Adds the emit step to this <see cref="GraphTraversal{SType, EType}" />.
/// </summary>
public GraphTraversal<S, E> Emit ()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index af31d1b..9bd0b14 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -331,6 +331,16 @@ namespace Gremlin.Net.Process.Traversal
}
/// <summary>
+ /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the elementMap step to that traversal.
+ /// </summary>
+ public static GraphTraversal<object, IDictionary<object, E2>> ElementMap<E2>(params string[] propertyKeys)
+ {
+ return propertyKeys.Length == 0
+ ? new GraphTraversal<object, IDictionary<object, E2>>().ElementMap<E2>()
+ : new GraphTraversal<object, IDictionary<object, E2>>().ElementMap<E2>(propertyKeys);
+ }
+
+ /// <summary>
/// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the emit step to that traversal.
/// </summary>
public static GraphTraversal<object, object> Emit()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
new file mode 100644
index 0000000..4027171
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
@@ -0,0 +1,36 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using Gremlin.Net.Process.Traversal;
+using Newtonsoft.Json.Linq;
+
+namespace Gremlin.Net.Structure.IO.GraphSON
+{
+ internal class DirectionDeserializer : IGraphSONDeserializer
+ {
+ public dynamic Objectify(JToken graphsonObject, GraphSONReader reader)
+ {
+ return Direction.GetByValue(graphsonObject.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
index 5ced99a..63641f0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -44,6 +44,7 @@ namespace Gremlin.Net.Structure.IO.GraphSON
{"g:Int64", new Int64Converter()},
{"g:Float", new FloatConverter()},
{"g:Double", new DoubleConverter()},
+ {"g:Direction", new DirectionDeserializer()},
{"g:UUID", new UuidDeserializer()},
{"g:Date", new DateDeserializer()},
{"g:Timestamp", new DateDeserializer()},
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 96851d2..1c6588b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -51,6 +51,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
new Dictionary<string, Func<string, string, object>>
{
{@"d\[([\d.]+)\]\.([ilfdm])", ToNumber},
+ {@"D\[(.+)\]", ToDirection},
{@"v\[(.+)\]", ToVertex},
{@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id},
{@"v\[(.+)\]\.sid", (x, graphName) => ToVertex(x, graphName).Id.ToString()},
@@ -90,7 +91,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
[Given("using the parameter (\\w+) defined as \"(.*)\"")]
public void UsingParameter(string name, string value)
{
- var parsedValue = ParseValue(value, _graphName);
+ var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName);
_parameters.Add(name, parsedValue);
}
@@ -244,6 +245,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
return T.GetByValue(enumName);
}
+ private static object ToDirection(string enumName, string graphName)
+ {
+ return Direction.GetByValue(enumName);
+ }
+
+// private static string toNormalCase(string name)
+// {
+// return name.Substring(0, 1) + name.Substring(1).ToLower();
+// }
+
private static object ToNumber(string stringNumber, string graphName)
{
return NumericParsers[stringNumber[stringNumber.Length - 1]](
@@ -306,8 +317,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private static object ParseValue(string stringValue, string graphName)
{
- // Parser issue: quotes are not normalized
- stringValue = stringValue.Replace("\\\"", "\"");
Func<string, string, object> parser = null;
string extractedValue = null;
foreach (var kv in Parsers)
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
index 7685b28..3a49143 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSONReaderTests.cs
@@ -280,6 +280,18 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphSON
Assert.Equal(T.Label, readT);
}
+ [Theory, MemberData(nameof(Versions))]
+ public void ShouldDeserializeDirection(int version)
+ {
+ var serializedValue = "{\"@type\":\"g:Direction\",\"@value\":\"OUT\"}";
+ var reader = CreateStandardGraphSONReader(version);
+
+ var jObject = JObject.Parse(serializedValue);
+ var deserializedValue = reader.ToObject(jObject);
+
+ Assert.Equal(Direction.Out, deserializedValue);
+ }
+
[Fact]
public void ShouldDeserializePathFromGraphSON2()
{
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index 157b0af..0fe34d6 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -443,6 +443,16 @@ class GraphTraversal extends Traversal {
}
/**
+ * Graph traversal elementMap method.
+ * @param {...Object} args
+ * @returns {GraphTraversal}
+ */
+ elementMap(...args) {
+ this.bytecode.addStep('elementMap', args);
+ return this;
+ }
+
+ /**
* Graph traversal emit method.
* @param {...Object} args
* @returns {GraphTraversal}
@@ -1264,6 +1274,7 @@ const statics = {
cyclicPath: (...args) => callOnEmptyTraversal('cyclicPath', args),
dedup: (...args) => callOnEmptyTraversal('dedup', args),
drop: (...args) => callOnEmptyTraversal('drop', args),
+ elementMap: (...args) => callOnEmptyTraversal('elementMap', args),
emit: (...args) => callOnEmptyTraversal('emit', args),
filter: (...args) => callOnEmptyTraversal('filter', args),
flatMap: (...args) => callOnEmptyTraversal('flatMap', args),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
index ff14320..7943852 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/graph-serializer.js
@@ -163,6 +163,7 @@ const deserializers = {
'g:Float': typeSerializers.NumberSerializer,
'g:Double': typeSerializers.NumberSerializer,
'g:Date': typeSerializers.DateSerializer,
+ 'g:Direction': typeSerializers.DirectionSerializer,
'g:Vertex': typeSerializers.VertexSerializer,
'g:Edge': typeSerializers.EdgeSerializer,
'g:VertexProperty': typeSerializers.VertexPropertySerializer,
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
index cfd67c9..c581712 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
@@ -363,6 +363,12 @@ class TSerializer extends TypeSerializer {
}
}
+class DirectionSerializer extends TypeSerializer {
+ deserialize(obj) {
+ return t.direction[obj[valueKey]];
+ }
+}
+
class ArraySerializer extends TypeSerializer {
constructor(typeKey) {
super();
@@ -458,6 +464,7 @@ module.exports = {
BulkSetSerializer,
BytecodeSerializer,
DateSerializer,
+ DirectionSerializer,
EdgeSerializer,
EnumSerializer,
LambdaSerializer,
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 02e7b3f..fed551d 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -34,6 +34,7 @@ const traversal = require('../../lib/process/anonymous-traversal').traversal;
const Path = graphModule.Path;
const __ = graphTraversalModule.statics;
const t = traversalModule.t;
+const direction = traversalModule.direction
// Determines whether the feature maps (m[]), are deserialized as objects (true) or maps (false).
// Use false for GraphSON3.
@@ -52,7 +53,8 @@ const parsers = [
[ 's\\[(.*)\\]', toArray ],
[ 'm\\[(.+)\\]', toMap ],
[ 'c\\[(.+)\\]', toLambda ],
- [ 't\\[(.+)\\]', toT ]
+ [ 't\\[(.+)\\]', toT ],
+ [ 'D\\[(.+)\\]', toDirection ]
].map(x => [ new RegExp('^' + x[0] + '$'), x[1] ]);
const ignoreReason = {
@@ -276,6 +278,10 @@ function toT(value) {
return t[value];
}
+function toDirection(value) {
+ return direction[value.toLowerCase()];
+}
+
function toArray(stringList) {
if (stringList === '') {
return new Array(0);
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index 5dde030..4be02f8 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -229,6 +229,10 @@ class GraphTraversal(Traversal):
self.bytecode.add_step("drop", *args)
return self
+ def elementMap(self, *args):
+ self.bytecode.add_step("elementMap", *args)
+ return self
+
def emit(self, *args):
self.bytecode.add_step("emit", *args)
return self
@@ -664,6 +668,10 @@ class __(object):
return cls.graph_traversal(None, None, Bytecode()).drop(*args)
@classmethod
+ def elementMap(cls, *args):
+ return cls.graph_traversal(None, None, Bytecode()).elementMap(*args)
+
+ @classmethod
def emit(cls, *args):
return cls.graph_traversal(None, None, Bytecode()).emit(*args)
@@ -1046,6 +1054,10 @@ def drop(*args):
return __.drop(*args)
+def elementMap(*args):
+ return __.elementMap(*args)
+
+
def emit(*args):
return __.emit(*args)
@@ -1388,6 +1400,8 @@ statics.add_static('dedup', dedup)
statics.add_static('drop', drop)
+statics.add_static('elementMap', elementMap)
+
statics.add_static('emit', emit)
statics.add_static('filter_', filter_)
diff --git a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
index 8c3cd9f..bccb982 100644
--- a/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
+++ b/gremlin-python/src/main/jython/gremlin_python/structure/io/graphsonV3d0.py
@@ -34,7 +34,7 @@ from isodate import parse_duration, duration_isoformat
from gremlin_python import statics
from gremlin_python.statics import FloatType, FunctionType, IntType, LongType, TypeType, DictType, ListType, SetType, SingleByte, ByteBufferType, SingleChar
-from gremlin_python.process.traversal import Binding, Bytecode, P, TextP, Traversal, Traverser, TraversalStrategy, T
+from gremlin_python.process.traversal import Binding, Bytecode, Direction, P, TextP, Traversal, Traverser, TraversalStrategy, T
from gremlin_python.structure.graph import Edge, Property, Vertex, VertexProperty, Path
log = logging.getLogger(__name__)
@@ -711,6 +711,20 @@ class TDeserializer(_GraphSONTypeIO):
def objectify(cls, d, reader):
return T[d]
+
+class DirectionIO(_GraphSONTypeIO):
+ graphson_type = "g:Direction"
+ graphson_base_type = "Direction"
+ python_type = Direction
+
+ @classmethod
+ def dictify(cls, d, writer):
+ return GraphSONUtil.typedValue(cls.graphson_base_type, d.name, "g")
+
+ @classmethod
+ def objectify(cls, d, reader):
+ return Direction[d]
+
class TraversalMetricsDeserializer(_GraphSONTypeIO):
graphson_type = "g:TraversalMetrics"
diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py
index ed6c15d..8db6b7b 100644
--- a/gremlin-python/src/main/jython/radish/feature_steps.py
+++ b/gremlin-python/src/main/jython/radish/feature_steps.py
@@ -80,7 +80,7 @@ def add_parameter(step, param_name, param):
if not hasattr(step.context, "traversal_params"):
step.context.traversal_params = {}
- step.context.traversal_params[param_name] = _convert(param, step.context)
+ step.context.traversal_params[param_name] = _convert(param.replace('\\"', '"'), step.context)
@given("the traversal of")
@@ -172,14 +172,16 @@ def _convert(val, ctx):
elif isinstance(val, str) and re.match("^e\[.*\]$", val): # parse edge
return __find_cached_element(ctx, graph_name, val[2:-1], "e")
elif isinstance(val, str) and re.match("^m\[.*\]$", val): # parse json as a map
- return _convert(json.loads(val[2:-1].replace('\\"', '"')), ctx)
+ return _convert(json.loads(val[2:-1]), ctx)
elif isinstance(val, str) and re.match("^p\[.*\]$", val): # parse path
path_objects = list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
return Path([set([])], path_objects)
elif isinstance(val, str) and re.match("^c\[.*\]$", val): # parse lambda/closure
return lambda: (val[2:-1], "gremlin-groovy")
- elif isinstance(val, str) and re.match("^t\[.*\]$", val): # parse instance of T enum
+ elif isinstance(val, str) and re.match("^t\[.*\]$", val): # parse instance of T enum
return T[val[2:-1]]
+ elif isinstance(val, str) and re.match("^D\[.*\]$", val): # parse instance of Direction enum
+ return Direction[val[2:-1]]
else:
return val
diff --git a/gremlin-test/features/map/ElementMap.feature b/gremlin-test/features/map/ElementMap.feature
new file mode 100644
index 0000000..95de688
--- /dev/null
+++ b/gremlin-test/features/map/ElementMap.feature
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+Feature: Step - elementMap()
+
+ Scenario: g_V_elementMap
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().elementMap()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"t[id]": "v[marko].id", "t[label]": "person", "name": "marko", "age": 29}] |
+ | m[{"t[id]": "v[josh].id", "t[label]": "person", "name": "josh", "age": 32}] |
+ | m[{"t[id]": "v[peter].id", "t[label]": "person", "name": "peter", "age": 35}] |
+ | m[{"t[id]": "v[vadas].id", "t[label]": "person", "name": "vadas", "age": 27}] |
+ | m[{"t[id]": "v[lop].id", "t[label]": "software", "name": "lop", "lang": "java"}] |
+ | m[{"t[id]": "v[ripple].id", "t[label]": "software", "name": "ripple", "lang": "java"}] |
+
+ Scenario: g_V_elementMapXname_ageX
+ Given the modern graph
+ And the traversal of
+ """
+ g.V().elementMap("name", "age")
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"t[id]": "v[marko].id", "t[label]": "person", "name": "marko", "age": 29}] |
+ | m[{"t[id]": "v[josh].id", "t[label]": "person", "name": "josh", "age": 32}] |
+ | m[{"t[id]": "v[peter].id", "t[label]": "person", "name": "peter", "age": 35}] |
+ | m[{"t[id]": "v[vadas].id", "t[label]": "person", "name": "vadas", "age": 27}] |
+ | m[{"t[id]": "v[lop].id", "t[label]": "software", "name": "lop"}] |
+ | m[{"t[id]": "v[ripple].id", "t[label]": "software", "name": "ripple"}] |
+
+ Scenario: g_EX11X_elementMap
+ Given the modern graph
+ And using the parameter e11Id defined as "e[josh-created->lop].id"
+ And the traversal of
+ """
+ g.E(e11Id).elementMap()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | m[{"t[id]": "e[josh-created->lop].id", "t[label]": "created", "weight": "d[0.4].d", "D[OUT]": "m[{\\"t[id]\\": \\"v[josh].id\\", \\"t[label]\\": \\"person\\"}]", "D[IN]": "m[{\\"t[id]\\": \\"v[lop].id\\", \\"t[label]\\": \\"software\\"}]"}] |
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
index 650dd38..f069a12 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/AbstractGremlinTest.java
@@ -159,8 +159,8 @@ public abstract class AbstractGremlinTest {
logger.warn("The {} is not of type ManagedGraphProvider and therefore graph instances may leak between test cases.", graphProvider.getClass());
if (shouldTestIteratorLeak) {
- long wait = 300;
- long[] tries = new long[] { 1, 3, 5, 7, 9, 18, 27, 36, 72, 144, 256, 512 };
+ final long wait = 300;
+ final long[] tries = new long[] { 1, 3, 5, 7, 9, 18, 27, 36, 72, 144, 256, 512 };
long openItrCount = StoreIteratorCounter.INSTANCE.getOpenIteratorCount();
for (int ix = 0; ix < tries.length && openItrCount > 0; ix++) {
Thread.sleep(wait * tries[ix]);
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 0951b86..3ca5b76 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -54,6 +54,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConnectedComponentTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConstantTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementMapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest;
@@ -150,6 +151,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
ConnectedComponentTest.Traversals.class,
ConstantTest.Traversals.class,
CountTest.Traversals.class,
+ ElementMapTest.Traversals.class,
FlatMapTest.Traversals.class,
FoldTest.Traversals.class,
GraphTest.Traversals.class,
@@ -249,6 +251,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
ConstantTest.class,
CountTest.class,
FlatMapTest.class,
+ ElementMapTest.class,
FoldTest.class,
MatchTest.class,
MathTest.class,
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 6bd6d5b..f127ca0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -48,6 +48,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.CoalesceTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.ConstantTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ElementMapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FlatMapTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldTest;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphTest;
@@ -140,6 +141,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
CoalesceTest.Traversals.class,
ConstantTest.Traversals.class,
CountTest.Traversals.class,
+ ElementMapTest.Traversals.class,
FlatMapTest.Traversals.class,
FoldTest.Traversals.class,
GraphTest.Traversals.class,
@@ -232,6 +234,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
CoalesceTest.class,
ConstantTest.class,
CountTest.class,
+ ElementMapTest.class,
FlatMapTest.class,
FoldTest.class,
LoopsTest.class,
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapTest.java
new file mode 100644
index 0000000..d64cbd9
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementMapTest.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.CREW;
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.apache.tinkerpop.gremlin.structure.T.id;
+import static org.apache.tinkerpop.gremlin.structure.T.label;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(GremlinProcessRunner.class)
+public abstract class ElementMapTest extends AbstractGremlinProcessTest {
+
+ public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_elementMap();
+
+ public abstract Traversal<Vertex, Map<Object, Object>> get_g_V_elementMapXname_ageX();
+
+ public abstract Traversal<Edge, Map<Object, Object>> get_g_EX11X_elementMap(final Object e11Id);
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_elementMap() {
+ final Traversal<Vertex, Map<Object, Object>> traversal = get_g_V_elementMap();
+ printTraversalForm(traversal);
+ int counter = 0;
+ while (traversal.hasNext()) {
+ counter++;
+ final Map<Object, Object> values = traversal.next();
+ final String name = (String) values.get("name");
+ assertEquals(4, values.size());
+ if (name.equals("marko")) {
+ assertEquals(29, values.get("age"));
+ assertEquals("person", values.get(label));
+ } else if (name.equals("josh")) {
+ assertEquals(32, values.get("age"));
+ assertEquals("person", values.get(label));
+ } else if (name.equals("peter")) {
+ assertEquals(35, values.get("age"));
+ assertEquals("person", values.get(label));
+ } else if (name.equals("vadas")) {
+ assertEquals(27, values.get("age"));
+ assertEquals("person", values.get(label));
+ } else if (name.equals("lop")) {
+ assertEquals("java", values.get("lang"));
+ assertEquals("software", values.get(label));
+ } else if (name.equals("ripple")) {
+ assertEquals("java", values.get("lang"));
+ assertEquals("software", values.get(label));
+ } else {
+ throw new IllegalStateException("It is not possible to reach here: " + values);
+ }
+
+ assertThat(values.containsKey(T.id), is(true));
+ }
+ assertEquals(6, counter);
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_elementMapXname_ageX() {
+ final Traversal<Vertex, Map<Object, Object>> traversal = get_g_V_elementMapXname_ageX();
+ printTraversalForm(traversal);
+ int counter = 0;
+ while (traversal.hasNext()) {
+ counter++;
+ final Map<Object, Object> values = traversal.next();
+ final String name = (String) values.get("name");
+ if (name.equals("marko")) {
+ assertEquals(29, values.get("age"));
+ assertEquals("person", values.get(label));
+ assertEquals(4, values.size());
+ } else if (name.equals("josh")) {
+ assertEquals(32, values.get("age"));
+ assertEquals("person", values.get(label));
+ assertEquals(4, values.size());
+ } else if (name.equals("peter")) {
+ assertEquals(35, values.get("age"));
+ assertEquals("person", values.get(label));
+ assertEquals(4, values.size());
+ } else if (name.equals("vadas")) {
+ assertEquals(27, values.get("age"));
+ assertEquals("person", values.get(label));
+ assertEquals(4, values.size());
+ } else if (name.equals("lop")) {
+ assertNull(values.get("lang"));
+ assertEquals("software", values.get(label));
+ assertEquals(3, values.size());
+ } else if (name.equals("ripple")) {
+ assertNull(values.get("lang"));
+ assertEquals("software", values.get(label));
+ assertEquals(3, values.size());
+ } else {
+ throw new IllegalStateException("It is not possible to reach here: " + values);
+ }
+
+ assertThat(values.containsKey(T.id), is(true));
+ }
+ assertEquals(6, counter);
+ }
+
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_EX11X_elementMap() {
+ final Object edgeId = convertToEdgeId("josh", "created", "lop");
+ final Traversal<Edge, Map<Object,Object>> traversal = get_g_EX11X_elementMap(edgeId);
+ printTraversalForm(traversal);
+
+ final Map<Object,Object> m = traversal.next();
+ assertEquals(5, m.size());
+ assertEquals(0.4d, m.get("weight"));
+ assertEquals("created", m.get(label));
+ assertEquals(edgeId, m.get(T.id));
+
+ final Vertex vJosh = convertToVertex("josh");
+ assertEquals(vJosh.id(), ((Map<Object,Object>) m.get(Direction.OUT)).get(T.id));
+ assertEquals(vJosh.label(), ((Map<Object,Object>) m.get(Direction.OUT)).get(T.label));
+
+ final Vertex vLop = convertToVertex("lop");
+ assertEquals(vLop.id(), ((Map<Object,Object>) m.get(Direction.IN)).get(T.id));
+ assertEquals(vLop.label(), ((Map<Object,Object>) m.get(Direction.IN)).get(T.label));
+
+ assertThat(traversal.hasNext(), is(false));
+ }
+
+ public static class Traversals extends ElementMapTest {
+ @Override
+ public Traversal<Vertex, Map<Object, Object>> get_g_V_elementMap() {
+ return g.V().elementMap();
+ }
+
+ @Override
+ public Traversal<Vertex, Map<Object, Object>> get_g_V_elementMapXname_ageX() {
+ return g.V().elementMap("name", "age");
+ }
+
+ @Override
+ public Traversal<Edge, Map<Object, Object>> get_g_EX11X_elementMap(final Object e11Id) {
+ return g.E(e11Id).elementMap();
+ }
+ }
+}