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

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

commit 637be9253bcf0a5eaf1dda47663eb3e770b4042f
Author: Stephen Mallette <stepm...@amazon.com>
AuthorDate: Fri Oct 2 16:52:39 2020 -0400

    TINKERPOP-2420 Added with() support for request options in C#
---
 gremlin-dotnet/glv/GraphTraversalSource.template   | 24 +++++++++++++
 gremlin-dotnet/glv/generate.groovy                 |  1 +
 .../Driver/Remote/DriverRemoteConnection.cs        | 30 ++++++++++++++--
 gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs    | 28 ++++++++++-----
 .../Process/Traversal/GraphTraversalSource.cs      | 26 +++++++++-----
 .../DriverRemoteConnection/GraphTraversalTests.cs  | 14 ++++----
 .../apache/tinkerpop/gremlin/driver/Tokens.java    | 40 ++++++++++++++++++++++
 7 files changed, 137 insertions(+), 26 deletions(-)

diff --git a/gremlin-dotnet/glv/GraphTraversalSource.template 
b/gremlin-dotnet/glv/GraphTraversalSource.template
index f3093e5..4ccf77f 100644
--- a/gremlin-dotnet/glv/GraphTraversalSource.template
+++ b/gremlin-dotnet/glv/GraphTraversalSource.template
@@ -72,6 +72,30 @@ namespace Gremlin.Net.Process.Traversal
             Bytecode = bytecode;
         }
 
+        public GraphTraversalSource With(string key)
+        {
+            return With(key, true);
+        }
+
+        public GraphTraversalSource With(string key, object value)
+        {
+            var optionsStrategyInst = Bytecode.SourceInstructions.Find(
+                inst => inst.OperatorName == "withStrategies" && 
inst.Arguments[0] is OptionsStrategy);
+            OptionsStrategy optionsStrategy;
+
+            if (optionsStrategyInst == null)
+            {
+                optionsStrategy = new OptionsStrategy();
+                optionsStrategy.Configuration[key] = value;
+                return WithStrategies(optionsStrategy);
+            }
+
+            optionsStrategy = optionsStrategyInst.Arguments[0];
+            optionsStrategy.Configuration[key] = value;
+            return new GraphTraversalSource(new 
List<ITraversalStrategy>(TraversalStrategies),
+                new Bytecode(Bytecode));
+        }
+
 <% sourceStepMethods.each{ method -> %>
         public GraphTraversalSource <%= 
toCSharpMethodName.call(method.methodName) %>(<%= method.parameters %>)
         {
diff --git a/gremlin-dotnet/glv/generate.groovy 
b/gremlin-dotnet/glv/generate.groovy
index 26daa58..a951907 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -256,6 +256,7 @@ def binding = ["pmethods": P.class.getMethods().
                         findAll { 
GraphTraversalSource.class.equals(it.returnType) }.
                         findAll {
                             !it.name.equals("clone") &&
+                                    
!it.name.equals(TraversalSource.Symbols.with) &&
                                     
!it.name.equals(TraversalSource.Symbols.withRemote) &&
                                     
!it.name.equals(TraversalSource.Symbols.withComputer)
                         }.
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs 
b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
index a52cb87..510a2f4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
@@ -27,6 +27,7 @@ using System.Threading.Tasks;
 using Gremlin.Net.Driver.Messages;
 using Gremlin.Net.Process.Remote;
 using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Process.Traversal.Strategy.Decoration;
 
 namespace Gremlin.Net.Driver.Remote
 {
@@ -37,6 +38,15 @@ namespace Gremlin.Net.Driver.Remote
     {
         private readonly IGremlinClient _client;
         private readonly string _traversalSource;
+        
+        /// <summary>
+        /// Filter on these keys provided to OptionsStrategy and apply them to 
the request. Note that
+        /// "scriptEvaluationTimeout" was deprecated in 3.3.9 but still 
supported in server implementations and will
+        /// be removed in later versions. 
+        /// </summary>
+        private readonly List<String> _allowedKeys = new List<string> 
+                    {Tokens.ArgsEvalTimeout, "scriptEvaluationTimeout", 
Tokens.ArgsBatchSize, 
+                     Tokens.RequestId, Tokens.ArgsUserAgent};
 
         /// <summary>
         ///     Initializes a new <see cref="IRemoteConnection" /> using "g" 
as the default remote TraversalSource name.
@@ -78,9 +88,23 @@ namespace Gremlin.Net.Driver.Remote
                     .Processor(Tokens.ProcessorTraversal)
                     .OverrideRequestId(requestid)
                     .AddArgument(Tokens.ArgsGremlin, bytecode)
-                    .AddArgument(Tokens.ArgsAliases, new Dictionary<string, 
string> {{"g", _traversalSource}})
-                    .Create();
-            return await 
_client.SubmitAsync<Traverser>(requestMsg).ConfigureAwait(false);
+                    .AddArgument(Tokens.ArgsAliases, new Dictionary<string, 
string> {{"g", _traversalSource}});
+
+            var optionsStrategyInst = bytecode.SourceInstructions.Find(
+                s => s.OperatorName == "withStrategies" && s.Arguments[0] is 
OptionsStrategy);
+            if (optionsStrategyInst != null)
+            {
+                OptionsStrategy optionsStrategy = 
optionsStrategyInst.Arguments[0];
+                foreach (KeyValuePair<string,dynamic> pair in 
optionsStrategy.Configuration)
+                {
+                    if (_allowedKeys.Contains(pair.Key))
+                    {
+                        requestMsg.AddArgument(pair.Key, pair.Value);
+                    }
+                }
+            }
+            
+            return await 
_client.SubmitAsync<Traverser>(requestMsg.Create()).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs 
b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
index a7f804a..36f281f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
@@ -32,6 +32,11 @@ namespace Gremlin.Net.Driver
     public class Tokens
     {
         /// <summary>
+        ///     The key for the unique identifier of the request. 
+        /// </summary>
+        public static string RequestId = "requestId";
+        
+        /// <summary>
         ///     Operation used by the client to authenticate itself.
         /// </summary>
         public static string OpsAuthentication = "authentication";
@@ -74,24 +79,25 @@ namespace Gremlin.Net.Driver
         public static string ProcessorSession = "session";
 
         /// <summary>
-        ///     Argument name that allows to defines the number of iterations 
each ResponseMessage should contain - overrides the
-        ///     resultIterationBatchSize server setting.
+        ///     Argument name that allows to definition of the number of 
iterations each ResponseMessage should
+        ///     contain - overrides the resultIterationBatchSize server 
setting.
         /// </summary>
         public static string ArgsBatchSize = "batchSize";
 
         /// <summary>
-        ///     Argument name that allows to provide a map of key/value pairs 
to apply as variables in the context of the Gremlin
-        ///     script.
+        ///     Argument name that allows definition of a map of key/value 
pairs to apply as variables in the
+        ///     context of the Gremlin request sent to the server.
         /// </summary>
         public static string ArgsBindings = "bindings";
 
         /// <summary>
-        ///     Argument name that allows to define aliases that represent 
globally bound Graph and TraversalSource objects.
+        ///     Argument name that allows definition of alias names for Graph 
and TraversalSource objects on the
+        ///     remote system.
         /// </summary>
         public static string ArgsAliases = "aliases";
 
         /// <summary>
-        ///     Argument name that corresponds to the Traversal to evaluate.
+        ///     Argument name that corresponds to the Gremlin to evaluate.
         /// </summary>
         public static string ArgsGremlin = "gremlin";
 
@@ -101,6 +107,12 @@ namespace Gremlin.Net.Driver
         public static string ArgsSession = "session";
 
         /// <summary>
+        ///     Argument name that allows a value that is a custom string that 
the user can pass to a server that
+        ///     might accept it for purpose of identifying the kind of client 
it came from.
+        /// </summary>
+        public static string ArgsUserAgent = "userAgent";
+
+        /// <summary>
         ///     Argument name that allows to specify the unique identifier for 
the request.
         /// </summary>
         [Obsolete("As of release 3.3.8, not replaced, prefer use of cap()-step 
to retrieve side-effects as part of traversal iteration", false)]
@@ -119,12 +131,12 @@ namespace Gremlin.Net.Driver
         public static string ArgsAggregateTo = "aggregateTo";
 
         /// <summary>
-        ///     Argument name that allows to change the flavor of Gremlin used 
(e.g. gremlin-groovy).
+        ///     Argument name that allows definition of the flavor of Gremlin 
used (e.g. gremlin-groovy) to process the request.
         /// </summary>
         public static string ArgsLanguage = "language";
 
         /// <summary>
-        ///     Argument name that allows to override the server setting that 
determines the maximum time to wait for a
+        ///     Argument name that allows the override of the server setting 
that determines the maximum time to wait for a
         ///     request to execute on the server.
         /// </summary>
         public static string ArgsEvalTimeout = "evaluationTimeout";
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs 
b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index b52b898..7a7f643 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -72,23 +72,31 @@ namespace Gremlin.Net.Process.Traversal
             Bytecode = bytecode;
         }
 
-
         public GraphTraversalSource With(string key)
         {
-            var source = new GraphTraversalSource(new 
List<ITraversalStrategy>(TraversalStrategies),
-                                                  new Bytecode(Bytecode));
-            source.Bytecode.AddSource("with", key);
-            return source;
+            return With(key, true);
         }
 
         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;
+            var optionsStrategyInst = Bytecode.SourceInstructions.Find(
+                inst => inst.OperatorName == "withStrategies" && 
inst.Arguments[0] is OptionsStrategy);
+            OptionsStrategy optionsStrategy;
+
+            if (optionsStrategyInst == null)
+            {
+                optionsStrategy = new OptionsStrategy();
+                optionsStrategy.Configuration[key] = value;
+                return WithStrategies(optionsStrategy);
+            }
+
+            optionsStrategy = optionsStrategyInst.Arguments[0];
+            optionsStrategy.Configuration[key] = value;
+            return new GraphTraversalSource(new 
List<ITraversalStrategy>(TraversalStrategies),
+                new Bytecode(Bytecode));
         }
 
+
         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 0f6bea6..0ae6277 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
@@ -24,6 +24,9 @@
 using System.Linq;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
 using Xunit;
@@ -201,8 +204,6 @@ namespace 
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
         [Fact]
         public void ShouldUseOptionsInTraversal()
         {
-            // smoke test to validate serialization of OptionsStrategy. no way 
to really validate this from an integration
-            // test perspective because there's no way to access the internals 
of the strategy via bytecode
             var connection = _connectionFactory.CreateRemoteConnection();
             var options = new Dictionary<string,object>
             {
@@ -210,13 +211,14 @@ namespace 
Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection
                 {"y", true}
             };
             var g = 
AnonymousTraversalSource.Traversal().WithRemote(connection);
-
-            var b = new Bindings();
+            
             var countWithStrategy = g.WithStrategies(new 
OptionsStrategy(options)).V().Count().Next();
             Assert.Equal(6, countWithStrategy);
+            
+            Assert.Equal(ResponseStatusCode.ServerTimeout, 
Assert.Throws<ResponseException>(() => 
+                g.With("y").With("x", "test").With(Tokens.ArgsEvalTimeout, 
10).Inject(1)
+                    
.SideEffect(Lambda.Groovy("Thread.sleep(10000)")).Iterate()).StatusCode);
 
-            var countWith = g.With("x", "test").With("y", 
true).V().Count().Next();
-            Assert.Equal(6, countWith);
         }
 
         [Fact]
diff --git 
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java 
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
index d7a4215..92641a7 100644
--- 
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
+++ 
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
@@ -18,6 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
 /**
  * String constants used in gremlin-driver and gremlin-server.
  *
@@ -46,12 +50,38 @@ public final class Tokens {
     @Deprecated
     public static final String OPS_KEYS = "keys";
 
+    /**
+     * The key for the unique identifier of the request.
+     */
     public static final String REQUEST_ID = "requestId";
+
+    /**
+     * Argument name that allows definition of the number of iterations each 
{@link ResponseMessage} should contain -
+     * overrides the @{code resultIterationBatchSize} server setting.
+     */
     public static final String ARGS_BATCH_SIZE = "batchSize";
+
+    /**
+     * Argument name that allows to provide a map of key/value pairs to apply 
as variables in the context of
+     * the Gremlin request sent to the server.
+     */
     public static final String ARGS_BINDINGS = "bindings";
+
+    /**
+     * Argument name that allows definition of alias names for {@link Graph} 
and {@link TraversalSource} objects on
+     * the remote system.
+     */
     public static final String ARGS_ALIASES = "aliases";
     public static final String ARGS_FORCE = "force";
+
+    /**
+     * Argument name that corresponds to the Gremlin to evaluate.
+     */
     public static final String ARGS_GREMLIN = "gremlin";
+
+    /**
+     * Argument name that allows definition of the flavor of Gremlin used 
(e.g. gremlin-groovy) to process the request.
+     */
     public static final String ARGS_LANGUAGE = "language";
 
     /**
@@ -59,6 +89,11 @@ public final class Tokens {
      */
     @Deprecated
     public static final String ARGS_SCRIPT_EVAL_TIMEOUT = 
"scriptEvaluationTimeout";
+
+    /**
+     * Argument name that allows the override of the server setting that 
determines the maximum time to wait for a
+     * request to execute on the server.
+     */
     public static final String ARGS_EVAL_TIMEOUT = "evaluationTimeout";
     public static final String ARGS_HOST = "host";
     public static final String ARGS_SESSION = "session";
@@ -86,6 +121,11 @@ public final class Tokens {
      */
     @Deprecated
     public static final String ARGS_SIDE_EFFECT_KEY = "sideEffectKey";
+
+    /**
+     * A value that is a custom string that the user can pass to a server that 
might accept it for purpose of
+     * identifying the kind of client it came from.
+     */
     public static final String ARGS_USER_AGENT = "userAgent";
 
     /**

Reply via email to