TINKERPOP-1996 Introduce read() and write() steps
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/3641e910 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/3641e910 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/3641e910 Branch: refs/heads/TINKERPOP-1996 Commit: 3641e9106141cc52b4266ce0179637f1660ab680 Parents: 3852c87 Author: Stephen Mallette <sp...@genoprime.com> Authored: Fri Jun 29 15:04:17 2018 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Thu Jul 12 10:59:38 2018 -0400 ---------------------------------------------------------------------- .../traversal/dsl/graph/GraphTraversal.java | 2 + .../dsl/graph/GraphTraversalSource.java | 17 +++ .../process/traversal/step/map/ReadStep.java | 112 +++++++++++++++++++ .../process/traversal/step/map/WriteStep.java | 111 ++++++++++++++++++ .../strategy/verification/IoUsageStrategy.java | 60 ++++++++++ .../verification/IoUsageStrategyTest.java | 93 +++++++++++++++ .../glv/GraphTraversalSource.template | 4 +- gremlin-dotnet/glv/generate.groovy | 5 +- .../Process/Traversal/GraphTraversalSource.cs | 22 ++++ .../lib/process/graph-traversal.js | 20 ++++ .../gremlin_python/process/graph_traversal.py | 10 ++ 11 files changed, 452 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java ---------------------------------------------------------------------- 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 7d1e7e4..6d75745 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 @@ -2789,6 +2789,8 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> { public static final String skip = "skip"; public static final String tail = "tail"; public static final String coin = "coin"; + public static final String read = "read"; + public static final String write = "write"; public static final String timeLimit = "timeLimit"; public static final String simplePath = "simplePath"; http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalSource.java ---------------------------------------------------------------------- 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 bc3ef9e..9b82108 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 @@ -31,6 +31,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddEdgeStartStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.AddVertexStartStep; import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.WriteStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep; import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.RequirementsStrategy; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; @@ -40,6 +42,7 @@ import org.apache.tinkerpop.gremlin.structure.Transaction; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; +import java.util.Map; import java.util.Optional; import java.util.function.BinaryOperator; import java.util.function.Supplier; @@ -390,6 +393,20 @@ public class GraphTraversalSource implements TraversalSource { return traversal.addStep(new GraphStep<>(traversal, Edge.class, true, edgesIds)); } + public GraphTraversal<Map<String,Object>, Map<String,Object>> read(final String localFile) { + final GraphTraversalSource clone = this.clone(); + clone.bytecode.addStep(GraphTraversal.Symbols.read, localFile); + final GraphTraversal.Admin<Map<String,Object>, Map<String,Object>> traversal = new DefaultGraphTraversal<>(clone); + return traversal.addStep(new ReadStep(traversal, localFile)); + } + + public GraphTraversal<Map<String,Object>, Map<String,Object>> write(final String localFile) { + final GraphTraversalSource clone = this.clone(); + clone.bytecode.addStep(GraphTraversal.Symbols.write, localFile); + final GraphTraversal.Admin<Map<String,Object>, Map<String,Object>> traversal = new DefaultGraphTraversal<>(clone); + return traversal.addStep(new WriteStep(traversal, localFile)); + } + /** * Proxies calls through to the underlying {@link Graph#tx()}. */ http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadStep.java new file mode 100644 index 0000000..afc3e53 --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadStep.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tinkerpop.gremlin.process.traversal.step.map; + +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator; +import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters; +import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader; +import org.apache.tinkerpop.gremlin.structure.util.StringFactory; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Reads data from a file into a {@link Graph}. This step is meant to be used as the first and last step in a + * traversal. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class ReadStep extends AbstractStep<Map<String,Object>, Map<String,Object>> implements Configuring { + + private Parameters parameters = new Parameters(); + private boolean first = true; + private String localFile; + + public ReadStep(final Traversal.Admin traversal, final String localFile) { + super(traversal); + + if (null == localFile || localFile.isEmpty()) + throw new IllegalArgumentException("localFile cannot be null or empty"); + if (!new File(localFile).exists()) throw new IllegalStateException(localFile + " does not exist"); + + this.localFile = localFile; + } + + @Override + public Parameters getParameters() { + return this.parameters; + } + + @Override + public void configure(final Object... keyValues) { + this.parameters.set(null, keyValues); + } + + @Override + protected Traverser.Admin<Map<String,Object>> processNextStart() { + if (!this.first) throw FastNoSuchElementException.instance(); + + this.first = false; + final TraverserGenerator generator = this.getTraversal().getTraverserGenerator(); + final File file = new File(localFile); + + try (final InputStream stream = new FileInputStream(file)) { + final Graph graph = (Graph) this.traversal.getGraph().get(); + GryoReader.build().create().readGraph(stream, graph); + + final Map<String,Object> stats = new LinkedHashMap<>(); + stats.put("vertices", IteratorUtils.count(graph.vertices())); + stats.put("edges", IteratorUtils.count(graph.edges())); + + return generator.generate(stats, this, 1L); + } catch (IOException ioe) { + throw new IllegalStateException(String.format("Could not read file %s into graph", localFile), ioe); + } + } + + @Override + public int hashCode() { + final int hash = super.hashCode() ^ this.parameters.hashCode(); + return (null != this.localFile) ? (hash ^ localFile.hashCode()) : hash; + } + + @Override + public String toString() { + return StringFactory.stepString(this, localFile, this.parameters); + } + + @Override + public ReadStep clone() { + final ReadStep clone = (ReadStep) super.clone(); + clone.parameters = this.parameters.clone(); + clone.localFile = this.localFile; + return clone; + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/WriteStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/WriteStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/WriteStep.java new file mode 100644 index 0000000..e9346cf --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/WriteStep.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tinkerpop.gremlin.process.traversal.step.map; + +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator; +import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters; +import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoWriter; +import org.apache.tinkerpop.gremlin.structure.util.StringFactory; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Writes data to a file from a {@link Graph}. This step is meant to be used as the first and last step in a + * traversal. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class WriteStep extends AbstractStep<Map<String,Object>, Map<String,Object>> implements Configuring { + + private Parameters parameters = new Parameters(); + private boolean first = true; + private String localFile; + + public WriteStep(final Traversal.Admin traversal, final String localFile) { + super(traversal); + + if (null == localFile || localFile.isEmpty()) + throw new IllegalArgumentException("localFile cannot be null or empty"); + + this.localFile = localFile; + } + + @Override + public Parameters getParameters() { + return this.parameters; + } + + @Override + public void configure(final Object... keyValues) { + this.parameters.set(null, keyValues); + } + + @Override + protected Traverser.Admin<Map<String,Object>> processNextStart() { + if (!this.first) throw FastNoSuchElementException.instance(); + + this.first = false; + final TraverserGenerator generator = this.getTraversal().getTraverserGenerator(); + + final File file = new File(localFile); + try (final OutputStream stream = new FileOutputStream(file)) { + final Graph graph = (Graph) this.traversal.getGraph().get(); + GryoWriter.build().create().writeGraph(stream, graph); + + final Map<String, Object> stats = new LinkedHashMap<>(); + stats.put("vertices", IteratorUtils.count(graph.vertices())); + stats.put("edges", IteratorUtils.count(graph.edges())); + + return generator.generate(stats, this, 1L); + } catch (IOException ioe) { + throw new IllegalStateException(String.format("Could not write file %s from graph", localFile), ioe); + } + } + + @Override + public int hashCode() { + final int hash = super.hashCode() ^ this.parameters.hashCode(); + return (null != this.localFile) ? (hash ^ localFile.hashCode()) : hash; + } + + @Override + public String toString() { + return StringFactory.stepString(this, localFile, this.parameters); + } + + @Override + public WriteStep clone() { + final WriteStep clone = (WriteStep) super.clone(); + clone.parameters = this.parameters.clone(); + clone.localFile = this.localFile; + return clone; + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategy.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategy.java new file mode 100644 index 0000000..95761ff --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategy.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification; + +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.ReadStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.WriteStep; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy; + +/** + * {@code IoUsageStrategy} prevents the {@link GraphTraversalSource#read(String)} and + * {@link GraphTraversalSource#write(String)} steps from being used outside of their intended scope, which is as the + * first and last step in a traversal. Therefore, it can only be used as {@code g.read('file.gryo')} and + * {@code g.write('file.gryo')}. As both of these steps take additional configuration, the use of the + * {@link GraphTraversal#with(String, Object)} is acceptable. + * <p/> + * + * @author Stephen Mallette (http://stephen.genoprime.com) + * @example <pre> + * g.read('file.kryo').V() // throws VerificationException + * g.write('file.kryo').V() // throws VerificationException + * </pre> + */ +public final class IoUsageStrategy extends AbstractTraversalStrategy<TraversalStrategy.VerificationStrategy> implements TraversalStrategy.VerificationStrategy { + + private static final IoUsageStrategy INSTANCE = new IoUsageStrategy(); + + private IoUsageStrategy() { + } + + @Override + public void apply(final Traversal.Admin<?, ?> traversal) { + if ((traversal.getStartStep() instanceof ReadStep || traversal.getStartStep() instanceof WriteStep) && traversal.getSteps().size() > 1) { + throw new VerificationException("The read() or write() steps must be the first and only step in the traversal - they cannot be used with other steps", traversal); + } + } + + public static IoUsageStrategy instance() { + return INSTANCE; + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategyTest.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategyTest.java new file mode 100644 index 0000000..907e2b7 --- /dev/null +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategyTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tinkerpop.gremlin.process.traversal.strategy.verification; + +import org.apache.tinkerpop.gremlin.TestHelper; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies; +import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +@RunWith(Parameterized.class) +public class IoUsageStrategyTest { + + private static final GraphTraversalSource g = EmptyGraph.instance().traversal(); + + private static File junkFile; + + static { + try { + junkFile = TestHelper.generateTempFile(IoUsageStrategyTest.class, "fake", "kryo"); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + + @Parameterized.Parameters(name = "{0}") + public static Iterable<Object[]> data() { + return Arrays.asList(new Object[][]{ + {"g.read('a.kryo')", g.read(junkFile.getAbsolutePath()), true}, + {"g.write('a.kryo')", g.write(junkFile.getAbsolutePath()), true}, + {"g.read('a.kryo').with(\"x\", \"y\")", g.read(junkFile.getAbsolutePath()).with("x", "y"), true}, + {"g.write('a.kryo').with(\"x\", \"y\")", g.write(junkFile.getAbsolutePath()).with("x", "y"), true}, + {"g.read('a.kryo').V()", g.read(junkFile.getAbsolutePath()).V(), false}, + {"g.write('a.kryo').V()", g.write(junkFile.getAbsolutePath()).V(), false} + }); + } + + @Parameterized.Parameter(value = 0) + public String name; + + @Parameterized.Parameter(value = 1) + public Traversal traversal; + + @Parameterized.Parameter(value = 2) + public boolean allow; + + @Test + public void shouldBeVerified() { + final TraversalStrategies strategies = new DefaultTraversalStrategies(); + strategies.addStrategies(IoUsageStrategy.instance()); + traversal.asAdmin().setStrategies(strategies); + if (allow) { + traversal.asAdmin().applyStrategies(); + } else { + try { + traversal.asAdmin().applyStrategies(); + fail("The strategy should not allow read()/write() to be used with other steps: " + this.traversal); + } catch (VerificationException ise) { + assertTrue(ise.getMessage().contains("read() or write() steps")); + } + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-dotnet/glv/GraphTraversalSource.template ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/glv/GraphTraversalSource.template b/gremlin-dotnet/glv/GraphTraversalSource.template index afa4297..23d66e5 100644 --- a/gremlin-dotnet/glv/GraphTraversalSource.template +++ b/gremlin-dotnet/glv/GraphTraversalSource.template @@ -127,9 +127,9 @@ namespace Gremlin.Net.Process.Traversal /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the <%= method.methodName %> step to that /// traversal. /// </summary> - public GraphTraversal<$method.typeNameString> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.parameters %>) + public GraphTraversal<$method.t1, $method.t2> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.parameters %>) { - var traversal = new GraphTraversal<$method.typeNameString>(TraversalStrategies, new Bytecode(Bytecode)); + var traversal = new GraphTraversal<$method.t1, $method.t2>(TraversalStrategies, new Bytecode(Bytecode)); <% if (method.parameters.contains("params ")) { %>var args = new List<$method.argsListType>(<%= method.paramNames.init().size() %> + <%= method.paramNames.last() %>.Length) {<%= method.paramNames.init().join(", ") %>}; args.AddRange(<%= method.paramNames.last() %>); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-dotnet/glv/generate.groovy ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy index e542471..bd2d9d7 100644 --- a/gremlin-dotnet/glv/generate.groovy +++ b/gremlin-dotnet/glv/generate.groovy @@ -38,6 +38,7 @@ def toCSharpTypeMap = ["Long": "long", "Object[]": "object[]", "Class": "Type", "Class[]": "Type[]", + "java.util.Map<java.lang.String, java.lang.Object>": "IDictionary<string, object>", "java.util.Map<java.lang.String, E2>": "IDictionary<string, E2>", "java.util.Map<java.lang.String, B>": "IDictionary<string, E2>", "java.util.Map<java.lang.Object, E2>": "IDictionary<object, E2>", @@ -251,13 +252,13 @@ def binding = ["pmethods": P.class.getMethods(). unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }. collect { javaMethod -> def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod) - def typeNameString = typeNames.join(", ") + def t1 = toCSharpType(typeNames[0]) def t2 = toCSharpType(typeNames[1]) def tParam = getCSharpGenericTypeParam(t2) def parameters = getCSharpParamString(javaMethod, true) def paramNames = getParamNames(javaMethod.parameters) def argsListType = getArgsListType(parameters) - return ["methodName": javaMethod.name, "typeNameString": typeNameString, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "argsListType":argsListType] + return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "argsListType":argsListType] }, "graphStepMethods": GraphTraversal.getMethods(). findAll { GraphTraversal.class.equals(it.returnType) }. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs index 2816c05..630ac28 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs @@ -333,6 +333,28 @@ namespace Gremlin.Net.Process.Traversal return traversal; } + /// <summary> + /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the read step to that + /// traversal. + /// </summary> + public GraphTraversal<IDictionary<string, object>, IDictionary<string, object>> Read(string localFile) + { + var traversal = new GraphTraversal<IDictionary<string, object>, IDictionary<string, object>>(TraversalStrategies, new Bytecode(Bytecode)); + traversal.Bytecode.AddStep("read", localFile); + return traversal; + } + + /// <summary> + /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the write step to that + /// traversal. + /// </summary> + public GraphTraversal<IDictionary<string, object>, IDictionary<string, object>> Write(string localFile) + { + var traversal = new GraphTraversal<IDictionary<string, object>, IDictionary<string, object>>(TraversalStrategies, new Bytecode(Bytecode)); + traversal.Bytecode.AddStep("write", localFile); + return traversal; + } + } #pragma warning restore 1591 http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js ---------------------------------------------------------------------- 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 f143542..8fa51de 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 @@ -172,6 +172,26 @@ class GraphTraversalSource { return new GraphTraversal(this.graph, new TraversalStrategies(this.traversalStrategies), b); } + /** + * read GraphTraversalSource step method. + * @param {...Object} args + * @returns {GraphTraversal} + */ + read(...args) { + const b = new Bytecode(this.bytecode).addStep('read', args); + return new GraphTraversal(this.graph, new TraversalStrategies(this.traversalStrategies), b); + } + + /** + * write GraphTraversalSource step method. + * @param {...Object} args + * @returns {GraphTraversal} + */ + write(...args) { + const b = new Bytecode(this.bytecode).addStep('write', args); + return new GraphTraversal(this.graph, new TraversalStrategies(this.traversalStrategies), b); + } + } /** http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/3641e910/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py ---------------------------------------------------------------------- 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 bb81d87..e559613 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 @@ -106,6 +106,16 @@ class GraphTraversalSource(object): traversal.bytecode.add_step("inject", *args) return traversal + def read(self, *args): + traversal = self.get_graph_traversal() + traversal.bytecode.add_step("read", *args) + return traversal + + def write(self, *args): + traversal = self.get_graph_traversal() + traversal.bytecode.add_step("write", *args) + return traversal + class GraphTraversal(Traversal): def __init__(self, graph, traversal_strategies, bytecode):