You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2019/05/02 16:11:03 UTC

[tinkerpop] branch TINKERPOP-2207 created (now 6efb784)

This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a change to branch TINKERPOP-2207
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


      at 6efb784  TINKERPOP-2207 Implemented SimpleValueMapStrategy

This branch includes the following new commits:

     new 6efb784  TINKERPOP-2207 Implemented SimpleValueMapStrategy

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tinkerpop] 01/01: TINKERPOP-2207 Implemented SimpleValueMapStrategy

Posted by dk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a commit to branch TINKERPOP-2207
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 6efb784abbb5744c044a52582c1940478b8ffd01
Author: Daniel Kuppitz <da...@hotmail.com>
AuthorDate: Thu May 2 09:10:43 2019 -0700

    TINKERPOP-2207 Implemented SimpleValueMapStrategy
---
 CHANGELOG.asciidoc                                 |   1 +
 docs/src/upgrade/release-3.4.x.asciidoc            |  27 +++++
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |   2 +
 .../finalization/SimpleValueMapStrategy.java       |  60 ++++++++++
 .../structure/io/graphson/GraphSONModule.java      |   5 +
 .../gremlin/structure/io/gryo/GryoVersion.java     |   7 +-
 .../finalization/SimpleValueMapStrategyTest.java   |  69 +++++++++++
 .../gremlin/process/ProcessComputerSuite.java      |   6 +-
 .../gremlin/process/ProcessStandardSuite.java      |   6 +-
 .../SimpleValueMapStrategyProcessTest.java         | 133 +++++++++++++++++++++
 10 files changed, 312 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 2bf08bd..9c9263f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-3-7, 3.3.7>>.
 
+* Implemented `SimpleValueMapStrategy`.
 * Allow a `Traversal` to know what `TraversalSource` it spawned from.
 * Fixed problem with connection pool sizing and retry.
 
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index bb9cf43..914bc34 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -27,6 +27,33 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 Please see the link:https://github.com/apache/tinkerpop/blob/3.4.2/CHANGELOG.asciidoc#release-3-4-2[changelog] for a complete list of all the modifications that are part of this release.
 
+=== Upgrading for Providers
+
+==== Automatic unfolding of valueMap() values
+
+This release contains a new strategy called `SimpleValueMapStrategy`. The strategy is not added by default, but meant to be added mainly by providers who do not support multi-valued
+properties. The strategy will automatically a `.by(unfold())` modulator to all `valueMap()` steps that don't have a `by()` modulator defined by the user. As a result, `valueMap()` will emit
+maps with single-valued values.
+
+```text
+gremlin> g.V().valueMap()
+==>[name:[marko],age:[29]]
+==>[name:[vadas],age:[27]]
+==>[name:[lop],lang:[java]]
+==>[name:[josh],age:[32]]
+==>[name:[ripple],lang:[java]]
+==>[name:[peter],age:[35]]
+gremlin> g.withStrategies(SimpleValueMapStrategy.instance()).V().valueMap()
+==>[name:marko,age:29]
+==>[name:vadas,age:27]
+==>[name:lop,lang:java]
+==>[name:josh,age:32]
+==>[name:ripple,lang:java]
+==>[name:peter,age:35]
+```
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2207[TINKERPOP-2207],
+
 == TinkerPop 3.4.1
 
 *Release Date: March 18, 2019*
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index cc7881c..23de08a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -84,6 +84,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.Refe
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.SimpleValueMapStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
@@ -257,6 +258,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(ReferenceElementStrategy.class);
         CLASS_IMPORTS.add(StandardVerificationStrategy.class);
         CLASS_IMPORTS.add(EdgeLabelVerificationStrategy.class);
+        CLASS_IMPORTS.add(SimpleValueMapStrategy.class);
         // graph traversal
         CLASS_IMPORTS.add(AnonymousTraversalSource.class);
         CLASS_IMPORTS.add(__.class);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategy.java
new file mode 100644
index 0000000..988125e
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategy.java
@@ -0,0 +1,60 @@
+/*
+ * 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.strategy.finalization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.structure.PropertyType;
+
+/**
+ * SimpleValueMapStrategy automatically adds a {@code .by(unfold())} to every {@code valueMap()} step that has no
+ * by-modulator specified. This is useful especially for providers who do not support multi-valued properties.
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class SimpleValueMapStrategy
+        extends AbstractTraversalStrategy<TraversalStrategy.FinalizationStrategy>
+        implements TraversalStrategy.FinalizationStrategy {
+
+    private final static SimpleValueMapStrategy INSTANCE = new SimpleValueMapStrategy();
+
+    private SimpleValueMapStrategy() {
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        for (final Step<?, ?> step : traversal.getSteps()) {
+            if (step instanceof PropertyMapStep) {
+                final PropertyMapStep pms = (PropertyMapStep) step;
+                if (pms.getReturnType() == PropertyType.VALUE && pms.getLocalChildren().isEmpty()) {
+                    //noinspection unchecked
+                    pms.modulateBy(__.unfold().asAdmin());
+                }
+            }
+        }
+    }
+
+    public static SimpleValueMapStrategy instance() {
+        return INSTANCE;
+    }
+}
\ No newline at end of file
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 6ad5db7..3b6b8d0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -43,6 +43,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Option
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.SimpleValueMapStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
@@ -204,6 +205,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                             StandardVerificationStrategy.class,
                             EarlyLimitStrategy.class,
                             EdgeLabelVerificationStrategy.class,
+                            SimpleValueMapStrategy.class,
                             //
                             GraphFilterStrategy.class,
                             VertexProgramStrategy.class
@@ -328,6 +330,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     StandardVerificationStrategy.class,
                     EarlyLimitStrategy.class,
                     EdgeLabelVerificationStrategy.class,
+                    SimpleValueMapStrategy.class,
                     //
                     GraphFilterStrategy.class,
                     VertexProgramStrategy.class
@@ -433,6 +436,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                             StandardVerificationStrategy.class,
                             EarlyLimitStrategy.class,
                             EdgeLabelVerificationStrategy.class,
+                            SimpleValueMapStrategy.class,
                             //
                             GraphFilterStrategy.class,
                             VertexProgramStrategy.class
@@ -547,6 +551,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     StandardVerificationStrategy.class,
                     EarlyLimitStrategy.class,
                     EdgeLabelVerificationStrategy.class,
+                    SimpleValueMapStrategy.class,
                     //
                     GraphFilterStrategy.class,
                     VertexProgramStrategy.class
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 73bac27..c13f966 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -52,6 +52,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Option
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.SimpleValueMapStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
@@ -354,7 +355,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(EarlyLimitStrategy.class, 188));
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 164));
-            add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));   // ***LAST ID***
+            add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));
+            add(GryoTypeReg.of(SimpleValueMapStrategy.class, 190));   // ***LAST ID***
 
             add(GryoTypeReg.of(TraverserSet.class, 58));
             add(GryoTypeReg.of(Tree.class, 61));
@@ -590,7 +592,8 @@ public enum GryoVersion {
             add(GryoTypeReg.of(EarlyLimitStrategy.class, 188));
             add(GryoTypeReg.of(MatchStep.CountMatchAlgorithm.class, 160));
             add(GryoTypeReg.of(MatchStep.GreedyMatchAlgorithm.class, 167));
-            add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));   // ***LAST ID***
+            add(GryoTypeReg.of(EdgeLabelVerificationStrategy.class, 189));
+            add(GryoTypeReg.of(SimpleValueMapStrategy.class, 190));   // ***LAST ID***
             // skip 171, 172 to sync with tp33
             add(GryoTypeReg.of(IndexedTraverserSet.VertexIndexedTraverserSet.class, 173));
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyTest.java
new file mode 100644
index 0000000..1caf6ae
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.strategy.finalization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+@RunWith(Parameterized.class)
+public class SimpleValueMapStrategyTest {
+
+    @Parameterized.Parameter()
+    public Traversal original;
+
+    @Parameterized.Parameter(value = 1)
+    public Traversal changed;
+
+    private void applyStrategy(final Traversal traversal) {
+        final TraversalStrategies strategies = new DefaultTraversalStrategies();
+        strategies.addStrategies(SimpleValueMapStrategy.instance());
+        traversal.asAdmin().setStrategies(strategies);
+        traversal.asAdmin().applyStrategies();
+    }
+
+    @Test
+    public void doTest() {
+        applyStrategy(original);
+        assertEquals(changed, original);
+    }
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> generateTestParameters() {
+        return Arrays.asList(new Traversal[][]{
+                {__.valueMap(), __.valueMap().by(__.unfold())},
+                {__.valueMap("name","age"), __.valueMap("name","age").by(__.unfold())},
+                {__.valueMap().by(__.limit(Scope.local, 1)), __.valueMap().by(__.limit(Scope.local, 1))},
+                {__.valueMap("name","age").by(__.limit(Scope.local, 1)), __.valueMap("name","age").by(__.limit(Scope.local, 1))}
+        });
+    }
+}
\ No newline at end of file
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..e82e8e2 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
@@ -93,6 +93,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTe
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.SimpleValueMapStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategyProcessTest;
@@ -214,7 +215,10 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
 
             // optimizations
             IncidentToAdjacentStrategyProcessTest.class,
-            EarlyLimitStrategyProcessTest.class
+            EarlyLimitStrategyProcessTest.class,
+
+            // finalization
+            SimpleValueMapStrategyProcessTest.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..31d6be7 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
@@ -87,6 +87,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventS
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategyProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.SimpleValueMapStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.EarlyLimitStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategyProcessTest;
@@ -195,7 +196,10 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
 
             // optimizations
             IncidentToAdjacentStrategyProcessTest.class,
-            EarlyLimitStrategyProcessTest.class
+            EarlyLimitStrategyProcessTest.class,
+
+            // finalization
+            SimpleValueMapStrategyProcessTest.class
     };
 
     /**
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyProcessTest.java
new file mode 100644
index 0000000..b5c0040
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/SimpleValueMapStrategyProcessTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.strategy.finalization;
+
+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.dsl.graph.GraphTraversal;
+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.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+@RunWith(GremlinProcessRunner.class)
+public class SimpleValueMapStrategyProcessTest extends AbstractGremlinProcessTest {
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void shouldApplyUnfold() throws Exception {
+
+        //
+        // without tokens
+        //
+        GraphTraversal<Vertex, Map<Object, Object>> t = g.withStrategies(SimpleValueMapStrategy.instance())
+                .V().has("person", "name", "marko").valueMap();
+
+        assertTrue(t.hasNext());
+
+        Map<Object, Object> result = t.next();
+
+        assertFalse(t.hasNext());
+        assertEquals(2, result.size());
+        assertTrue(result.containsKey("name"));
+        assertTrue(result.containsKey("age"));
+        assertEquals("marko", result.get("name"));
+        assertEquals(29, result.get("age"));
+
+        //
+        // with tokens
+        //
+        t = g.withStrategies(SimpleValueMapStrategy.instance())
+                .V().has("person", "name", "marko").valueMap().with(WithOptions.tokens);
+
+        assertTrue(t.hasNext());
+
+        result = t.next();
+
+        assertFalse(t.hasNext());
+        assertEquals(4, result.size());
+        assertTrue(result.containsKey(T.id));
+        assertTrue(result.containsKey(T.label));
+        assertTrue(result.containsKey("name"));
+        assertTrue(result.containsKey("age"));
+        assertEquals("person", result.get(T.label));
+        assertEquals("marko", result.get("name"));
+        assertEquals(29, result.get("age"));
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void shouldNotApplyUnfold() throws Exception {
+
+        final List<String> list = Collections.singletonList("X");
+
+        //
+        // without tokens
+        //
+        GraphTraversal<Vertex, Map<Object, Object>> t = g.withStrategies(SimpleValueMapStrategy.instance())
+                .V().has("person", "name", "marko").valueMap().by(__.constant(list));
+
+        assertTrue(t.hasNext());
+
+        Map<Object, Object> result = t.next();
+
+        assertFalse(t.hasNext());
+        assertEquals(2, result.size());
+        assertTrue(result.containsKey("name"));
+        assertTrue(result.containsKey("age"));
+        assertEquals(list, result.get("name"));
+        assertEquals(list, result.get("age"));
+
+        //
+        // with tokens
+        //
+        t = g.withStrategies(SimpleValueMapStrategy.instance())
+                .V().has("person", "name", "marko").valueMap().with(WithOptions.tokens).by(__.constant(list));
+
+        assertTrue(t.hasNext());
+
+        result = t.next();
+
+        assertFalse(t.hasNext());
+        assertEquals(4, result.size());
+        assertTrue(result.containsKey(T.id));
+        assertTrue(result.containsKey(T.label));
+        assertTrue(result.containsKey("name"));
+        assertTrue(result.containsKey("age"));
+        assertEquals(list, result.get(T.id));
+        assertEquals(list, result.get(T.label));
+        assertEquals(list, result.get("name"));
+        assertEquals(list, result.get("age"));
+    }
+}
\ No newline at end of file