[ 
https://issues.apache.org/jira/browse/TINKERPOP-1278?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15329388#comment-15329388
 ] 

Marko A. Rodriguez commented on TINKERPOP-1278:
-----------------------------------------------

So in branch {{TINKERPOP-1278}} we have 2 different ways of doing this 
implemented and I think a third (yet unimplemented) way may be the best. I will 
describe all three models with their +/- so people can help decide which model 
we should go with. First, note that all three models make use of a new 
construct called a {{Translator}}. In short, a {{Translator}} wraps a 
{{StringBuilder}} and for each {{traversal.x(y,z)}} call, 
{{Translator.addStep(traversal, "x", y, z)}} is called. In essence the 
translator is able to take calls in one Gremlin variant and convert them to 
calls in another Gremlin variant.

1. {{ScriptXXXTraversal}} and {{ScriptXXXTraversalSource}}

{{ScriptGraphTraversal}} implements all the methods of {{GraphTraversal}}, but 
instead of {{addStep(new BlahStep())}}, it calls {{Translator.addStep(stepName, 
Object... stepArguments)}}. When {{applyStrategies()}} is called (i.e. the 
traversal is compiled), the {{Translator.getScriptEngine()}} is used to compile 
the internal {{Translator.getTraversalScript()}} and the result of the 
compilation is added to the {{ScriptGraphTraversal}} and thus, the 
{{ScriptGraphTraversal}} has implemented steps and is ready to execute.

*plus* Translation is decoupled from {{DefaultGraphTraversal}} and thus, an 
entirely separate class space.
*minus* Every {{XXXTraversal}} will need to have a {{ScriptXXXTraversal}} 
implementation. For {{GraphTraversal}}, this was a copy/paste nightmare.
*minus* {{ScriptGraphTraversalSource}} is required and thus, this is NOT a 
{{TraversalStrategy}} but a new {{TraversalSource}} -- 
{{graph.traversal(PythonTranslator.of("g"))}}.

2. {{TranslationStrategy implements CreationStrategy}} 

In this model, there is a new type of {{TraversalStrategy}} called a 
{{CreationStrategy}} whose sort order comes before {{DecorationStrategy}}. 
Along with {{apply(traversal)}} method, creation strategies also have a 
{{addStep(stepName,stepArguments...)}} method as well as a {{getTranslator()}} 
method. This means that every {{GraphTraversal}} method has the following form:

{code}
public default GraphTraversal<S, Vertex> out(final String... edgeLabels) {
  TraversalHelper.addStepToCreationStrategies(this.asAdmin(), "out", 
edgeLabels);
  return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), Vertex.class, 
Direction.OUT, edgeLabels));
}
{code}

Finally, {{TranslationStrategy.apply()}} does like {{RemoteStrategy}} does and 
simple compiles the script and inserts the steps into the traversal.

*plus* {{CreationStrategy}} is like an interceptor and we could reuse this 
construct in other areas.
*minus* If you are doing translation, you are also constructing the traversals 
in the host language (wasted memory/clock cycles).
*minus* {{CreationStrategy}} is sorta like a {{TraversalStrategy}} but has more 
methods.
*plus* Everyone's implementation of {{XXXTraversal}} has all the machinery for 
translation. No need for a parallel {{ScriptXXXTraversal}} implementation to 
maintain.

3. {{Traversal.setTranslator(translator)}} 

If we make {{Translator}} core to {{Traversal}} then we would have the benefits 
of the two above without the drawbacks.

{code}
public default GraphTraversal<S, Vertex> out(final String... edgeLabels) {
  if(null != this.translator) {
    this.translator.addStep(this.asAdmin(), "out", edgeLabels);
    return this;
  } else
    return this.asAdmin().addStep(new VertexStep<>(this.asAdmin(), 
Vertex.class, Direction.OUT, edgeLabels));
}
{code}

*plus* You either translate or your construct -- no wasted memory/clock cycles.
*minus* {{Translator}} is now a "new concept" parallel with 
{{TraversalStrategies}} and {{TraversalSideEffects}}.

-----

Finally, I really do like {{CreationStrategy}}, but if we do it, then I think 
that instantiating steps and adding them to the traversal would actually be a 
{{CreationStrategy}}. For instance:

{code}
public default GraphTraversal<S, Vertex> out(final String... edgeLabels) {
  TraversalHelper.addStepToCreationStrategies(this.asAdmin(), "out", 
edgeLabels);
  return this;
}
{code}

That is, there would be a {{AddStepStrategy}} which would 
{{traversal.addStep(new VertexStep<>(this.asAdmin(), Vertex.class, 
Direction.OUT, edgeLabels))}}! If you wanted to translate only, then you would 
remote {{AddStepStrategy}} and add {{TranslationStrategy}}.... CraZy. The 
drawback of this is that {{AddStepStrategy}} would look something like this:

{code}
switch stepName
  case "out":
    traversal.addStep(new VertexStep<>(this.asAdmin(), Vertex.class, 
Direction.OUT, (String[]) args[0]));
    break;
  case "map":
    ...
  case "fold":
   ...
  case "groupCount":
   ...
{code}

> Implement Gremlin-Python and general purpose language variant test 
> infrastructure
> ---------------------------------------------------------------------------------
>
>                 Key: TINKERPOP-1278
>                 URL: https://issues.apache.org/jira/browse/TINKERPOP-1278
>             Project: TinkerPop
>          Issue Type: Improvement
>          Components: language-variant
>    Affects Versions: 3.2.0-incubating
>            Reporter: Marko A. Rodriguez
>            Assignee: Marko A. Rodriguez
>
> As discussed on dev@...
> Apache TinkerPop should provide, out-of-the-box, at least 3 Gremlin language 
> variants. It would be cool if these were:
> * Python (Mark Henderson)
> * PHP ([~PommeVerte])
> * Ruby (?[~okram])
> I think each of these should be generated using the reflection-model 
> presented in 
> http://tinkerpop.apache.org/docs/3.2.1-SNAPSHOT/tutorials/gremlin-language-variants/.
>  Moreover, on every {{mvn clean install}}, the code for these variants is 
> generated.
> Given the desire to separate language variants from language drivers, I think 
> that a language driver for each variant above should be "plugable." Moreover, 
> we should provide one driver implementation for each -- simple GremlinServer 
> REST.
> {code}
> gremlin-variants/
>   gremlin-ruby/
>     gremlin_ruby.rb
>     gremlin_ruby_rest_driver.rb
>   gremlin-php/
>     Gremlin_PHP.php
>     Gremlin_PHP_REST_Driver.php
>   gremlin-python/
>     gremlin-python.py
>     gremlin-python-rest-driver.py
> {code}
> Next, each variant implementation should be testable. This is PAINFUL if we 
> have to implement each {{g_V_out_repeatXasXaXX}} test case in 
> {{ProcessXXXSuite}}. Perhaps some RegEx transducer magic could be used to 
> convert all those tests from Gremlin-Java to the respective host language? 
> However, even if we do that, we still have the problem of how to test the 
> returned results. 
> I think what we should test the returned results using the JVM. For instance, 
> JRuby, Jython, JPHP (does it exist?). If we do this, we will save ourselves a 
> massive headache. All we have to do is create a {{GraphProvider}} that uses 
> {{TinkerGraph}} and whose {{TraversalSource}} is some sort of wrapper around 
> reflection-generated Ruby (e.g.).
> {code}
> g.V.out_e("knows") // returns a Ruby iterator
> {code}
> That Ruby iterator should be converted to a Java iterator and then the 
> {{ProcessXXXSuite}} can verify the results.
> With this, most everything is reflectively constructed.
> {code}
> gremlin_ruby.rb             // generated via Java reflection
> gremlin_ruby_rest_driver.rb // manually coded
> match_test.rb               // generated via RegEx transducer
> has_test.rb                 // generated via RegEx transducer
> ...
> RubyGraphProvider.java        // manually coded
> RubyProcessStandardSuite.java // manually coded
> RubyProcessComputerSuite.java // manually coded
> {code}
> Thus, the testing data flow would be:
> {code}
> MatchTest.Traversals.java --transducer-> match_test.rb
> match-test.rb --REST--> GremlinServer
> GremlinServer --GraphSON-->match-test.rb
> GraphSON --JRuby/GraphSONReader-->Java objects
> Java objects --JRuby-->MatchTest.java 
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to