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/05/17 12:03:33 UTC

[tinkerpop] branch master updated (1b221be -> e0d2091)

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

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


    from 1b221be  Merge branch 'tp33'
     new f71ce0d  Fixed typo in header ancho CTR
     new e0d2091  Merge branch 'tp33'

The 2 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.


Summary of changes:
 docs/src/reference/gremlin-variants.asciidoc | 2 ++
 docs/src/reference/the-traversal.asciidoc    | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)


[tinkerpop] 02/02: Merge branch 'tp33'

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

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

commit e0d2091ee18061faa68d9068dd18c2eaad748158
Merge: 1b221be f71ce0d
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Fri May 17 08:03:20 2019 -0400

    Merge branch 'tp33'

 docs/src/reference/gremlin-variants.asciidoc | 2 ++
 docs/src/reference/the-traversal.asciidoc    | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --cc docs/src/reference/gremlin-variants.asciidoc
index 24a4e2d,e4a6cef..efb843d
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@@ -753,229 -305,116 +753,230 @@@ g.V().out().map(lambda: "x: len(x.get()
  <7> The default lambda language is changed back to Gremlin-Python.
  <8> If the `lambda`-prefix is not provided, then it is appended automatically in order to give a more natural look to the expression.
  
 -=== Limitations
 +Finally, Gremlin `Bytecode` that includes lambdas requires that the traversal be processed by the
 +`ScriptEngine`. To avoid continued recompilation costs, it supports the encoding of bindings, which allow a remote
 +engine to to cache traversals that will be reused over and over again save that some parameterization may change. Thus,
 +instead of translating, compiling, and then executing each submitted bytecode, it is possible to simply execute.
  
 -* Traversals that return a `Set` *might* be coerced to a `List` in Python. In the case of Python, number equality 
 -is different from JVM languages which produces different `Set` results when those types are in use. When this case
 -is detected during deserialization, the `Set` is coerced to a `List` so that traversals return consistent
 -results within a collection across different languages. If a `Set` is needed then convert `List` results
 -to `Set` manually.
 +[gremlin-python,modern]
 +----
 +g.V(Bindings.of('id',1)).out('created').map(lambda: ("it.get().value('name').length()", "gremlin-groovy")).sum().toList()
 +g.V(Bindings.of('id',4)).out('created').map(lambda: ("it.get().value('name').length()", "gremlin-groovy")).sum().toList()
 +----
  
 -[[gremlin-DotNet]]
 -== Gremlin.Net
 +==== Native Python Lambdas
  
 -image:gremlin-dotnet-logo.png[width=371,float=right] Apache TinkerPop's Gremlin.Net implements Gremlin within the C# language. It targets .NET Standard and can
 -therefore be used on different operating systems and with different .NET frameworks, such as .NET Framework
 -and link:https://www.microsoft.com/net/core[.NET Core]. Since the C# syntax is very similar to that of Java, it should be very easy to switch between
 -Gremlin-Java and Gremlin.Net. The only major syntactical difference is that all method names in Gremlin.Net
 -use PascalCase as opposed to camelCase in Gremlin-Java in order to comply with .NET conventions.
 +To process lambdas in Python, the `GremlinJythonScriptEngine` must be enabled on the remote end. If that remote is
 +Gremlin Server, then these instructions can help configuration it. As an example, the
 +`conf/gremlin-server-modern-py.yaml` configuration maintains a `GremlinJythonScriptEngine`.
  
 -[source,powershell]
 -nuget install Gremlin.Net
 +[source,bash]
 +----
 +$ bin/gremlin-server.sh install org.apache.tinkerpop gremlin-python x.y.z
 +$ bin/gremlin-server.sh conf/gremlin-server-modern-py.yaml
 +[INFO] GremlinServer -
 +       \,,,/
 +       (o o)
 +---oOOo-(3)-oOOo---
  
 -In Gremlin.Net there exists `GraphTraversalSource`, `GraphTraversal`, and `__` which mirror the respective classes
 -in Gremlin-Java. The `GraphTraversalSource` requires a driver in order to communicate with <<gremlin-server,GremlinServer>> (or any
 -RemoteConnection-enabled server).
 +[INFO] GremlinServer - Configuring Gremlin Server from conf/gremlin-server-modern-py.yaml
 +[INFO] MetricManager - Configured Metrics Slf4jReporter configured with interval=180000ms and loggerName=org.apache.tinkerpop.gremlin.server.Settings$Slf4jReporterMetrics
 +[INFO] GraphManager - Graph [graph] was successfully configured via [conf/tinkergraph-empty.properties].
 +[INFO] ServerGremlinExecutor - Initialized Gremlin thread pool.  Threads in pool named with pattern gremlin-*
 +[INFO] ScriptEngines - Loaded gremlin-jython ScriptEngine
 +[INFO] ScriptEngines - Loaded gremlin-python ScriptEngine
 +[INFO] ScriptEngines - Loaded gremlin-groovy ScriptEngine
 +[INFO] GremlinExecutor - Initialized gremlin-groovy ScriptEngine with scripts/generate-modern.groovy
 +[INFO] ServerGremlinExecutor - Initialized GremlinExecutor and configured ScriptEngines.
 +[INFO] ServerGremlinExecutor - A GraphTraversalSource is now bound to [g] with graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
 +[INFO] OpLoader - Adding the standard OpProcessor.
 +[INFO] OpLoader - Adding the session OpProcessor.
 +[INFO] OpLoader - Adding the traversal OpProcessor.
 +[INFO] TraversalOpProcessor - Initialized cache for TraversalOpProcessor with size 1000 and expiration time of 600000 ms
 +[INFO] GremlinServer - Executing start up LifeCycleHook
 +[INFO] Logger$info - Loading 'modern' graph data.
 +[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 +[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+gryo-stringd with org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0
 +[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 +[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
 +[INFO] GremlinServer$1 - Gremlin Server configured with worker thread pool of 1, gremlin pool of 4 and boss thread pool of 1.
 +[INFO] GremlinServer$1 - Channel started at port 8182.
 +----
  
 -The `Gremlin.Net.Driver.Remote.DriverRemoteConnection` is provided as part of Apache TinkerPop’s Gremlin.Net.
 +NOTE: The command to use `install` need only be executed once to gather `gremlin-python` dependencies into Gremlin Servers'
 +path. Future starts of Gremlin Server will not require that command.
  
 -IMPORTANT: For developers wishing to provide another driver implementation, be sure to implement `IRemoteConnection` in
 -`Gremlin.Net.Process.Remote` so it can then be used by Gremlin.Net’s `GraphTraversal`.
 +WARNING: As explained throughout the documentation, when possible <<a-note-on-lambdas,avoid>> lambdas. If lambdas
 +must be used, then consider submitting Groovy lambdas as opposed to Python-based ones. The `GremlinGroovyScriptEngine`
 +is far more featured and performant than its Jython sibling and will likely yield better results.
  
 -When Gremlin Server is running, Gremlin.Net can communicate with Gremlin Server by sending traversals serialized as `Bytecode`.
 +=== Submitting Scripts
  
 -IMPORTANT: Gremlin.Net is not compatible with GraphSON 1.0.
 +WARNING: TinkerPop does not recommend submitting script-based requests and generally continues to support this feature
 +for legacy reasons and corner use cases which are still not completely addressed by the Gremlin language. Please
 +consider using bytecode-based requests instead when possible.
  
 -A traversal source can be spawned anonymously using an `AnonymousTraversalSource` which can be statically imported as
 -follows:
 +The `Client` class implementation/interface is based on the Java Driver, with some restrictions. Most notably,
 +Gremlin-Python does not yet implement the `Cluster` class. Instead, `Client` is instantiated directly.
 +Usage is as follows:
  
 -[source,csharp]
 +[source,python]
  ----
 -using static Gremlin.Net.Process.Traversal.AnonymousTraversalSource;
 +from gremlin_python.driver import client <1>
 +client = client.Client('ws://localhost:8182/gremlin', 'g') <2>
  ----
  
 -which will expose a static `Traversal()` method which can be used as follows to yield a `GraphTraversalSource` assigned
 -to "g" and configured to connect to Gremlin Server at "localhost:8182":
 +<1> Import the Gremlin-Python `client` module.
 +<2> Opens a reference to `localhost` - note that there are various configuration options that can be passed
 +to the `Client` object upon instantiation as keyword arguments.
  
 -[source,csharp]
 +Once a `Client` instance is ready, it is possible to issue some Gremlin:
 +
 +[source,python]
  ----
 -var remoteConnection = new DriverRemoteConnection(new GremlinClient(new GremlinServer("localhost", 8182)));
 -var g = Traversal().WithRemote(remoteConnection);
 +result_set = client.submit("[1,2,3,4]")  <1>
 +future_results = result_set.all()  <2>
 +results = future_results.result() <3>
 +assert results == [1, 2, 3, 4] <4>
 +
 +future_result_set = client.submitAsync("[1,2,3,4]") <5>
 +result_set = future_result_set.result() <6>
 +result = result_set.one() <7>
 +assert results == [1, 2, 3, 4] <8>
 +assert result_set.done.done() <9>
 +
 +client.close() <10>
  ----
  
 -When a traversal from the `GraphTraversalSource` is iterated, the traversal’s `Bytecode` is sent over the wire via the registered
 -`IRemoteConnection`. The bytecode is used to construct the equivalent traversal at the remote traversal source.
 -Moreover, typically the bytecode is analyzed to determine which language the bytecode should be translated to. If the traversal
 -does not contain lambdas, the remote location (e.g. Gremlin Server) will typically
 -use Gremlin-Java. If it has lambdas written in Groovy, it will use Gremlin-Groovy (e.g. `GremlinGroovyScriptEngine`).
 -Likewise, if it has lambdas represented in Python, it will use Gremlin-Python (e.g. `GremlinJythonScriptEngine`).
 +<1> Submit a script that simply returns a `List` of integers.  This method blocks until the request is written to
 +the server and a `ResultSet` is constructed.
 +<2> Even though the `ResultSet` is constructed, it does not mean that the server has sent back the results (or even
 +evaluated the script potentially).  The `ResultSet` is just a holder that is awaiting the results from the server. The `all` method
 +returns a `concurrent.futures.Future` that resolves to a list when it is complete.
 +<3> Block until the the script is evaluated and results are sent back by the server.
 +<4> Verify the result.
 +<5> Submit the same script to the server but don't block.
 +<6> Wait until request is written to the server and `ResultSet` is constructed.
 +<7> Read a single result off the result stream.
 +<8> Again, verify the result.
 +<9> Verify that the all results have been read and stream is closed.
 +<10> Close client and underlying pool connections.
  
 -IMPORTANT: Gremlin.Net’s `ITraversal` interface supports the standard Gremlin methods such as `Next()`, `NextTraverser()`, `ToSet()`,
 -`ToList()`, etc. Such "terminal" methods trigger the evaluation of the traversal.
++[[gremlin-python-dsl]]
 +=== Domain Specific Languages
  
 -=== RemoteConnection Submission
 +Writing a Gremlin <<dsl,Domain Specific Language>> (DSL) in Python simply requires direct extension of several classes:
  
 -Very similar to Gremlin-Python and Gremlin-Java, there are various ways to submit a traversal to a `IRemoteConnection` using
 -terminal/action methods off of `ITraversal`.
 +* `GraphTraversal` - which exposes the various steps used in traversal writing
 +* `__` - which spawns anonymous traversals from steps
 +* `GraphTraversalSource` - which spawns `GraphTraversal` instances
  
 -* `ITraversal.Next()`
 -* `ITraversal.NextTraverser()`
 -* `ITraversal.ToList()`
 -* `ITraversal.ToSet()`
 -* `ITraversal.Iterate()`
 +The Social DSL based on the link:http://tinkerpop.apache.org/docs/current/images/tinkerpop-modern.png["modern" toy graph]
 +might look like this:
  
 -=== Configuration
 +[source,python]
 +----
 +class SocialTraversal(GraphTraversal):
  
 -The following sections describe how the Gremlin.Net driver can be configured.
 +    def knows(self, person_name):
 +        return self.out("knows").hasLabel("person").has("name", person_name)
  
 -==== Gremlin Server
 +    def youngestFriendsAge(self):
 +        return self.out("knows").hasLabel("person").values("age").min()
  
 -The connection properties for the Gremlin.Net driver can be passed to the `GremlinServer` instance as keyword arguments:
 +    def createdAtLeast(self, number):
 +        return self.outE("created").count().is_(P.gte(number))
  
 -[width="100%",cols="3,10,^2",options="header"]
 -|=========================================================
 -|Key |Description |Default
 -|hostname |The hostname that the driver will connect to. |localhost
 -|port |The port on which Gremlin Server can be reached. |8182
 -|enableSsl |Determines if SSL should be enabled or not. If enabled on the server then it must be enabled on the client. |false
 -|username |The username to submit on requests that require authentication. |_none_
 -|password |The password to submit on requests that require authentication. |_none_
 -|=========================================================
 +class __(AnonymousTraversal):
  
 -==== GraphSON Serialization
 +    graph_traversal = SocialTraversal
  
 -The Gremlin.Net driver uses by default GraphSON 3.0 but it is also possible to use GraphSON 2.0 which can be necessary
 -when the server does not support GraphSON 3.0 yet:
 +    @classmethod
 +    def knows(cls, *args):
 +        return cls.graph_traversal(None, None, Bytecode()).knows(*args)
  
 -[source,csharp]
 +    @classmethod
 +    def youngestFriendsAge(cls, *args):
 +        return cls.graph_traversal(None, None, Bytecode()).youngestFriendsAge(*args)
 +
 +    @classmethod
 +    def createdAtLeast(cls, *args):
 +        return cls.graph_traversal(None, None, Bytecode()).createdAtLeast(*args)
 +
 +
 +class SocialTraversalSource(GraphTraversalSource):
 +
 +    def __init__(self, *args, **kwargs):
 +        super(SocialTraversalSource, self).__init__(*args, **kwargs)
 +        self.graph_traversal = SocialTraversal
 +
 +    def persons(self, *args):
 +        traversal = self.get_graph_traversal()
 +        traversal.bytecode.add_step("V")
 +        traversal.bytecode.add_step("hasLabel", "person")
 +
 +        if len(args) > 0:
 +            traversal.bytecode.add_step("has", "name", P.within(args))
 +
 +        return traversal
  ----
 -var client = new GremlinClient(new GremlinServer("localhost", 8182), new GraphSON2Reader(),
 -    new GraphSON2Writer(), GremlinClient.GraphSON2MimeType);
 +
 +NOTE: The `AnonymousTraversal` class above is just an alias for `__` as in
 +`from gremlin_python.process.graph_traversal import __ as AnonymousTraversal`
 +
 +Using the DSL is straightforward and just requires that the graph instance know the `SocialTraversalSource` should
 +be used:
 +
 +[source,python]
 +----
 +social = Graph().traversal(SocialTraversalSource).withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
 +social.persons("marko").knows("josh")
 +social.persons("marko").youngestFriendsAge()
 +social.persons().filter(__.createdAtLeast(2)).count()
  ----
  
 -=== Static Enums and Methods
 +=== Syntactic Sugar
  
 -Gremlin has various tokens (e.g. `T`, `P`, `Order`, `Operator`, etc.) that are represented in Gremlin.Net as classes.
 +Python supports meta-programming and operator overloading. There are three uses of these techniques in Gremlin-Python
 +that makes traversals a bit more concise.
  
 -These can be used analogously to how they are used in Gremlin-Java.
 +[gremlin-python,modern]
 +----
 +g.V().both()[1:3].toList()
 +g.V().both()[1].toList()
 +g.V().both().name.toList()
 +----
  
 -[source,csharp]
 -g.V().HasLabel("person").Has("age",P.Gt(30)).Order().By("age",Order.desc).ToList()
 +=== Limitations
  
 -Moreover, the class prefixes can be omitted with a `using static`.
 +* Traversals that return a `Set` *might* be coerced to a `List` in Python. In the case of Python, number equality
 +is different from JVM languages which produces different `Set` results when those types are in use. When this case
 +is detected during deserialization, the `Set` is coerced to a `List` so that traversals return consistent
 +results within a collection across different languages. If a `Set` is needed then convert `List` results
 +to `Set` manually.
 +* Gremlin is capable of returning `Dictionary` results that use non-hashable keys (e.g. Dictionary as a key) and Python
 +does not support that at a language level. Gremlin that returns such results will need to be re-written to avoid that.
 +
 +anchor:gremlin-DotNet[]
 +[[gremlin-dotnet]]
 +== Gremlin.Net
 +
 +image:gremlin-dotnet-logo.png[width=371,float=right] Apache TinkerPop's Gremlin.Net implements Gremlin within the C#
 +language. It targets .NET Standard and can therefore be used on different operating systems and with different .NET
 +frameworks, such as .NET Framework and link:https://www.microsoft.com/net/core[.NET Core]. Since the C# syntax is very
 +similar to that of Java, it should be very easy to switch between Gremlin-Java and Gremlin.Net. The only major
 +syntactical difference is that all method names in Gremlin.Net use PascalCase as opposed to camelCase in Gremlin-Java
 +in order to comply with .NET conventions.
 +
 +[source,powershell]
 +nuget install Gremlin.Net
 +
 +=== Connecting
 +
 +The pattern for connecting is described in <<connecting-gremlin,Connecting Gremlin>> and it basically distills down to
 +creating a `GraphTraversalSource`. A `GraphTraversalSource` is created from the `AnonymousTraversalSource.traversal()`
 +method where the "g" provided to the `DriverRemoteConnection` corresponds to the name of a `GraphTraversalSource` on
 +the remote end.
  
  [source,csharp]
  ----
@@@ -1065,81 -497,6 +1066,82 @@@ g.V().Out().Map<int>(Lambda.Python("lam
  The `ILambda` interface returned by these two methods inherits interfaces like `IFunction` and `IPredicate` that mirror
  their Java counterparts which makes it possible to use lambdas with Gremlin.Net for the same steps as in Gremlin-Java.
  
 +=== Submitting Scripts
 +
 +WARNING: TinkerPop does not recommend submitting script-based requests and generally continues to support this feature
 +for legacy reasons and corner use cases which are still not completely addressed by the Gremlin language. Please
 +consider using bytecode-based requests instead when possible.
 +
 +Gremlin scripts are sent to the server from a `IGremlinClient` instance.  A `IGremlinClient` is created as follows:
 +
 +[source,csharp]
 +----
 +include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs[tags=submittingScripts]
 +----
 +
 +If the remote system has authentication and SSL enabled, then the `GremlinServer` object can be configured as follows:
 +
 +[source,csharp]
 +----
 +include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs[tags=submittingScriptsWithAuthentication]
 +----
 +
++[[gremlin-net-dsl]]
 +=== Domain Specific Languages
 +
 +Developing a <<dsl,Domain Specific Language>> (DSL) for .Net is most easily implemented using
 +link:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods[Extension Methods]
 +as they don't require direct extension of classes in the TinkerPop hierarchy. Extension Method classes simply need to
 +be constructed for the `GraphTraversal` and the `GraphTraversalSource`. Unfortunately, anonymous traversals (spawned
 +from `__`) can't use the Extension Method approach as they do not work for static classes and static classes can't be
 +extended. The only option is to re-implement the methods of `__` as a wrapper in the anonymous traversal for the DSL
 +or to simply create a static class for the DSL and use the two anonymous traversals creators independently. The
 +following example uses the latter approach as it saves a lot of boilerplate code with the minor annoyance of having a
 +second static class to deal with when writing traversals rather than just calling `__` for everything.
 +
 +[source,csharp]
 +----
 +include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsDsl.cs[tags=dsl]
 +----
 +
 +Note the creation of `__Social` as the Social DSL's "extension" to the available ways in which to spawn anonymous
 +traversals. The use of the double underscore prefix in the name is just a convention to consider using and is not a
 +requirement. To use the DSL, bring it into scope with the `using` directive:
 +
 +[source,csharp]
 +----
 +include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsDslTests.cs[tags=dslUsing]
 +----
 +
 +and then it can be called from the application as follows:
 +
 +[source,csharp]
 +----
 +include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsDslTests.cs[tags=dslExamples]
 +----
 +
 +anchor:gremlin-dotnet-template[]
 +[[dotnet-application-examples]]
 +=== Application Examples
 +
 +This link:https://docs.microsoft.com/dotnet/core/tools/custom-templates[dotnet template] helps getting started with
 +<<gremlin-dotnet,Gremlin.Net>>. It creates a new C# console project that shows how to connect to a
 +<<gremlin-server,Gremlin Server>> with Gremlin.Net.
 +
 +You can install the template with the dotnet CLI tool:
 +[source,shell]
 +dotnet new -i Gremlin.Net.Template
 +
 +After the template is installed, a new project based on this template can be installed:
 +
 +[source,shell]
 +dotnet new gremlin
 +
 +Specify the output directory for the new project which will then also be used as the name of the created project:
 +
 +[source,shell]
 +dotnet new gremlin -o MyFirstGremlinProject
 +
  [[gremlin-javascript]]
  == Gremlin-JavaScript
  
diff --cc docs/src/reference/the-traversal.asciidoc
index c1d4ef8,914411c..f5f43eb
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@@ -4020,5 -3659,357 +4020,5 @@@ g.V().hasLabel('person').has('name','ma
  social.persons("marko").youngestFriendsAge()
  ----
  
- Learn more about hwo to implement these DSLs in the <<gremlin-drivers-variants,Gremlin Language Variants>> section
 -The following sections explain how to develop application specific DSLs for different <<gremlin-variants,Gremlin Language Variants>>
 -using the examples above of the Social DSL as the API for the implementation.
 -
 -[[gremlin-java-dsl]]
 -=== Gremlin-Java
 -
 -Creating a DSL in Java requires the `@GremlinDsl` Java annotation in `gremlin-core`. This annotation should be applied
 -to a "DSL interface" that extends `GraphTraversal.Admin`.
 -
 -[source,java]
 -----
 -@GremlinDsl
 -public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 -}
 -----
 -
 -IMPORTANT: The name of the DSL interface should be suffixed with "TraversalDSL". All characters in the interface name
 -before that become the "name" of the DSL.
 -
 -In this interface, define the methods that the DSL will be composed of:
 -
 -[source,java]
 -----
 -@GremlinDsl
 -public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 -    public default GraphTraversal<S, Vertex> knows(String personName) {
 -        return out("knows").hasLabel("person").has("name", personName);
 -    }
 -
 -    public default <E2 extends Number> GraphTraversal<S, E2> youngestFriendsAge() {
 -        return out("knows").hasLabel("person").values("age").min();
 -    }
 -
 -    public default GraphTraversal<S, Long> createdAtLeast(int number) {
 -        return outE("created").count().is(P.gte(number));
 -    }
 -}
 -----
 -
 -IMPORTANT: Follow the TinkerPop convention of using `<S,E>` in naming generics as those conventions are taken into
 -account when generating the anonymous traversal class. The processor attempts to infer the appropriate type parameters
 -when generating the anonymous traversal class. If it cannot do it correctly, it is possible to avoid the inference by
 -using the `GremlinDsl.AnonymousMethod` annotation on the DSL method. It allows explicit specification of the types to
 -use.
 -
 -The `@GremlinDsl` annotation is used by the link:https://docs.oracle.com/javase/8/docs/api/index.html?javax/annotation/processing/Processor.html[Java Annotation Processor]
 -to generate the boilerplate class structure required to properly use the DSL within the TinkerPop framework. These
 -classes can be generated and maintained by hand, but it would be time consuming, monotonous and error-prone to do so.
 -Typically, the Java compilation process is automatically configured to detect annotation processors on the classpath
 -and will automatically use them when found. If that does not happen, it may be necessary to make configuration changes
 -to the build to allow for the compilation process to be aware of the following `javax.annotation.processing.Processor`
 -implementation:
 -
 -[source,java]
 -----
 -org.apache.tinkerpop.gremlin.process.traversal.dsl.GremlinDslProcessor
 -----
 -
 -The annotation processor will generate several classes for the DSL:
 -
 -* `SocialTraversal` - A `Traversal` interface that extends the `SocialTraversalDsl` proxying methods to its underlying
 -interfaces (such as `GraphTraversal`) to instead return a `SocialTraversal`
 -* `DefaultSocialTraversal` - A default implementation of `SocialTraversal` (typically not used directly by the user)
 -* `SocialTraversalSource` - Spawns `DefaultSocialTraversal` instances.
 -* `__` - Spawns anonymous `DefaultSocialTraversal` instances.
 -
 -Using the DSL then just involves telling the `Graph` to use it:
 -
 -[source,java]
 -----
 -SocialTraversalSource social = graph.traversal(SocialTraversalSource.class);
 -social.V().has("name","marko").knows("josh");
 -----
 -
 -The `SocialTraversalSource` can also be customized with DSL functions. As an additional step, include a class that
 -extends from `GraphTraversalSource` and with a name that is suffixed with "TraversalSourceDsl". Include in this class,
 -any custom methods required by the DSL:
 -
 -[source,java]
 -----
 -public class SocialTraversalSourceDsl extends GraphTraversalSource {
 -
 -    public SocialTraversalSourceDsl(Graph graph, TraversalStrategies traversalStrategies) {
 -        super(graph, traversalStrategies);
 -    }
 -
 -    public SocialTraversalSourceDsl(Graph graph) {
 -        super(graph);
 -    }
 -
 -    public GraphTraversal<Vertex, Vertex> persons(String... names) {
 -        GraphTraversalSource clone = this.clone();
 -
 -        // Manually add a "start" step for the traversal in this case the equivalent of V(). GraphStep is marked
 -        // as a "start" step by passing "true" in the constructor.
 -        clone.getBytecode().addStep(GraphTraversal.Symbols.V);
 -        GraphTraversal<Vertex, Vertex> traversal = new DefaultGraphTraversal<>(clone);
 -        traversal.asAdmin().addStep(new GraphStep<>(traversal.asAdmin(), Vertex.class, true));
 -
 -        traversal = traversal.hasLabel("person");
 -        if (names.length > 0) traversal = traversal.has("name", P.within(names));
 -
 -        return traversal;
 -    }
 -}
 -----
 -
 -Then, back in the `SocialTraversal` interface, update the `GremlinDsl` annotation with the `traversalSource` argument
 -to point to the fully qualified class name of the `SocialTraversalSourceDsl`:
 -
 -[source,java]
 -----
 -@GremlinDsl(traversalSource = "com.company.SocialTraversalSourceDsl")
 -public interface SocialTraversalDsl<S, E> extends GraphTraversal.Admin<S, E> {
 -    ...
 -}
 -----
 -
 -It is then possible to use the `persons()` method to start traversals:
 -
 -[source,java]
 -----
 -SocialTraversalSource social = graph.traversal(SocialTraversalSource.class);
 -social.persons("marko").knows("josh");
 -----
 -
 -NOTE: Using Maven, as shown in the `gremlin-archetype-dsl` module, makes developing DSLs with the annotation processor
 -straightforward in that it sets up appropriate paths to the generated code automatically.
 -
 -[[gremlin-python-dsl]]
 -=== Gremlin-Python
 -
 -Writing a Gremlin DSL in Python simply requires direct extension of several classes:
 -
 -* `GraphTraversal` - which exposes the various steps used in traversal writing
 -* `__` - which spawns anonymous traversals from steps
 -* `GraphTraversalSource` - which spawns `GraphTraversal` instances
 -
 -The Social DSL based on the link:http://tinkerpop.apache.org/docs/current/images/tinkerpop-modern.png["modern" toy graph]
 -might look like this:
 -
 -[source,python]
 -----
 -class SocialTraversal(GraphTraversal):
 -
 -    def knows(self, person_name):
 -        return self.out("knows").hasLabel("person").has("name", person_name)
 -
 -    def youngestFriendsAge(self):
 -        return self.out("knows").hasLabel("person").values("age").min()
 -
 -    def createdAtLeast(self, number):
 -        return self.outE("created").count().is_(P.gte(number))
 -
 -class __(AnonymousTraversal):
 -
 -    graph_traversal = SocialTraversal
 -
 -    @classmethod
 -    def knows(cls, *args):
 -        return cls.graph_traversal(None, None, Bytecode()).knows(*args)
 -
 -    @classmethod
 -    def youngestFriendsAge(cls, *args):
 -        return cls.graph_traversal(None, None, Bytecode()).youngestFriendsAge(*args)
 -
 -    @classmethod
 -    def createdAtLeast(cls, *args):
 -        return cls.graph_traversal(None, None, Bytecode()).createdAtLeast(*args)
 -
 -
 -class SocialTraversalSource(GraphTraversalSource):
 -
 -    def __init__(self, *args, **kwargs):
 -        super(SocialTraversalSource, self).__init__(*args, **kwargs)
 -        self.graph_traversal = SocialTraversal
 -
 -    def persons(self, *args):
 -        traversal = self.get_graph_traversal()
 -        traversal.bytecode.add_step("V")
 -        traversal.bytecode.add_step("hasLabel", "person")
 -
 -        if len(args) > 0:
 -            traversal.bytecode.add_step("has", "name", P.within(args))
 -
 -        return traversal
 -----
 -
 -NOTE: The `AnonymousTraversal` class above is just an alias for `__` as in
 -`from gremlin_python.process.graph_traversal import __ as AnonymousTraversal`
 -
 -Using the DSL is straightforward and just requires that the graph instance know the `SocialTraversalSource` should
 -be used:
 -
 -[source,python]
 -----
 -social = Graph().traversal(SocialTraversalSource).withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
 -social.persons("marko").knows("josh")
 -social.persons("marko").youngestFriendsAge()
 -social.persons().filter(__.createdAtLeast(2)).count()
 -----
 -
 -[[gremlin-net-dsl]]
 -=== Gremlin.Net
 -
 -Developing DSLs for .Net is most easily implemented using link:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods[Extension Methods]
 -as they don't require direct extension of classes in the TinkerPop hierarchy. Extension Method classes simply need to
 -be constructed for the `GraphTraversal` and the `GraphTraversalSource`. Unfortunately, anonymous traversals (spawned
 -from `__`) can't use the Extension Method approach as they do not work for static classes and static classes can't be
 -extended. The only option is to re-implement the methods of `__` as a wrapper in the anonymous traversal for the DSL
 -or to simply create a static class for the DSL and use the two anonymous traversals creators independently. The
 -following example uses the latter approach as it saves a lot of boilerplate code with the minor annoyance of having a
 -second static class to deal with when writing traversals rather than just calling `__` for everything.
 -
 -[source,csharp]
 -----
 -namespace Dsl
 -{
 -
 -    public static class SocialTraversalExtensions
 -    {
 -        public static GraphTraversal<Vertex,Vertex> Knows(this GraphTraversal<Vertex,Vertex> t, string personName)
 -        {
 -            return t.Out("knows").HasLabel("person").Has("name", personName);
 -        }
 -
 -        public static GraphTraversal<Vertex, int> YoungestFriendsAge(this GraphTraversal<Vertex,Vertex> t)
 -        {
 -            return t.Out("knows").HasLabel("person").Values<int>("age").Min<int>();
 -        }
 -
 -        public static GraphTraversal<Vertex,long> CreatedAtLeast(this GraphTraversal<Vertex,Vertex> t, long number)
 -        {
 -            return t.OutE("created").Count().Is(P.Gte(number));
 -        }
 -    }
 -
 -    public static class __Social
 -    {
 -        public static GraphTraversal<object,Vertex> Knows(string personName)
 -        {
 -            return __.Out("knows").HasLabel("person").Has("name", personName);
 -        }
 -
 -        public static GraphTraversal<object, int> YoungestFriendsAge()
 -        {
 -            return __.Out("knows").HasLabel("person").Values<int>("age").Min<int>();
 -        }
 -
 -        public static GraphTraversal<object,long> CreatedAtLeast(long number)
 -        {
 -            return __.OutE("created").Count().Is(P.Gte(number));
 -        }
 -    }
 -
 -    public static class SocialTraversalSourceExtensions
 -    {
 -        public static GraphTraversal<Vertex,Vertex> Persons(this GraphTraversalSource g, params string[] personNames)
 -        {
 -            GraphTraversal<Vertex,Vertex> t = g.V().HasLabel("person");
 -
 -            if (personNames.Length > 0)
 -            {
 -                t = t.Has("name", P.Within(personNames));
 -            }
 -
 -            return t;
 -        }
 -    }
 -}
 -----
 -
 -Note the creation of `__Social` as the Social DSL's "extension" to the available ways in which to spawn anonymous
 -traversals. The use of the double underscore prefix in the name is just a convention to consider using and is not a
 -requirement. To use the DSL, bring it into scope with the `using` directive:
 -
 -[source,csharp]
 -----
 -using Dsl;
 -using static Dsl.__Social;
 -----
 -
 -and then it can be called from the application as follows:
 -
 -[source,csharp]
 -----
 -var graph = new Graph();
 -var connection = new DriverRemoteConnection(new GremlinClient(new GremlinServer("localhost", 8182)));
 -var social = graph.Traversal().WithRemote(connection);
 -
 -social.Persons("marko").Knows("josh");
 -social.Persons("marko").YoungestFriendsAge();
 -social.Persons().Filter(CreatedAtLeast(2)).Count();
 -----
 -
 -[[gremlin-javascript-dsl]]
 -=== Gremlin-JavaScript
 -
 -Developing Gremlin DSLs in JavaScript largely requires extension of existing core classes with use of standalone
 -functions for anonymous traversal spawning. The pattern is demonstrated in the following example:
 -
 -[source,javascript]
 -----
 -class SocialTraversal extends GraphTraversal {
 -  constructor(graph, traversalStrategies, bytecode) {
 -    super(graph, traversalStrategies, bytecode);
 -  }
 -
 -  aged(age) {
 -    return this.has('person', 'age', age);
 -  }
 -}
 -
 -class SocialTraversalSource extends GraphTraversalSource {
 -  constructor(graph, traversalStrategies, bytecode) {
 -    super(graph, traversalStrategies, bytecode, SocialTraversalSource, SocialTraversal);
 -  }
 -
 -  person(name) {
 -    return this.V().has('person', 'name', name);
 -  }
 -}
 -
 -function anonymous() {
 -  return new SocialTraversal(null, null, new Bytecode());
 -}
 -
 -function aged(age) {
 -  return anonymous().aged(age);
 -}
 -----
 -
 -`SocialTraversal` extends the core `GraphTraversal` class and has a three argument constructor which is immediately
 -proxied to the `GraphTraversal` constructor. New DSL steps are then added to this class using available steps to
 -construct the underlying traversal to execute as demonstrated in the `aged()` step.
 -
 -The `SocialTraversal` is spawned from a `SocialTraversalSource` which is extended from `GraphTraversalSource`. Steps
 -added here are meant to be start steps. In the above case, the `person()` start step find a "person" vertex to begin
 -the traversal from.
 -
 -Typically, steps that are made available on a `GraphTraversal` (i.e. SocialTraversal in this example) should also be
 -made available as spawns for anonymous traversals. The recommendation is that these steps be exposed in the module
 -as standalone functions. In the example above, the standalone `aged()` step creates an anonymous traversal through
 -an `anonymous()` utility function. The method for creating these standalone functions can be handled in other ways if
 -desired.
 -
 -To use the DSL, simply initialize the `g` as follows:
 -
 -[source,javascript]
 -----
 -const g = traversal(SocialTraversalSource).withRemote(connection);
 -g.person('marko').aged(29).values('name').toList().
 -  then(names => console.log(names));
 -----
++Learn more about how to implement these DSLs in the <<gremlin-drivers-variants,Gremlin Language Variants>> section
 +specific to the programming language of interest.


[tinkerpop] 01/02: Fixed typo in header ancho CTR

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

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

commit f71ce0d7c03ab475df2bedc6f65555b0f2c57b9e
Author: Stephen Mallette <sp...@genoprime.com>
AuthorDate: Fri May 17 07:59:42 2019 -0400

    Fixed typo in header ancho CTR
---
 docs/src/reference/the-traversal.asciidoc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 41d2eab..914411c 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -3954,7 +3954,7 @@ social.Persons("marko").YoungestFriendsAge();
 social.Persons().Filter(CreatedAtLeast(2)).Count();
 ----
 
-[[gremli-javascript-dsl]]
+[[gremlin-javascript-dsl]]
 === Gremlin-JavaScript
 
 Developing Gremlin DSLs in JavaScript largely requires extension of existing core classes with use of standalone
@@ -4012,4 +4012,4 @@ To use the DSL, simply initialize the `g` as follows:
 const g = traversal(SocialTraversalSource).withRemote(connection);
 g.person('marko').aged(29).values('name').toList().
   then(names => console.log(names));
-----
\ No newline at end of file
+----