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 2018/07/12 15:00:30 UTC

[26/26] tinkerpop git commit: TINKERPOP-1996 Made read()/write() terminator steps

TINKERPOP-1996 Made read()/write() terminator steps

Without this approach the with() operator couldn't be used because the traversal would already be iterated on the call to read() and write(). In this way read() and write() are both terminators and modulators at the same time.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/2e6c1708
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/2e6c1708
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/2e6c1708

Branch: refs/heads/TINKERPOP-1996
Commit: 2e6c1708bc9526df6d3ac5af1657720d9702868e
Parents: f02daaf
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Jul 11 10:20:39 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jul 12 10:59:39 2018 -0400

----------------------------------------------------------------------
 .../decoration/VertexProgramStrategy.java       |   5 +-
 .../process/traversal/TraversalStrategies.java  |   2 -
 .../traversal/dsl/graph/GraphTraversal.java     |  34 +++++
 .../dsl/graph/GraphTraversalSource.java         |  19 +--
 .../process/traversal/step/ReadWriting.java     |  40 ++++++
 .../gremlin/process/traversal/step/Reading.java |  32 -----
 .../gremlin/process/traversal/step/Writing.java |  32 -----
 .../process/traversal/step/map/IoStep.java      | 135 +++++++++++++++++++
 .../process/traversal/step/map/ReadStep.java    | 113 ----------------
 .../process/traversal/step/map/WriteStep.java   | 111 ---------------
 .../strategy/verification/IoUsageStrategy.java  |  74 ----------
 .../decoration/VertexProgramStrategyTest.java   |   4 +-
 .../verification/IoUsageStrategyTest.java       |  93 -------------
 .../process/traversal/step/map/ReadTest.java    |   8 +-
 .../traversal/step/map/HadoopIoStep.java        | 110 +++++++++++++++
 .../traversal/step/map/HadoopReadStep.java      |  82 -----------
 .../traversal/step/map/HadoopWriteStep.java     |  82 -----------
 .../traversal/strategy/HadoopIoStrategy.java    |  30 ++---
 .../structure/TinkerGraphPlayTest.java          |   2 +-
 19 files changed, 343 insertions(+), 665 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
index c83039a..cb99652 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/decoration/VertexProgramStrategy.java
@@ -34,8 +34,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Reading;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
@@ -102,7 +101,7 @@ public final class VertexProgramStrategy extends AbstractTraversalStrategy<Trave
 
         // wrap all non-VertexComputing steps into a TraversalVertexProgramStep
         currentStep = traversal.getStartStep();
-        if (!(currentStep instanceof Reading) && !(currentStep instanceof Writing)) {
+        if (!(currentStep instanceof ReadWriting)) {
             while (!(currentStep instanceof EmptyStep)) {
                 final Traversal.Admin<?, ?> computerTraversal = new DefaultTraversal<>();
                 final Step<?, ?> firstLegalOLAPStep = getFirstLegalOLAPStep(currentStep);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 66b0236..ef3e841 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -36,7 +36,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Path
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.IoUsageStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -223,7 +222,6 @@ public interface TraversalStrategies extends Serializable, Cloneable {
                     PathRetractionStrategy.instance(),
                     LazyBarrierStrategy.instance(),
                     ProfileStrategy.instance(),
-                    IoUsageStrategy.instance(),
                     StandardVerificationStrategy.instance());
             GRAPH_CACHE.put(Graph.class, graphStrategies);
             GRAPH_CACHE.put(EmptyGraph.class, new DefaultTraversalStrategies());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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 6d75745..a7d420a 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
@@ -39,6 +39,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Configuring;
 import org.apache.tinkerpop.gremlin.process.traversal.step.FromToModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Mutating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TimesModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.branch.BranchStep;
@@ -2705,6 +2706,38 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
 
     ////
 
+    ///////////////////// IO TERMINATOR STEPS /////////////////////
+
+    /**
+     * This step is technically a step modulator for the the {@link GraphTraversalSource#io(String)} step which
+     * instructs the step to perform a read with its given configuration.
+     *
+     * @return the traversal that has been iterated with the read IO action executed
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#io-step" target="_blank">Reference Documentation - IO Step</a>
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#read-step" target="_blank">Reference Documentation - Read Step</a>
+     * @since 3.4.0
+     */
+    public default GraphTraversal<S,E> read() {
+        this.asAdmin().getBytecode().addStep(Symbols.read);
+        ((ReadWriting) this.asAdmin().getEndStep()).setMode(ReadWriting.Mode.READING);
+        return this.iterate();
+    }
+
+    /**
+     * This step is technically a step modulator for the the {@link GraphTraversalSource#io(String)} step which
+     * instructs the step to perform a write with its given configuration.
+     *
+     * @return the traversal that has been iterated with the write IO action executed
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#io-step" target="_blank">Reference Documentation - IO Step</a>
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#write-step" target="_blank">Reference Documentation - Write Step</a>
+     * @since 3.4.0
+     */
+    public default GraphTraversal<S,E> write() {
+        this.asAdmin().getBytecode().addStep(Symbols.write);
+        ((ReadWriting) this.asAdmin().getEndStep()).setMode(ReadWriting.Mode.WRITING);
+        return this.iterate();
+    }
+
     /**
      * Iterates the traversal presumably for the generation of side-effects.
      */
@@ -2789,6 +2822,7 @@ 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 io = "io";
         public static final String read = "read";
         public static final String write = "write";
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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 49e012f..aa4995d 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
@@ -24,7 +24,6 @@ import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.strategy.decoration.RemoteStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
@@ -32,8 +31,7 @@ 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.map.IoStep;
 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;
@@ -43,8 +41,6 @@ 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.NoSuchElementException;
 import java.util.Optional;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
@@ -395,18 +391,11 @@ public class GraphTraversalSource implements TraversalSource {
         return traversal.addStep(new GraphStep<>(traversal, Edge.class, true, edgesIds));
     }
 
-    public <S> GraphTraversal<S, S> read(final String file) {
+    public <S> GraphTraversal<S, S> io(final String file) {
         final GraphTraversalSource clone = this.clone();
-        clone.bytecode.addStep(GraphTraversal.Symbols.read, file);
+        clone.bytecode.addStep(GraphTraversal.Symbols.io, file);
         final GraphTraversal.Admin<S,S> traversal = new DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new ReadStep<S>(traversal, file)).iterate();
-    }
-
-    public <S> GraphTraversal<S, S> write(final String file) {
-        final GraphTraversalSource clone = this.clone();
-        clone.bytecode.addStep(GraphTraversal.Symbols.write, file);
-        final GraphTraversal.Admin<S,S> traversal = new DefaultGraphTraversal<>(clone);
-        return traversal.addStep(new WriteStep<S>(traversal, file)).iterate();
+        return traversal.addStep(new IoStep<S>(traversal, file));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadWriting.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadWriting.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadWriting.java
new file mode 100644
index 0000000..18de925
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/ReadWriting.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface ReadWriting extends Configuring {
+
+    public enum Mode {
+        UNSET,
+        READING,
+        WRITING
+    }
+
+    /**
+     * Get the file location to write to.
+     */
+    public String getFile();
+
+    public void setMode(final Mode mode);
+
+    public Mode getMode();
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Reading.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Reading.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Reading.java
deleted file mode 100644
index 3f7c714..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Reading.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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;
-
-/**
- * An interface for describing steps that will read a graph from some specified location.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public interface Reading extends Configuring {
-
-    /**
-     * Get the file location to read from.
-     */
-    public String getFile();
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Writing.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Writing.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Writing.java
deleted file mode 100644
index fe56363..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Writing.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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;
-
-/**
- * An interface for describing steps that will write a graph to some specified location.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public interface Writing extends Configuring {
-
-    /**
-     * Get the file location to write to.
-     */
-    public String getFile();
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IoStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IoStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IoStep.java
new file mode 100644
index 0000000..8d22427
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IoStep.java
@@ -0,0 +1,135 @@
+/*
+ * 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.step.ReadWriting;
+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.traverser.util.EmptyTraverser;
+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.io.gryo.GryoWriter;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class IoStep<S> extends AbstractStep<S,S> implements ReadWriting {
+    private Parameters parameters = new Parameters();
+    private boolean first = true;
+    private String file;
+    private Mode mode = Mode.UNSET;
+
+    public IoStep(final Traversal.Admin traversal, final String file) {
+        super(traversal);
+
+        if (null == file || file.isEmpty())
+            throw new IllegalArgumentException("file cannot be null or empty");
+
+        this.file = file;
+    }
+
+    @Override
+    public void setMode(final Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public Mode getMode() {
+        return mode;
+    }
+
+    @Override
+    public String getFile() {
+        return file;
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return this.parameters;
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        this.parameters.set(null, keyValues);
+    }
+
+    @Override
+    protected Traverser.Admin<S> processNextStart() {
+        if (mode == Mode.UNSET) throw new IllegalStateException("IO mode was not set to read() or write()");
+        if (!this.first) throw FastNoSuchElementException.instance();
+
+        this.first = false;
+        final File file = new File(this.file);
+
+        if (mode == Mode.READING) {
+            if (!file.exists()) throw new IllegalStateException(this.file + " does not exist");
+
+            try (final InputStream stream = new FileInputStream(file)) {
+                final Graph graph = (Graph) this.traversal.getGraph().get();
+                GryoReader.build().create().readGraph(stream, graph);
+
+                return EmptyTraverser.instance();
+            } catch (IOException ioe) {
+                throw new IllegalStateException(String.format("Could not read file %s into graph", this.file), ioe);
+            }
+        } else if (mode == Mode.WRITING) {
+            try (final OutputStream stream = new FileOutputStream(file)) {
+                final Graph graph = (Graph) this.traversal.getGraph().get();
+                GryoWriter.build().create().writeGraph(stream, graph);
+
+                return EmptyTraverser.instance();
+            } catch (IOException ioe) {
+                throw new IllegalStateException(String.format("Could not write file %s from graph", this.file), ioe);
+            }
+        } else {
+            throw new IllegalStateException("Invalid ReadWriting.Mode configured in IoStep: " + mode.name());
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int hash = super.hashCode() ^ this.parameters.hashCode();
+        return (null != this.file) ? (hash ^ file.hashCode()) : hash;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, file, this.parameters);
+    }
+
+    @Override
+    public IoStep clone() {
+        final IoStep clone = (IoStep) super.clone();
+        clone.parameters = this.parameters.clone();
+        clone.file = this.file;
+        clone.mode = this.mode;
+        return clone;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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
deleted file mode 100644
index 99f7e66..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadStep.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.Reading;
-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.traverser.util.EmptyTraverser;
-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<S> extends AbstractStep<S,S> implements Reading {
-
-    private Parameters parameters = new Parameters();
-    private boolean first = true;
-    private String file;
-
-    public ReadStep(final Traversal.Admin traversal, final String file) {
-        super(traversal);
-
-        if (null == file || file.isEmpty())
-            throw new IllegalArgumentException("file cannot be null or empty");
-
-        this.file = file;
-    }
-
-    @Override
-    public String getFile() {
-        return file;
-    }
-
-    @Override
-    public Parameters getParameters() {
-        return this.parameters;
-    }
-
-    @Override
-    public void configure(final Object... keyValues) {
-        this.parameters.set(null, keyValues);
-    }
-
-    @Override
-    protected Traverser.Admin<S> processNextStart() {
-        if (!this.first) throw FastNoSuchElementException.instance();
-
-        this.first = false;
-        final File file = new File(this.file);
-        if (!file.exists()) throw new IllegalStateException(this.file + " does not exist");
-
-        try (final InputStream stream = new FileInputStream(file)) {
-            final Graph graph = (Graph) this.traversal.getGraph().get();
-            GryoReader.build().create().readGraph(stream, graph);
-
-            return EmptyTraverser.instance();
-        } catch (IOException ioe) {
-            throw new IllegalStateException(String.format("Could not read file %s into graph", this.file), ioe);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int hash = super.hashCode() ^ this.parameters.hashCode();
-        return (null != this.file) ? (hash ^ file.hashCode()) : hash;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, file, this.parameters);
-    }
-
-    @Override
-    public ReadStep clone() {
-        final ReadStep clone = (ReadStep) super.clone();
-        clone.parameters = this.parameters.clone();
-        clone.file = this.file;
-        return clone;
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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
deleted file mode 100644
index 20ffec9..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/WriteStep.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.Writing;
-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.traverser.util.EmptyTraverser;
-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<S> extends AbstractStep<S,S> implements Writing {
-
-    private Parameters parameters = new Parameters();
-    private boolean first = true;
-    private String file;
-
-    public WriteStep(final Traversal.Admin traversal, final String file) {
-        super(traversal);
-
-        if (null == file || file.isEmpty())
-            throw new IllegalArgumentException("file cannot be null or empty");
-
-        this.file = file;
-    }
-
-    @Override
-    public String getFile() {
-        return file;
-    }
-
-    @Override
-    public Parameters getParameters() {
-        return this.parameters;
-    }
-
-    @Override
-    public void configure(final Object... keyValues) {
-        this.parameters.set(null, keyValues);
-    }
-
-    @Override
-    protected Traverser.Admin<S> processNextStart() {
-        if (!this.first) throw FastNoSuchElementException.instance();
-
-        this.first = false;
-        final File file = new File(this.file);
-        try (final OutputStream stream = new FileOutputStream(file)) {
-            final Graph graph = (Graph) this.traversal.getGraph().get();
-            GryoWriter.build().create().writeGraph(stream, graph);
-
-            return EmptyTraverser.instance();
-        } catch (IOException ioe) {
-            throw new IllegalStateException(String.format("Could not write file %s from graph", this.file), ioe);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int hash = super.hashCode() ^ this.parameters.hashCode();
-        return (null != this.file) ? (hash ^ file.hashCode()) : hash;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, file, this.parameters);
-    }
-
-    @Override
-    public WriteStep clone() {
-        final WriteStep clone = (WriteStep) super.clone();
-        clone.parameters = this.parameters.clone();
-        clone.file = this.file;
-        return clone;
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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
deleted file mode 100644
index b4a0669..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategy.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.Step;
-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.filter.NoneStep;
-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;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * {@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) {
-        final Step start = traversal.getStartStep();
-        final Step end = traversal.getEndStep();
-        if ((start instanceof ReadStep || start instanceof WriteStep) && end != start) {
-            if ((end instanceof NoneStep && traversal.getSteps().size() > 2)) {
-                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;
-    }
-
-    @Override
-    public Set<Class<? extends VerificationStrategy>> applyPrior() {
-        return Collections.singleton(ComputerVerificationStrategy.class);
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/VertexProgramStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/VertexProgramStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/VertexProgramStrategyTest.java
index 71cb22d..972db9a 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/VertexProgramStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/VertexProgramStrategyTest.java
@@ -69,8 +69,8 @@ public class VertexProgramStrategyTest {
         final ComputerResultStep computerResultStep = new ComputerResultStep(EmptyTraversal.instance());
 
         return Arrays.asList(new Traversal[][]{
-                { EmptyGraph.instance().traversal().read("blah.json"), EmptyGraph.instance().traversal().read("blah.json")},
-                { EmptyGraph.instance().traversal().write("blah.json"), EmptyGraph.instance().traversal().write("blah.json")},
+                { EmptyGraph.instance().traversal().io("blah.json").read(), EmptyGraph.instance().traversal().io("blah.json").read()},
+                { EmptyGraph.instance().traversal().io("blah.json").write(), EmptyGraph.instance().traversal().io("blah.json").write()},
                 {__.V().out().count(), start().addStep(traversal(__.V().out().count())).addStep(computerResultStep)},
                 {__.V().pageRank().out().count(), start().pageRank().asAdmin().addStep(traversal(__.V().out().count())).addStep(computerResultStep)},
                 {__.V().out().pageRank(), start().addStep(traversal(__.V().out())).pageRank().asAdmin().addStep(traversal(__.identity())).addStep(computerResultStep)},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/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
deleted file mode 100644
index 907e2b7..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/verification/IoUsageStrategyTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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/2e6c1708/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
index 2cfc3f7..6b7b67e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ReadTest.java
@@ -43,11 +43,11 @@ import static org.junit.Assert.assertTrue;
 @RunWith(GremlinProcessRunner.class)
 public abstract class ReadTest extends AbstractGremlinProcessTest {
 
-    public abstract Traversal<Map<String,Object>, Map<String,Object>> get_g_read()  throws IOException;
+    public abstract Traversal<Object,Object> get_g_io_read()  throws IOException;
 
     @Test
     public void g_read() throws IOException {
-        final Traversal<Map<String,Object>, Map<String,Object>> traversal = get_g_read();
+        final Traversal<Object,Object> traversal = get_g_io_read();
         printTraversalForm(traversal);
         assertTrue(traversal.hasNext());
 
@@ -56,9 +56,9 @@ public abstract class ReadTest extends AbstractGremlinProcessTest {
 
     public static class Traversals extends ReadTest {
         @Override
-        public Traversal<Map<String,Object>, Map<String,Object>> get_g_read() throws IOException {
+        public Traversal<Object,Object> get_g_io_read() throws IOException {
             final String fileToRead = TestHelper.generateTempFileFromResource(ReadTest.class, GryoResourceAccess.class, "tinkerpop-modern-v3d0.kryo", "").getAbsolutePath().replace('\\', '/');
-            return g.read(fileToRead);
+            return g.io(fileToRead).read();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopIoStep.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopIoStep.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopIoStep.java
new file mode 100644
index 0000000..83a95e0
--- /dev/null
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopIoStep.java
@@ -0,0 +1,110 @@
+/*
+ * 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.hadoop.process.computer.traversal.step.map;
+
+import org.apache.tinkerpop.gremlin.hadoop.Constants;
+import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
+import org.apache.tinkerpop.gremlin.process.computer.Memory;
+import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.VertexProgramStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class HadoopIoStep extends VertexProgramStep implements ReadWriting {
+
+    private Parameters parameters = new Parameters();
+    private Mode mode = Mode.UNSET;
+    private String file;
+
+    public HadoopIoStep(final Traversal.Admin traversal, final String file) {
+        super(traversal);
+        this.file = file;
+    }
+
+    @Override
+    public void setMode(final Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public Mode getMode() {
+        return mode;
+    }
+
+    @Override
+    public String getFile() {
+        return file;
+    }
+
+    @Override
+    public void configure(final Object... keyValues) {
+        // TODO: probably should write to the Configuration selectively - no need for actual Parameters?????????
+        this.parameters.set(null, keyValues);
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return parameters;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, new GraphFilter(this.computer));
+    }
+
+    @Override
+    public CloneVertexProgram generateProgram(final Graph graph, final Memory memory) {
+        if (mode == Mode.UNSET)
+            throw new IllegalStateException("IO mode was not set to read() or write()");
+        else if (mode == Mode.READING)
+            configureForRead(graph);
+        else if (mode == Mode.WRITING)
+            configureForWrite(graph);
+        else
+            throw new IllegalStateException("Invalid ReadWriting.Mode configured in IoStep: " + mode.name());
+
+        return CloneVertexProgram.build().create(graph);
+    }
+
+    @Override
+    public HadoopIoStep clone() {
+        return (HadoopIoStep) super.clone();
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    private void configureForRead(final Graph graph) {
+        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_GRAPH_READER, "org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat");
+        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION, file);
+    }
+
+    private void configureForWrite(final Graph graph) {
+        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_GRAPH_WRITER, "org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoOutputFormat");
+        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, file);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopReadStep.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopReadStep.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopReadStep.java
deleted file mode 100644
index 1ec3d38..0000000
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopReadStep.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.hadoop.process.computer.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.hadoop.Constants;
-import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
-import org.apache.tinkerpop.gremlin.process.computer.Memory;
-import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.VertexProgramStep;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Reading;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class HadoopReadStep extends VertexProgramStep implements Reading {
-
-    private Parameters parameters = new Parameters();
-
-    public HadoopReadStep(final Traversal.Admin traversal, final String localFile) {
-        super(traversal);
-
-        final Graph graph = (Graph) traversal.getGraph().get();
-        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_GRAPH_READER, "org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoInputFormat");
-        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION, localFile);
-    }
-
-    @Override
-    public String getFile() {
-        return (String) ((Graph) traversal.getGraph().get()).configuration().getProperty(Constants.GREMLIN_HADOOP_INPUT_LOCATION);
-    }
-
-    @Override
-    public void configure(final Object... keyValues) {
-        // TODO: probably should write to the Configuration selectively - no need for actual Parameters?????????
-        this.parameters.set(null, keyValues);
-    }
-
-    @Override
-    public Parameters getParameters() {
-        return parameters;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, new GraphFilter(this.computer));
-    }
-
-    @Override
-    public CloneVertexProgram generateProgram(final Graph graph, final Memory memory) {
-        return CloneVertexProgram.build().create(graph);
-    }
-
-    @Override
-    public HadoopReadStep clone() {
-        return (HadoopReadStep) super.clone();
-    }
-
-    @Override
-    public int hashCode() {
-        return super.hashCode();
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopWriteStep.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopWriteStep.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopWriteStep.java
deleted file mode 100644
index 2bb8e67..0000000
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/step/map/HadoopWriteStep.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.hadoop.process.computer.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.hadoop.Constants;
-import org.apache.tinkerpop.gremlin.process.computer.GraphFilter;
-import org.apache.tinkerpop.gremlin.process.computer.Memory;
-import org.apache.tinkerpop.gremlin.process.computer.clone.CloneVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.VertexProgramStep;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Reading;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public class HadoopWriteStep extends VertexProgramStep implements Reading {
-
-    private Parameters parameters = new Parameters();
-
-    public HadoopWriteStep(final Traversal.Admin traversal, final String localFile) {
-        super(traversal);
-
-        final Graph graph = (Graph) traversal.getGraph().get();
-        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_GRAPH_WRITER, "org.apache.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoOutputFormat");
-        graph.configuration().setProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION, localFile);
-    }
-
-    @Override
-    public String getFile() {
-        return (String) ((Graph) traversal.getGraph().get()).configuration().getProperty(Constants.GREMLIN_HADOOP_OUTPUT_LOCATION);
-    }
-
-    @Override
-    public void configure(final Object... keyValues) {
-        // TODO: probably should write to the Configuration selectively - no need for actual Parameters?????????
-        this.parameters.set(null, keyValues);
-    }
-
-    @Override
-    public Parameters getParameters() {
-        return parameters;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, new GraphFilter(this.computer));
-    }
-
-    @Override
-    public CloneVertexProgram generateProgram(final Graph graph, final Memory memory) {
-        return CloneVertexProgram.build().create(graph);
-    }
-
-    @Override
-    public HadoopWriteStep clone() {
-        return (HadoopWriteStep) super.clone();
-    }
-
-    @Override
-    public int hashCode() {
-        return super.hashCode();
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/strategy/HadoopIoStrategy.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/strategy/HadoopIoStrategy.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/strategy/HadoopIoStrategy.java
index 7e0e23c..1805df8 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/strategy/HadoopIoStrategy.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/process/computer/traversal/strategy/HadoopIoStrategy.java
@@ -19,14 +19,13 @@
 
 package org.apache.tinkerpop.gremlin.hadoop.process.computer.traversal.strategy;
 
-import org.apache.tinkerpop.gremlin.hadoop.process.computer.traversal.step.map.HadoopReadStep;
-import org.apache.tinkerpop.gremlin.hadoop.process.computer.traversal.step.map.HadoopWriteStep;
+import org.apache.tinkerpop.gremlin.hadoop.process.computer.traversal.step.map.HadoopIoStep;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Reading;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Writing;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ReadWriting;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.IoStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
@@ -43,23 +42,16 @@ public final class HadoopIoStrategy extends AbstractTraversalStrategy<TraversalS
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        // replace Reading and Writing steps with hadoop specific ones
-        if (traversal.getStartStep() instanceof Reading) {
-            final Reading reading = (Reading) traversal.getStartStep();
-            final HadoopReadStep hadoopReadStep = new HadoopReadStep(traversal, reading.getFile());
-            reading.getParameters().getRaw().entrySet().forEach(kv ->
-                hadoopReadStep.configure(null, kv.getKey(), kv.getValue())
+        // replace IoStep steps with hadoop specific one
+        if (traversal.getStartStep() instanceof IoStep) {
+            final ReadWriting readWriting = (ReadWriting) traversal.getStartStep();
+            final HadoopIoStep hadoopIoStep = new HadoopIoStep(traversal, readWriting.getFile());
+            hadoopIoStep.setMode(readWriting.getMode());
+            readWriting.getParameters().getRaw().entrySet().forEach(kv ->
+                    hadoopIoStep.configure(null, kv.getKey(), kv.getValue())
             );
 
-            TraversalHelper.replaceStep((Step) reading, hadoopReadStep, traversal);
-        } else if (traversal.getStartStep() instanceof Writing) {
-            final Writing writing = (Writing) traversal.getStartStep();
-            final HadoopWriteStep hadoopWriteStep = new HadoopWriteStep(traversal, writing.getFile());
-            writing.getParameters().getRaw().entrySet().forEach(kv ->
-                hadoopWriteStep.configure(null, kv.getKey(), kv.getValue())
-            );
-
-            TraversalHelper.replaceStep((Step) writing, hadoopWriteStep, traversal);
+            TraversalHelper.replaceStep((Step) readWriting, hadoopIoStep, traversal);
         }
 
         if (traversal.getEndStep() instanceof NoneStep)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/2e6c1708/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index 82bf2d7..69062ef 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -340,7 +340,7 @@ public class TinkerGraphPlayTest {
     public void testBlah() {
         TinkerGraph graph = TinkerGraph.open();
         GraphTraversalSource g = graph.traversal();
-        g.read("../data/tinkerpop-modern.kryo");
+        g.io("../data/tinkerpop-modern.kryo").read();
 
         IoTest.assertModernGraph(graph, true, false);
     }