You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/03/29 19:45:05 UTC

incubator-tinkerpop git commit: Added ProjectStep and GraphTraversal.project() which is like select(), but on the current traverser, not history data. As such, it does not require path-computations, though its by()-modulators are local children. Added te

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1237 [created] d90be26f1


Added ProjectStep and GraphTraversal.project() which is like select(), but on the current traverser, not history data. As such, it does not require path-computations, though its by()-modulators are local children. Added test cases and updated docs.


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

Branch: refs/heads/TINKERPOP-1237
Commit: d90be26f1625e376e93ce91adcff725de836a8e5
Parents: ce98e43
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Mar 29 11:44:52 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Mar 29 11:44:52 2016 -0600

----------------------------------------------------------------------
 docs/src/reference/the-traversal.asciidoc       |  18 ++++
 .../traversal/dsl/graph/GraphTraversal.java     |   8 ++
 .../gremlin/process/traversal/dsl/graph/__.java |   7 ++
 .../process/traversal/step/map/ProjectStep.java | 104 +++++++++++++++++++
 .../process/traversal/step/map/SelectStep.java  |   2 +-
 .../traversal/step/map/ProjectStepTest.java     |  47 +++++++++
 .../traversal/step/map/GroovyProjectTest.groovy |  42 ++++++++
 .../process/GroovyProcessComputerSuite.java     |   2 +
 .../process/GroovyProcessStandardSuite.java     |   2 +
 .../process/AbstractGremlinProcessTest.java     |   4 +-
 .../gremlin/process/ProcessComputerSuite.java   |   2 +
 .../gremlin/process/ProcessStandardSuite.java   |   6 ++
 .../process/traversal/step/map/ProjectTest.java |  82 +++++++++++++++
 .../structure/TinkerGraphPlayTest.java          |   7 +-
 14 files changed, 323 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index bcc7bf2..5f8d270 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1376,6 +1376,24 @@ metrics = t.getSideEffects().get('metrics')
 
 For traversal compilation information, please see <<explain-step,`explain()`>>-step.
 
+[[project-step]]
+Project Step
+~~~~~~~~~~~~
+
+The `project()`-step (*map*) projects labeled attributes of the current object into a `Map<String,Object>`. It is similar
+to <<select-step,`select()`>>-step, save that instead of retrieving and modulating historic traverser state, it modulates
+the current state of the traverser.
+
+[gremlin-groovy,modern]
+----
+g.V().out('created').
+           project('a",'b').
+             by('name').
+             by(__.in('created').count()).
+           order().by(select('b'),decr).
+           select('a')
+----
+
 [[range-step]]
 Range Step
 ~~~~~~~~~~

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/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 2ed3dd7..0a72819 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
@@ -93,6 +93,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyKeyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertyMapStep;
@@ -540,6 +541,13 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this.asAdmin().addStep(new LoopsStep<>(this.asAdmin()));
     }
 
+    public default <E2> GraphTraversal<S, Map<String, E2>> project(final String projectKey, final String... otherProjectKeys) {
+        final String[] projectKeys = new String[otherProjectKeys.length + 1];
+        projectKeys[0] = projectKey;
+        System.arraycopy(otherProjectKeys, 0, projectKeys, 1, otherProjectKeys.length);
+        return this.asAdmin().addStep(new ProjectStep<>(this.asAdmin(), projectKeys));
+    }
+
     /**
      * Map the {@link Traverser} to a {@link Map} projection of sideEffect values, map values, and/or path values.
      *

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index befae78..b5c2ea4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -269,6 +269,13 @@ public class __ {
     }
 
     /**
+     * @see GraphTraversal#project(String, String...)
+     */
+    public static <A, B> GraphTraversal<A, Map<String, B>> project(final String projectKey, final String... projectKeys) {
+        return __.<A>start().project(projectKey, projectKeys);
+    }
+
+    /**
      * @see GraphTraversal#select(Column)
      */
     public static <A, B> GraphTraversal<A, Collection<B>> select(final Column column) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
new file mode 100644
index 0000000..2e586b7
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
@@ -0,0 +1,104 @@
+/*
+ * 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.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class ProjectStep<S, E> extends MapStep<S, Map<String, E>> implements TraversalParent, ByModulating {
+
+    private final List<String> projectKeys;
+    private TraversalRing<S, E> traversalRing;
+
+    public ProjectStep(final Traversal.Admin traversal, final String... projectKeys) {
+        super(traversal);
+        this.projectKeys = Arrays.asList(projectKeys);
+        this.traversalRing = new TraversalRing<>();
+    }
+
+    @Override
+    protected Map<String, E> map(final Traverser.Admin<S> traverser) {
+        final Map<String, E> end = new LinkedHashMap<>(this.projectKeys.size(), 1.0f);
+        for (final String projectKey : this.projectKeys) {
+            end.put(projectKey, TraversalUtil.apply(traverser, this.traversalRing.next()));
+        }
+        this.traversalRing.reset();
+        return end;
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        this.traversalRing.reset();
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.projectKeys, this.traversalRing);
+    }
+
+    @Override
+    public ProjectStep<S, E> clone() {
+        final ProjectStep<S, E> clone = (ProjectStep<S, E>) super.clone();
+        clone.traversalRing = this.traversalRing.clone();
+        return clone;
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.traversalRing.getTraversals().forEach(this::integrateChild);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() ^ this.traversalRing.hashCode() ^ this.projectKeys.hashCode();
+    }
+
+    @Override
+    public List<Traversal.Admin<S, E>> getLocalChildren() {
+        return this.traversalRing.getTraversals();
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> selectTraversal) {
+        this.traversalRing.addTraversal(this.integrateChild(selectTraversal));
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index d7089da..af8cfdb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -61,7 +61,7 @@ public final class SelectStep<S, E> extends MapStep<S, Map<String, E>> implement
 
     @Override
     protected Map<String, E> map(final Traverser.Admin<S> traverser) {
-        final Map<String, E> bindings = new LinkedHashMap<>();
+        final Map<String, E> bindings = new LinkedHashMap<>(this.selectKeys.size(),1.0f);
         for (final String selectKey : this.selectKeys) {
             final E end = this.getNullableScopeValue(this.pop, selectKey, traverser);
             if (null != end)

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStepTest.java
new file mode 100644
index 0000000..fb63526
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStepTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class ProjectStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.project("x", "y"),
+                __.project("x"),
+                __.project("y"),
+                __.project("x", "y").by(__.outE().count()).by("name"),
+                __.project("x", "y").by("age").by("name"),
+                __.project("x", "y").by(__.outE().count()),
+                __.project("x").by(__.outE().count()),
+                __.project("y").by("name")
+        );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyProjectTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyProjectTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyProjectTest.groovy
new file mode 100644
index 0000000..c20867c
--- /dev/null
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyProjectTest.groovy
@@ -0,0 +1,42 @@
+/*
+ * 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.util.ScriptTraversal
+import org.apache.tinkerpop.gremlin.structure.Vertex
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class GroovyProjectTest {
+
+    public static class Traversals extends ProjectTest {
+        @Override
+        public Traversal<Vertex, Map<String, Number>> get_g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.hasLabel('person').project('a','b').by(outE().count).by('age')")
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__decrX_selectXaX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.out('created').project('a', 'b').by('name').by(__.in('created').count).order.by(select('b'),decr).select('a')")
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
index 496083f..df7e185 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessComputerSuite.java
@@ -61,6 +61,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPageRankTes
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPathTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPeerPressureTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyProfileTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyProjectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPropertiesTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovySelectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovySumTest;
@@ -146,6 +147,7 @@ public class GroovyProcessComputerSuite extends ProcessComputerSuite {
             GroovyPathTest.Traversals.class,
             GroovyPeerPressureTest.Traversals.class,
             GroovyProfileTest.Traversals.class,
+            GroovyProjectTest.Traversals.class,
             GroovyPropertiesTest.Traversals.class,
             GroovySelectTest.Traversals.class,
             GroovySumTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
index 870cb9a..fdb7d41 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/process/GroovyProcessStandardSuite.java
@@ -61,6 +61,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyMinTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyOrderTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPathTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyProfileTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyProjectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovyPropertiesTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovySelectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroovySumTest;
@@ -141,6 +142,7 @@ public class GroovyProcessStandardSuite extends ProcessStandardSuite {
             GroovyMinTest.Traversals.class,
             GroovyOrderTest.Traversals.class,
             GroovyProfileTest.Traversals.class,
+            GroovyProjectTest.Traversals.class,
             GroovyPathTest.Traversals.class,
             GroovyPropertiesTest.Traversals.class,
             GroovySelectTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
index 72e0f4e..0c0f19d 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/AbstractGremlinProcessTest.java
@@ -145,9 +145,7 @@ public abstract class AbstractGremlinProcessTest extends AbstractGremlinTest {
         final List<Map.Entry<A, B>> actualList = actualMap.entrySet().stream().sorted((a, b) -> a.getKey().toString().compareTo(b.getKey().toString())).collect(Collectors.toList());
         final List<Map.Entry<A, B>> expectedList = expectedMap.entrySet().stream().sorted((a, b) -> a.getKey().toString().compareTo(b.getKey().toString())).collect(Collectors.toList());
 
-        if (expectedList.size() > actualList.size()) {
-            return false;
-        } else if (actualList.size() > expectedList.size()) {
+        if (expectedList.size() != actualList.size()) {
             return false;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
index 82436c2..c3c3d02 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessComputerSuite.java
@@ -64,6 +64,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.PageRankTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PeerPressureTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProfileTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumTest;
@@ -154,6 +155,7 @@ public class ProcessComputerSuite extends AbstractGremlinSuite {
             PathTest.Traversals.class,
             PeerPressureTest.Traversals.class,
             ProfileTest.Traversals.class,
+            ProjectTest.Traversals.class,
             PropertiesTest.Traversals.class,
             SelectTest.Traversals.class,
             UnfoldTest.Traversals.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
index 7850c3f..15fa44b 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/ProcessStandardSuite.java
@@ -59,6 +59,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PathTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProfileTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.ProjectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.PropertiesTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumTest;
@@ -77,6 +79,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffect
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StoreTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphTest;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeTest;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategyProcessTest;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategyProcessTest;
@@ -147,6 +150,7 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
             OrderTest.Traversals.class,
             PathTest.Traversals.class,
             ProfileTest.Traversals.class,
+            ProjectTest.Traversals.class,
             PropertiesTest.Traversals.class,
             SelectTest.Traversals.class,
             VertexTest.Traversals.class,
@@ -225,6 +229,8 @@ public class ProcessStandardSuite extends AbstractGremlinSuite {
             OrderTest.class,
             PathTest.class,
             PropertiesTest.class,
+            ProfileStep.class,
+            ProjectStep.class,
             SelectTest.class,
             VertexTest.class,
             UnfoldTest.class,

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
new file mode 100644
index 0000000..3fd7ad3
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
+import org.apache.tinkerpop.gremlin.process.traversal.Order;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public abstract class ProjectTest extends AbstractGremlinProcessTest {
+
+    public abstract Traversal<Vertex, Map<String, Number>> get_g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX();
+
+    public abstract Traversal<Vertex, String> get_g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__decrX_selectXaX();
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX() {
+        final Traversal<Vertex, Map<String, Number>> traversal = get_g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX();
+        printTraversalForm(traversal);
+        checkResults(makeMapList(2,
+                "a", 3l, "b", 29,
+                "a", 0l, "b", 27,
+                "a", 2l, "b", 32,
+                "a", 1l, "b", 35), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__decrX_selectXaX() {
+        final Traversal<Vertex, String> traversal = get_g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__decrX_selectXaX();
+        printTraversalForm(traversal);
+        final List<String> names = traversal.toList();
+        assertEquals(4, names.size());
+        assertEquals("lop", names.get(0));
+        assertEquals("lop", names.get(1));
+        assertEquals("lop", names.get(2));
+        assertEquals("ripple", names.get(3));
+    }
+
+    public static class Traversals extends ProjectTest {
+
+        @Override
+        public Traversal<Vertex, Map<String, Number>> get_g_V_hasLabelXpersonX_projectXa_bX_byXoutE_countX_byXageX() {
+            return g.V().hasLabel("person").<Number>project("a", "b").by(__.outE().count()).by("age");
+        }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__decrX_selectXaX() {
+            return g.V().out("created").project("a", "b").by("name").by(__.in("created").count()).order().by(__.select("b"), Order.decr).select("a");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d90be26f/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 5b33552..7f2444b 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
@@ -70,12 +70,7 @@ public class TinkerGraphPlayTest {
         //System.out.println(g.V().outE("knows").identity().inV().count().is(P.eq(5)).explain());
         //System.out.println(g.V().hasLabel("person").fold().order(Scope.local).by("age").toList());
         //System.out.println(g.V().repeat(out()).times(2).profile("m").explain());
-        final Traversal<?, ?> traversal = g.V().<Vertex>match(
-                as("a").in("sungBy").as("b"),
-                as("a").in("writtenBy").as("c"),
-                as("b").out("writtenBy").as("d"))
-                .where(as("c").out("sungBy").as("d"))
-                .where(as("d").has("name", "Garcia"));
+        final Traversal<?, ?> traversal = g.V().hasLabel("person").<Number>project("a", "b").by(__.outE().count()).by("age");
         System.out.println(traversal.explain());
         //System.out.println(g.V().hasLabel("person").pageRank().by("rank").by(bothE()).values("rank").profile("m").explain());
         //System.out.println(traversal.asAdmin().clone().toString());