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 2020/11/19 14:25:08 UTC

[tinkerpop] branch TINKERPOP-2479 created (now a6ebe54)

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

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


      at a6ebe54  TINKERPOP-2479 Adds config/reset options to :bytecode command

This branch includes the following new commits:

     new a6ebe54  TINKERPOP-2479 Adds config/reset options to :bytecode command

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-2479 Adds config/reset options to :bytecode command

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

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

commit a6ebe54bb97bef15f50e199d44d87b0494d36233
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu Nov 19 09:23:56 2020 -0500

    TINKERPOP-2479 Adds config/reset options to :bytecode command
    
    Also fixes TINKERPOP-2478 where whitespace was a problem with the from/translate options.
---
 CHANGELOG.asciidoc                                 |  3 +
 docs/src/reference/gremlin-applications.asciidoc   | 19 ++++++
 docs/src/upgrade/release-3.4.x.asciidoc            | 10 +++
 .../console/commands/BytecodeCommand.groovy        | 71 ++++++++++++++++++++--
 .../console/commands/BytecodeCommand.properties    |  2 +-
 .../ser/AbstractGraphSONMessageSerializerV2d0.java |  1 -
 6 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d2734ea..3d81a53 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -45,6 +45,9 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Allowed Gremlin Python sugar calls from anonymous context.
 * Implemented `AutoCloseable` on `MultiIterator`.
 * Fixed an iterator leak in `HasContainer`.
+* Fixed bug in `:bytecode` command preventing translations with whitespace from working properly.
+* Added `reset` and `config` options to the `:bytecode` command to allow for greater customization options.
+* Added GraphSON extension module and the `TinkerIoRegistry` to the default `GraphSONMapper` configuration used by the `:bytecode` command.
 * Added `GremlinASTChecker` to provide a way to extract properties of scripts before doing an actual `eval()`.
 * Avoided creating unnecessary detached objects in JVM.
 * Added support for `TraversalStrategy` usage in Javascript.
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 50b5efe..1e2a037 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -148,10 +148,29 @@ gremlin> :bytecode from g.V().out('knows')  <1>
 ==>{"@type":"g:Bytecode","@value":{"step":[["V"],["out","knows"]]}}
 gremlin> :bytecode translate g {"@type":"g:Bytecode","@value":{"step":[["V"],["out","knows"]]}} <2>
 ==>g.V().out("knows")
+gremlin> m = GraphSONMapper.build().create()
+==>org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper@69d6a7cd
+gremlin> :bc config m  <3>
+==>Configured bytecode serializer
+gremlin> :bc from g.V().property('d',java.time.YearMonth.now()) <4>
+Could not find a type identifier for the class : class java.time.Month. Make sure the value to serialize has a type identifier registered for its class. (through reference chain: java.time.YearMonth["month"])
+Type ':help' or ':h' for help.
+Display stack trace? [yN]n
+gremlin> :bc reset  <5>
+==>Bytecode serializer reset to GraphSON 3.0 with extensions and TinkerGraph serializers
+gremlin> :bc from g.V().property('d',java.time.YearMonth.now())
+==>{"@type":"g:Bytecode","@value":{"step":[["V"],["property","d",{"@type":"gx:YearMonth","@value":"2020-11"}]]}}
 ----
 
 <1> Generates a GraphSON 3.0 representation of the traversal as bytecode.
 <2> Converts bytecode in GraphSON 3.0 format to a traversal string.
+<3> Configure a custom `GraphSONMapper` for the `:bytecode` command to use which can be helpful when working with
+custom classes from different graph providers. The `config` option can take a `GraphSONMapper` argument as shown or
+one or more `IoRegistry` or `SimpleModule` implementations that will plug into the default `GraphSONMapper` constructed
+by the `:bytecode` command. The default will configure for GraphSON 3.0 with the extensions module and, if present,
+the `TinkerIoRegistry` from TinkerGraph.
+<4> Note that the `YearMonth` will not serialize because `m` did not configure the extensions module.
+<5> After `reset` it works properly once more.
 
 NOTE: The Console does expose the `:record` command which is inherited from the Groovy Shell. This command works well
 with local commands, but may record session outputs differently for `:remote` commands. If there is a need to use
diff --git a/docs/src/upgrade/release-3.4.x.asciidoc b/docs/src/upgrade/release-3.4.x.asciidoc
index 4b25018..913138a 100644
--- a/docs/src/upgrade/release-3.4.x.asciidoc
+++ b/docs/src/upgrade/release-3.4.x.asciidoc
@@ -59,6 +59,16 @@ be better to continue use of the deprecated versions.
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-2461[TINKERPOP-2461]
 
+=== Bytecode Command Improvements
+
+The `:bytecode` command in the Gremlin console includes two new options: `reset` and `config`. Both options provide
+ways to better control the `GraphSONMapper` used internally by the command. The `reset` option will replace the current
+`GraphSONMapper` with a new one with some basic defaults: GraphSON 3.0 with extension and `TinkerIoRegistry` if
+present. The `config` option provides a way to specify a custom `GraphSONMapper` or additional configurations to the
+default one previously described.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2479[TINKERPOP-2479]
+
 === withStrategies() Groovy Syntax
 
 The `withStrategies()` configuration step accepts a variable number of `TraversalStrategy` instances. In Java, those
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
index 0b09ac4..3718202 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.groovy
@@ -22,9 +22,13 @@ import org.apache.tinkerpop.gremlin.console.Mediator
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal
 import org.apache.tinkerpop.gremlin.process.traversal.translator.GroovyTranslator
+import org.apache.tinkerpop.gremlin.structure.io.IoRegistry
+import org.apache.tinkerpop.gremlin.structure.io.Mapper
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion
+import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV3d0
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper
+import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule
 import org.codehaus.groovy.tools.shell.ComplexCommandSupport
 import org.codehaus.groovy.tools.shell.Groovysh
 
@@ -37,16 +41,27 @@ class BytecodeCommand extends ComplexCommandSupport {
 
     private final Mediator mediator
 
-    private final ObjectMapper mapper = GraphSONMapper.build().version(GraphSONVersion.V3_0).create().createMapper()
+    private ObjectMapper mapper
 
     public BytecodeCommand(final Groovysh shell, final Mediator mediator) {
-        super(shell, ":bytecode", ":bc", ["from", "translate"])
+        super(shell, ":bytecode", ":bc", ["config", "from", "reset", "translate"])
         this.mediator = mediator
+        do_reset()
+    }
+
+    def Object do_config = { List<String> arguments ->
+        def resolvedArgs = arguments.collect{shell.interp.context.getVariable(it)}
+        try {
+            this.initMapper(resolvedArgs)
+            return "Configured bytecode serializer"
+        } catch (IllegalArgumentException iae) {
+            return iae.message
+        }
     }
     
     def Object do_from = { List<String> arguments ->
         mediator.showShellEvaluationOutput(false)
-        def args = arguments.join("")
+        def args = arguments.join(" ")
         def traversal = args.startsWith("@") ? shell.interp.context.getVariable(args.substring(1)) : shell.execute(args)
         if (!(traversal instanceof Traversal))
             return "Argument does not resolve to a Traversal instance, was: " + traversal.class.simpleName
@@ -57,8 +72,56 @@ class BytecodeCommand extends ComplexCommandSupport {
 
     def Object do_translate = { List<String> arguments ->
         def g = arguments[0]
-        def args = arguments.drop(1).join("")
+        def args = arguments.drop(1).join(" ")
         def graphson = args.startsWith("@") ? shell.interp.context.getVariable(args.substring(1)) : args
         return GroovyTranslator.of(g).translate(mapper.readValue(graphson, Bytecode.class))
     }
+
+    def Object do_reset = { List<String> arguments ->
+        def (GraphSONMapper.Builder builder, boolean loadedTinkerGraph) = createDefaultBuilder()
+
+        try {
+            this.initMapper([builder.create()])
+            return "Bytecode serializer reset to GraphSON 3.0 with extensions" +
+                    (loadedTinkerGraph ? " and TinkerGraph serializers" : "")
+        } catch (IllegalArgumentException iae) {
+            return iae.message
+        }
+    }
+
+    private def static createDefaultBuilder() {
+        def builder = GraphSONMapper.build().
+                addCustomModule(GraphSONXModuleV3d0.build().create(false)).
+                version(GraphSONVersion.V3_0)
+
+        def loadedTinkerGraph = false
+        try {
+            def tinkergraphIoRegistry = Class.forName("org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0")
+            builder.addRegistry(tinkergraphIoRegistry."instance"())
+            loadedTinkerGraph = true
+        } catch (Exception ignored) {
+            // ok to skip if the registry isn't present
+        }
+        [builder, loadedTinkerGraph]
+    }
+
+    private initMapper(def args) {
+        if (args.size() == 1 && args[0] instanceof GraphSONMapper) {
+            this.mapper = ((GraphSONMapper) args[0]).createMapper()
+        } else {
+            GraphSONMapper.Builder builder = (GraphSONMapper.Builder) createDefaultBuilder()[0]
+            args.each {
+                if (it instanceof GraphSONMapper)
+                    throw new IllegalArgumentException("If specifying a GraphSONMapper it must be the only argument")
+                else if (it instanceof IoRegistry)
+                    builder.addRegistry(it)
+                else if (it instanceof SimpleModule)
+                    builder.addCustomModule(it)
+                else
+                    throw new IllegalArgumentException("Configuration argument of ${it.class.simpleName} is ignored - must be IoRegistry, SimpleModule or a single GraphSONMapper")
+            }
+
+            this.mapper = builder.create().createMapper()
+        }
+    }
 }
diff --git a/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.properties b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.properties
index d31bea8..c895855 100644
--- a/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.properties
+++ b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/commands/BytecodeCommand.properties
@@ -16,5 +16,5 @@
 # under the License.
 
 command.description=Gremlin bytecode helper commands
-command.usage=[from <Traversal>|translate <g> <bytecode>]
+command.usage=[config <[GraphSONMapper|IoRegistry|SimpleModule]>|from <Traversal>|reset|translate <g> <bytecode>]
 command.help=Gremlin bytecode helper commands
\ No newline at end of file
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java
index fcd389a..2e48e10 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java
@@ -33,7 +33,6 @@ import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
 import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
 import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
-import org.apache.tinkerpop.shaded.jackson.core.type.TypeReference;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
 import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;