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 2018/10/10 21:32:38 UTC

[tinkerpop] 01/01: TINKERPOP-2061 Added with() option for traversal configuration

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

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

commit 49cb1dccd63081edc6a1a8c0eb618fc6d465f206
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Wed Oct 10 17:31:36 2018 -0400

    TINKERPOP-2061 Added with() option for traversal configuration
    
    Basically just shorthands the direct use of OptionStrategy which is much more verbose and less nice to look at.
---
 CHANGELOG.asciidoc                                 |  3 +-
 docs/src/upgrade/release-3.4.x.asciidoc            | 10 +++++-
 .../gremlin/process/traversal/TraversalSource.java | 36 ++++++++++++++++++++++
 .../traversal/dsl/graph/GraphTraversal.java        |  1 +
 .../traversal/dsl/graph/GraphTraversalSource.java  | 17 ++++++++++
 .../Process/Traversal/GraphTraversalSource.cs      | 16 ++++++++++
 .../DriverRemoteConnection/GraphTraversalTests.cs  |  6 ++--
 .../lib/process/graph-traversal.js                 | 10 ++++++
 .../gremlin_python/process/graph_traversal.py      |  5 +++
 .../src/main/jython/tests/driver/test_client.py    |  5 +++
 .../strategy/decoration/OptionsStrategyTest.java   | 13 +++++++-
 11 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4e490b4..48c7037 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,7 +25,6 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-3-3, 3.3.3>>.
 
-* Added `OptionsStrategy` to allow traversals to take arbitrary traversal-wide configurations.
 * Added text predicates.
 * Removed groovy-sql
 * Rewrote `ConnectiveStrategy` to support an arbitrary number of infix notations in a single traversal.
@@ -54,6 +53,8 @@ This release also includes changes from <<release-3-3-3, 3.3.3>>.
 * Replaced `Parameterizing.addPropertyMutations()` with `Configuring.configure()`.
 * Changed interface hierarchy for `Parameterizing` and `Mutating` interfaces as they are tightly related.
 * Introduced the `with(k,v)` and `with(k)` step modulators which can supply configuration options to `Configuring` steps.
+* Added `OptionsStrategy` to allow traversals to take arbitrary traversal-wide configurations.
+* Introduced the `with(k,v)` and `with(k)` traveral source configuration options which can supply configuration options to the traversal.
 * Added `connectedComponent()` step and related `VertexProgram`.
 * Added `supportsUpsert()` option to `VertexFeatures` and `EdgeFeatures`.
 * `min()` and `max()` now support all types implementing `Comparable`.
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 241571e..055fd9e 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -510,7 +510,15 @@ accessible to their custom steps. A user would write something like:
 
 [source,java]
 ----
-g.withStrategies(OptionsStrategy.build().with("specialLimit", 10000).create());
+g.withStrategies(OptionsStrategy.build().with("specialLimit", 10000).create()).V();
+----
+
+The `OptionsStrategy` is really only the carrier for the configurations and while users can choose to utilize that
+more verbose method for constructing it shown above, it is more elegantly constructed as follows using `with()`-step:
+
+[source,java]
+----
+g.with("specialLimit", 10000)).V();
 ----
 
 The graph provider could then access that value of "specialLimit" in their custom step (or elsewhere) as follows:
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
index 2421a78..d332612 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSource.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SackStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SideEffectStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -48,6 +49,7 @@ import java.util.function.UnaryOperator;
  * {@code TraversalSource(Graph)} and {@code TraversalSource(Graph,TraversalStrategies)}
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public interface TraversalSource extends Cloneable, AutoCloseable {
 
@@ -83,6 +85,7 @@ public interface TraversalSource extends Cloneable, AutoCloseable {
             // static fields only
         }
 
+        public static final String with = "with";
         public static final String withSack = "withSack";
         public static final String withStrategies = "withStrategies";
         public static final String withoutStrategies = "withoutStrategies";
@@ -94,6 +97,39 @@ public interface TraversalSource extends Cloneable, AutoCloseable {
     /////////////////////////////
 
     /**
+     * Provides a configuration to a traversal in the form of a key which is the same as {@code with(key, true)}. The
+     * key of the configuration must be graph provider specific and therefore a configuration could be supplied that
+     * is not known to be valid until execution.
+     *
+     * @param key the key of the configuration to apply to a traversal
+     * @return a new traversal source with the included configuration
+     * @since 3.4.0
+     */
+    public default TraversalSource with(final String key) {
+        return with(key, true);
+    }
+
+    /**
+     * Provides a configuration to a traversal in the form of a key value pair. The  key of the configuration must be
+     * graph provider specific and therefore a configuration could be supplied that is not known to be valid until
+     * execution. This is a handy shortcut for building an {@link OptionsStrategy} manually and then add with
+     * {@link #withStrategies(TraversalStrategy[])}.
+     *
+     * @param key the key of the configuration to apply to a traversal
+     * @param value the value of the configuration to apply to a traversal
+     * @return a new traversal source with the included configuration
+     * @since 3.4.0
+     */
+    public default TraversalSource with(final String key, final Object value) {
+        final Optional<OptionsStrategy> opt = getStrategies().getStrategy(OptionsStrategy.class);
+        final OptionsStrategy strategy = opt.orElse(OptionsStrategy.EMPTY);
+        final OptionsStrategy.Builder builder = OptionsStrategy.build();
+        strategy.getOptions().forEach(builder::with);
+        builder.with(key, value);
+        return withStrategies(builder.create());
+    }
+
+    /**
      * Add an arbitrary collection of {@link TraversalStrategy} instances to the traversal source.
      *
      * @param traversalStrategies a collection of traversal strategies to add
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 d5b0290..e984312 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
@@ -170,6 +170,7 @@ import java.util.function.Predicate;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public interface GraphTraversal<S, E> extends Traversal<S, E> {
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
index 95104f6..fa33573 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java
@@ -52,6 +52,7 @@ import java.util.function.UnaryOperator;
  * Any DSL can be constructed based on the methods of both {@code GraphTraversalSource} and {@link GraphTraversal}.
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class GraphTraversalSource implements TraversalSource {
     protected transient RemoteConnection connection;
@@ -121,6 +122,22 @@ public class GraphTraversalSource implements TraversalSource {
      * {@inheritDoc}
      */
     @Override
+    public GraphTraversalSource with(final String key) {
+        return (GraphTraversalSource) TraversalSource.super.with(key);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversalSource with(final String key, final Object value) {
+        return (GraphTraversalSource) TraversalSource.super.with(key, value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public GraphTraversalSource withStrategies(final TraversalStrategy... traversalStrategies) {
         return (GraphTraversalSource) TraversalSource.super.withStrategies(traversalStrategies);
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index 15d42d7..b52b898 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -73,6 +73,22 @@ namespace Gremlin.Net.Process.Traversal
         }
 
 
+        public GraphTraversalSource With(string key)
+        {
+            var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
+                                                  new Bytecode(Bytecode));
+            source.Bytecode.AddSource("with", key);
+            return source;
+        }
+
+        public GraphTraversalSource With(string key, object value)
+        {
+            var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
+                                                  new Bytecode(Bytecode));
+            source.Bytecode.AddSource("with", key, value);
+            return source;
+        }
+
         public GraphTraversalSource WithBulk(bool useBulk)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
index e46fa22..cc73bde 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/GraphTraversalTests.cs
@@ -199,9 +199,11 @@ namespace Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
             var g = graph.Traversal().WithRemote(connection);
 
             var b = new Bindings();
-            var count = g.WithStrategies(new OptionsStrategy(options)).V().Count().Next();
+            var countWithStrategy = g.WithStrategies(new OptionsStrategy(options)).V().Count().Next();
+            Assert.Equal(6, countWithStrategy);
 
-            Assert.Equal(6, count);
+            var countWith = g.With("x", "test").With("y", true).V().Count().Next();
+            Assert.Equal(6, countWith);
         }
 
         [Fact]
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 a38cfa2..bcb37fa 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
@@ -63,6 +63,16 @@ class GraphTraversalSource {
   }
   
   /**
+   * Graph Traversal Source with method.
+   * @param {...Object} args
+   * @returns {GraphTraversalSource}
+   */
+  with_(...args) {
+    const b = new Bytecode(this.bytecode).addSource('with', args);
+    return new GraphTraversalSource(this.graph, new TraversalStrategies(this.traversalStrategies), b);
+  }
+  
+  /**
    * Graph Traversal Source withBulk method.
    * @param {...Object} args
    * @returns {GraphTraversalSource}
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 a54853b..7d7a4c9 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
@@ -67,6 +67,11 @@ class GraphTraversalSource(object):
         source.bytecode.add_source("withStrategies", *args)
         return source
 
+    def with_(self, *args):
+        source = self.get_graph_traversal_source()
+        source.bytecode.add_source("with", *args)
+        return source
+
     def withoutStrategies(self, *args):
         source = self.get_graph_traversal_source()
         source.bytecode.add_source("withoutStrategies", *args)
diff --git a/gremlin-python/src/main/jython/tests/driver/test_client.py b/gremlin-python/src/main/jython/tests/driver/test_client.py
index edc5bea..dd1de47 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_client.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_client.py
@@ -79,6 +79,11 @@ def test_client_bytecode_options(client):
     message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
     result_set = client.submit(message)
     assert len(result_set.all().result()) == 6
+    ##
+    t = g.with_("x", "test").with_("y", True).V()
+    message = RequestMessage('traversal', 'bytecode', {'gremlin': t.bytecode, 'aliases': {'g': 'gmodern'}})
+    result_set = client.submit(message)
+    assert len(result_set.all().result()) == 6
 
 
 def test_iterate_result_set(client):
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
index 09ce128..ce39953 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/decoration/OptionsStrategyTest.java
@@ -42,11 +42,22 @@ public class OptionsStrategyTest {
     public void shouldAddOptionsToTraversal() {
         final Graph graph = TinkerGraph.open();
         final GraphTraversalSource optionedG = graph.traversal().withStrategies(OptionsStrategy.build().with("a", "test").with("b").create());
+        assertOptions(optionedG);
+    }
+
+    @Test
+    public void shouldAddOptionsToTraversalUsingWith() {
+        final Graph graph = TinkerGraph.open();
+        final GraphTraversalSource optionedG = graph.traversal().with("a", "test").with("b");
+        assertOptions(optionedG);
+    }
+
+    private static void assertOptions(final GraphTraversalSource optionedG) {
         GraphTraversal t = optionedG.inject(1);
         t = t.asAdmin().addStep(new MapStep<Object, Object>(t.asAdmin()) {
             @Override
             protected Object map(final Traverser.Admin<Object> traverser) {
-                final OptionsStrategy strategy = this.getTraversal().asAdmin().getStrategies().getStrategy(OptionsStrategy.class).get();
+                final OptionsStrategy strategy = traversal.asAdmin().getStrategies().getStrategy(OptionsStrategy.class).get();
                 return Arrays.asList(strategy.getOptions().get("a"), strategy.getOptions().get("b"));
             }
         });