You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2018/04/25 23:56:27 UTC

[1/2] tinkerpop git commit: TINKERPOP-1628 Implemented TraversalSelectStep

Repository: tinkerpop
Updated Branches:
  refs/heads/tp33 edaabb441 -> 4eeb17804


TINKERPOP-1628 Implemented TraversalSelectStep


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

Branch: refs/heads/tp33
Commit: c135da6ee3d428c633ddf8a11c6faecc92848c08
Parents: 8005cb3
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Thu Apr 19 18:06:02 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Wed Apr 25 16:19:21 2018 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 docs/src/recipes/shortest-path.asciidoc         |  39 +++++
 docs/src/reference/the-traversal.asciidoc       |  18 +++
 .../traversal/dsl/graph/GraphTraversal.java     |  30 ++++
 .../gremlin/process/traversal/dsl/graph/__.java |  14 ++
 .../traversal/step/map/TraversalSelectStep.java | 157 +++++++++++++++++++
 .../Process/Traversal/GraphTraversal.cs         |  18 +++
 .../src/Gremlin.Net/Process/Traversal/__.cs     |  16 ++
 gremlin-test/features/map/Select.feature        |  46 +++++-
 .../process/AbstractGremlinProcessTest.java     |  14 ++
 .../process/traversal/step/map/SelectTest.java  |  48 ++++++
 .../structure/TinkerGraphPlayTest.java          | 114 +++++++++++---
 12 files changed, 492 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index aead6ef..ab20fff 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 This release also includes changes from <<release-3-2-9, 3.2.9>>.
 
+* Implemented `TraversalSelectStep` which allows to `select()` runtime-generated keys.
 * Coerced `BulkSet` to `g:List` in GraphSON 3.0.
 * Deprecated `CredentialsGraph` DSL in favor of `CredentialsTraversalDsl` which uses the recommended method for Gremlin DSL development.
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/docs/src/recipes/shortest-path.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/recipes/shortest-path.asciidoc b/docs/src/recipes/shortest-path.asciidoc
index 04301f1..2e33055 100644
--- a/docs/src/recipes/shortest-path.asciidoc
+++ b/docs/src/recipes/shortest-path.asciidoc
@@ -95,5 +95,44 @@ calculated cost. With some slight modifications given the use of `select` it bec
 the output. Note that the path with the lowest "cost" actually has a longer path length as determined by the graph
 structure.
 
+The following query illustrates how `select(<traversal>)` can be used to find all shortest weighted undirected paths
+in the modern toy graph.
 
+[gremlin-groovy,modern]
+----
+g.withSack(0.0).V().as("from").       <1>
+  repeat(bothE().
+         sack(sum).
+           by("weight").
+         otherV().                    <2>
+         where(neq("from")).as("to"). <3>
+         group("m").                  <4>
+           by(select("from","to")).
+           by(sack().min()).
+         filter(project("s","x").     <5>
+                  by(sack()).
+                  by(select("m").select(select("from","to"))).
+                where("s", eq("x"))).
+         group("p").                  <6>
+           by(select("from", "to")).
+           by(map(union(path().by("name").by("weight"),
+                        sack()).fold())).
+         barrier()).
+  cap("p").unfold().
+  order().                            <7>
+    by(select(keys).select("from").id()).
+    by(select(keys).select("to").id()).
+  barrier().
+  dedup().                            <8>
+    by(select(keys).select(values).order(local).by(id))
+----
+
+<1> Start the traversal from all vertices with an initial sack value of 0.
+<2> Traverse into all directions and sum up the edge weight values.
+<3> Filter out the initial start vertex.
+<4> For the current start and end vertex, update the minimum sack value (weighted length of the path).
+<5> Compare the current weighted path length to the current minimum weighted path length between the 2 vertices. Eliminate traversers that found a path that is longer than the current shortest path.
+<6> Update the path and weighted path length for the current start and end vertex pair.
+<7> Order the output by the start vertex id and then the end vertex id (for better readability).
+<8> Deduplicate vertex pairs (the shortest path from `v[1]` to `v[6]` is the same as the path from `v[6]` to `v[1]`).
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index dcda556..11f24e4 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2338,6 +2338,22 @@ g.V(1).as("a").repeat(out().as("a")).times(2).select(last, "a")
 g.V(1).as("a").repeat(out().as("a")).times(2).select(all, "a")
 ----
 
+In addition to the previously shown examples, where `select()` was used to select an element based on a static key, `select()` can also accept a traversal
+that emits a key.
+
+WARNING: Since the key used by `select(<traversal>)` cannot be determined at compile time, the `TraversalSelectStep` enables full path tracking.
+
+[gremlin-groovy,modern]
+----
+g.withSideEffect("alias", ["marko":"okram"]).V().  <1>
+  values("name").sack(assign).                     <2>
+  optional(select("alias").select(sack()))         <3>
+----
+
+<1> Inject a name alias map and start the traversal from all vertices.
+<2> Select all `name` values and store them as the current traverser's sack value.
+<3> Optionally select the alias for the current name from the injected map.
+
 [[using-where-with-select]]
 ==== Using Where with Select
 
@@ -2369,6 +2385,8 @@ link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/grem
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#select-org.apache.tinkerpop.gremlin.process.traversal.Pop-java.lang.String-++[`select(Pop,String)`],
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#select-java.lang.String-++[`select(String)`],
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#select-java.lang.String-java.lang.String-java.lang.String...-++[`select(String,String,String...)`],
+link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#select-org.apache.tinkerpop.gremlin.process.traversal.Traversal-++[`select(Traversal)`],
+link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#select-org.apache.tinkerpop.gremlin.process.traversal.Pop-org.apache.tinkerpop.gremlin.process.traversal.Traversal-++[`select(Pop,Traversal)`],
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/Column.html++[`Column`],
 link:++http://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/Pop.html++[`Pop`]
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/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 a10ddb2..afc0bb4 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
@@ -112,6 +112,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TailLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
@@ -734,6 +735,35 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     /**
+     * Map the {@link Traverser} to the object specified by the key returned by the {@code keyTraversal} and apply the {@link Pop} operation
+     * to it.
+     *
+     * @param keyTraversal the traversal expression that selects the key to project
+     * @return the traversal with an appended {@link SelectStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#select-step" target="_blank">Reference Documentation - Select Step</a>
+     * @since 3.3.3
+     */
+    public default <E2> GraphTraversal<S, E2> select(final Pop pop, final Traversal<S, E2> keyTraversal) {
+        this.asAdmin().getBytecode().addStep(Symbols.select, pop, keyTraversal);
+        return this.asAdmin().addStep(new TraversalSelectStep<>(this.asAdmin(), pop, keyTraversal));
+    }
+
+    /**
+     * Map the {@link Traverser} to the object specified by the key returned by the {@code keyTraversal}. Note that unlike other uses of
+     * {@code select} where there are multiple keys, this use of {@code select} with a traversal does not produce a
+     * {@code Map}.
+     *
+     * @param keyTraversal the traversal expression that selects the key to project
+     * @return the traversal with an appended {@link TraversalSelectStep}.
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#select-step" target="_blank">Reference Documentation - Select Step</a>
+     * @since 3.3.3
+     */
+    public default <E2> GraphTraversal<S, E2> select(final Traversal<S, E2> keyTraversal) {
+        this.asAdmin().getBytecode().addStep(Symbols.select, keyTraversal);
+        return this.asAdmin().addStep(new TraversalSelectStep<>(this.asAdmin(), null, keyTraversal));
+    }
+
+    /**
      * A version of {@code select} that allows for the extraction of a {@link Column} from objects in the traversal.
      *
      * @param column the column to extract

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/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 39e5258..5cbfe87 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
@@ -352,6 +352,20 @@ public class __ {
     }
 
     /**
+     * @see GraphTraversal#select(Pop, Traversal)
+     */
+    public static <A, B> GraphTraversal<A, B> select(final Pop pop, final Traversal<A, B> keyTraversal) {
+        return __.<A>start().select(pop, keyTraversal);
+    }
+
+    /**
+     * @see GraphTraversal#select(Traversal)
+     */
+    public static <A, B> GraphTraversal<A, B> select(final Traversal<A, B> keyTraversal) {
+        return __.<A>start().select(keyTraversal);
+    }
+
+    /**
      * @see GraphTraversal#unfold()
      */
     public static <A> GraphTraversal<A, A> unfold() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
new file mode 100644
index 0000000..dd02a8c
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TraversalSelectStep.java
@@ -0,0 +1,157 @@
+/*
+ * 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.Path;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+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.PathProcessor;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
+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.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+
+import java.util.*;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public final class TraversalSelectStep<S, E> extends MapStep<S, E> implements TraversalParent, PathProcessor, ByModulating {
+
+    private final Pop pop;
+    private Traversal.Admin<S, E> keyTraversal;
+    private Traversal.Admin<E, E> selectTraversal = null;
+    private Set<String> keepLabels;
+
+    public TraversalSelectStep(final Traversal.Admin traversal, final Pop pop, final Traversal<S, E> keyTraversal) {
+        super(traversal);
+        this.pop = pop;
+        this.keyTraversal = this.integrateChild(keyTraversal.asAdmin());
+    }
+
+    @Override
+    protected E map(final Traverser.Admin<S> traverser) {
+        E end = null;
+        final Iterator<E> keyIterator = TraversalUtil.applyAll(traverser, this.keyTraversal);
+        if (keyIterator.hasNext()) {
+            final E key = keyIterator.next();
+            final Object object = traverser.get();
+            if (object instanceof Map && ((Map) object).containsKey(key))
+                end = (E) ((Map) object).get(key);
+            else if (key instanceof String) {
+                final String skey = (String) key;
+                if (traverser.getSideEffects().exists(skey)) {
+                    end = traverser.getSideEffects().get((String) key);
+                } else {
+                    final Path path = traverser.path();
+                    if (path.hasLabel(skey))
+                        end = null == pop ? path.get(skey) : path.get(pop, skey);
+                }
+            }
+        }
+        return null != end ? TraversalUtil.applyNullable(end, this.selectTraversal) : null;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.pop, this.keyTraversal, this.selectTraversal);
+    }
+
+    @Override
+    public TraversalSelectStep<S, E> clone() {
+        final TraversalSelectStep<S, E> clone = (TraversalSelectStep<S, E>) super.clone();
+        clone.keyTraversal = this.keyTraversal.clone();
+        if (null != this.selectTraversal)
+            clone.selectTraversal = this.selectTraversal.clone();
+        return clone;
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.integrateChild(this.selectTraversal);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.keyTraversal.hashCode();
+        if (null != this.selectTraversal)
+            result ^= this.selectTraversal.hashCode();
+        if (null != this.pop)
+            result ^= this.pop.hashCode();
+        return result;
+    }
+
+    @Override
+    public List<Traversal.Admin<?, ?>> getLocalChildren() {
+        return null == this.selectTraversal ? Collections.emptyList() : Collections.singletonList(this.selectTraversal);
+    }
+
+    @Override
+    public void removeLocalChild(final Traversal.Admin<?, ?> traversal) {
+        if (this.selectTraversal == traversal)
+            this.selectTraversal = null;
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> selectTraversal) {
+        this.selectTraversal = this.integrateChild(selectTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(
+                TraverserRequirement.OBJECT,
+                TraverserRequirement.SIDE_EFFECTS,
+                TraverserRequirement.PATH);
+    }
+
+    //@Override
+    //public Set<String> getScopeKeys() {
+    //    return Collections.singleton(this.selectKey);
+    //}
+
+    public Pop getPop() {
+        return this.pop;
+    }
+
+    @Override
+    public void setKeepLabels(final Set<String> keepLabels) {
+        this.keepLabels = new HashSet<>(keepLabels);
+    }
+
+    @Override
+    public Set<String> getKeepLabels() {
+        return this.keepLabels;
+    }
+
+    @Override
+    protected Traverser.Admin<E> processNextStart() {
+        final Traverser.Admin<E> traverser = super.processNextStart();
+        if (!(this.getTraversal().getParent() instanceof MatchStep)) {
+            PathProcessor.processTraverserPathLabels(traverser, this.keepLabels);
+        }
+        return traverser;
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 5e6e9d5..9952455 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -1323,6 +1323,15 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
+        public GraphTraversal<S, E2> Select<E2> (Pop pop, ITraversal keyTraversal)
+        {
+            Bytecode.AddStep("select", pop, keyTraversal);
+            return Wrap<S, E2>(this);
+        }
+
+        /// <summary>
+        ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
         public GraphTraversal<S, E2> Select<E2> (string selectKey)
         {
             Bytecode.AddStep("select", selectKey);
@@ -1341,6 +1350,15 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
+        public GraphTraversal<S, E2> Select<E2> (ITraversal keyTraversal)
+        {
+            Bytecode.AddStep("select", keyTraversal);
+            return Wrap<S, E2>(this);
+        }
+
+        /// <summary>
         ///     Adds the sideEffect step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
         public GraphTraversal<S, E> SideEffect (IConsumer consumer)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 4e34b45..27a0004 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -999,6 +999,14 @@ namespace Gremlin.Net.Process.Traversal
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
+        public static GraphTraversal<object, E2> Select<E2>(Pop pop, ITraversal keyTraversal)
+        {
+            return new GraphTraversal<object, E2>().Select<E2>(pop, keyTraversal);            
+        }
+
+        /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
+        /// </summary>
         public static GraphTraversal<object, E2> Select<E2>(string selectKey)
         {
             return new GraphTraversal<object, E2>().Select<E2>(selectKey);            
@@ -1015,6 +1023,14 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, E2> Select<E2>(ITraversal keyTraversal)
+        {
+            return new GraphTraversal<object, E2>().Select<E2>(keyTraversal);            
+        }
+
+        /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the sideEffect step to that traversal.
         /// </summary>
         public static GraphTraversal<object, object> SideEffect(IConsumer consumer)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/gremlin-test/features/map/Select.feature
----------------------------------------------------------------------
diff --git a/gremlin-test/features/map/Select.feature b/gremlin-test/features/map/Select.feature
index 35d9322..713dd81 100644
--- a/gremlin-test/features/map/Select.feature
+++ b/gremlin-test/features/map/Select.feature
@@ -514,4 +514,48 @@ Feature: Step - select()
     Then the result should be unordered
       | result |
       | d[2].l |
-      | d[2].l |
\ No newline at end of file
+      | d[2].l |
+
+  Scenario: g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").select(__.select("a"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[3].l |
+      | d[1].l |
+      | d[3].l |
+      | d[3].l |
+      | d[1].l |
+      | d[1].l |
+
+  Scenario: g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").select(__.select("a")).by(__.math("_+_"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[6].d |
+      | d[2].d |
+      | d[6].d |
+      | d[6].d |
+      | d[2].d |
+      | d[2].d |
+
+  Scenario: g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().as("a").out("knows").as("a").select(Pop.all, __.constant("a"))
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | l[v[marko],v[vadas]] |
+      | l[v[marko],v[josh]] |

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/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 9dbf261..2861724 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
@@ -129,6 +129,8 @@ public abstract class AbstractGremlinProcessTest extends AbstractGremlinTest {
         for (T t : results) {
             if (t instanceof Map) {
                 assertThat("Checking map result existence: " + t, expectedResults.stream().filter(e -> e instanceof Map).filter(e -> internalCheckMap((Map) e, (Map) t)).findAny().isPresent(), is(true));
+            } else if (t instanceof List) {
+                assertThat("Checking list result existence: " + t, expectedResults.stream().filter(e -> e instanceof List).filter(e -> internalCheckList((List) e, (List) t)).findAny().isPresent(), is(true));
             } else {
                 assertThat("Checking result existence: " + t, expectedResults.contains(t), is(true));
             }
@@ -162,6 +164,18 @@ public abstract class AbstractGremlinProcessTest extends AbstractGremlinTest {
         }
     }
 
+    private static <A> boolean internalCheckList(final List<A> expectedList, final List<A> actualList) {
+        if (expectedList.size() != actualList.size()) {
+            return false;
+        }
+        for (int i = 0; i < actualList.size(); i++) {
+            if (!actualList.get(i).equals(expectedList.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private static <A, B> boolean internalCheckMap(final Map<A, B> expectedMap, final Map<A, B> actualMap) {
         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());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index 3620456..3140004 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -83,6 +83,12 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Vertex> get_g_V_chooseXoutE_count_isX0X__asXaX__asXbXX_chooseXselectXaX__selectXaX__selectXbXX();
 
+    public abstract Traversal<Vertex, Long> get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX();
+
+    public abstract Traversal<Vertex, Double> get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX();
+
+    public abstract Traversal<Vertex, List<Vertex>> get_g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX();
+
     // below are original back()-tests
 
     public abstract Traversal<Vertex, Vertex> get_g_VX1X_asXhereX_out_selectXhereX(final Object v1Id);
@@ -341,6 +347,33 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
         assertEquals(3, xCounter);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX() {
+        final Traversal<Vertex, Long> traversal = get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(3L, 1L, 3L, 3L, 1L, 1L), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX() {
+        final Traversal<Vertex, Double> traversal = get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(6D, 2D, 6D, 6D, 2D, 2D), traversal);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX() {
+        final Vertex marko = convertToVertex(graph, "marko");
+        final Vertex vadas = convertToVertex(graph, "vadas");
+        final Vertex josh = convertToVertex(graph, "josh");
+        final Traversal<Vertex, List<Vertex>> traversal = get_g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList(Arrays.asList(marko, vadas), Arrays.asList(marko, josh)), traversal);
+    }
+
     // below are original back()-tests
 
     @Test
@@ -722,6 +755,21 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
             return g.V().choose(__.outE().count().is(0L), __.as("a"), __.as("b")).choose(__.select("a"), __.select("a"), __.select("b"));
         }
 
+        @Override
+        public Traversal<Vertex, Long> get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX() {
+            return g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").select(__.select("a"));
+        }
+
+        @Override
+        public Traversal<Vertex, Double> get_g_V_asXaX_groupXmX_by_byXbothE_countX_barrier_selectXmX_selectXselectXaXX_byXmathX_plus_XX() {
+            return g.V().as("a").group("m").by().by(__.bothE().count()).barrier().select("m").<Double>select(__.select("a")).by(__.math("_+_"));
+        }
+
+        @Override
+        public Traversal<Vertex, List<Vertex>> get_g_V_asXaX_outXknowsX_asXaX_selectXall_constantXaXX() {
+            return g.V().as("a").out("knows").as("a").select(Pop.all, (Traversal) __.constant("a"));
+        }
+
         // below are original back()-tests
 
         @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c135da6e/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 a13a4ad..e0018fc 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
@@ -19,15 +19,15 @@
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 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.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLIo;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
 import org.junit.Ignore;
@@ -36,24 +36,15 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Supplier;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.Operator.sum;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.choose;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.outE;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.sack;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.select;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.union;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.valueMap;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -131,12 +122,91 @@ public class TinkerGraphPlayTest {
     @Ignore
     public void testPlayDK() throws Exception {
 
-        Graph graph = TinkerGraph.open();
-        GraphTraversalSource g = graph.traversal();
-        graph.io(GraphMLIo.build()).readGraph("/projects/apache/tinkerpop/data/grateful-dead.xml");
-        System.out.println(g.V().filter(outE("sungBy").count().is(0)).explain());
-        System.out.println(g.V().filter(outE("sungBy").count().is(lt(1))).explain());
-        System.out.println(g.V().filter(outE("sungBy").count().is(1)).explain());
+        final Map<String, String> aliases = new HashMap<>();
+        aliases.put("marko","okram");
+        final GraphTraversalSource g = TinkerFactory.createModern().traversal();
+        /*g.withSideEffect("a", aliases).V().hasLabel("person").
+                values("name").as("n").
+                optional(select("a").select(select("n"))).
+                forEachRemaining(System.out::println);*/
+
+        // shortest path lengths (by summed weight)
+        g.withSack(0.0).V().has("person", "name", "marko").
+                repeat(__.bothE().
+                        sack(sum).
+                            by("weight").
+                        otherV().
+                        group("m").
+                            by().
+                            by(sack().min()).as("x").
+                        // where(P.eq("m")).by(sack()).by(select(select("x"))). // could be that easy, but "x" is unknown here
+                        filter(project("s","x").
+                                    by(sack()).
+                                    by(select("m").select(select("x"))).
+                                where("s", P.eq("x"))).
+                        group("p").
+                            by().
+                            by(project("path","length").
+                                    by(path().by("name").by("weight")).
+                                    by(sack()))
+                        ).
+                cap("p").unfold().
+                group().
+                    by(select(Column.keys).values("name")).
+                    by(Column.values).next().entrySet().
+                forEach(System.out::println);
+
+        System.out.println("---");
+
+        // longest path lengths (by summed weight)
+        g.withSack(0.0).V().has("person", "name", "marko").
+                repeat(__.bothE().simplePath().
+                        sack(sum).
+                          by("weight").
+                        otherV().
+                        group("m").
+                            by().
+                            by(sack().max()).as("x").
+                        filter(project("s","x").
+                                by(sack()).
+                                by(select("m").select(select("x"))).
+                                where("s", P.eq("x"))).
+                        group("p").
+                                by().
+                                by(project("path","length").
+                                        by(path().by("name").by("weight")).
+                                        by(sack()))
+                        ).
+                cap("p").unfold().
+                group().
+                    by(select(Column.keys).values("name")).
+                    by(Column.values).next().entrySet().
+                forEach(System.out::println);
+
+        System.out.println("---");
+
+        // all shortest paths (by summed weight)
+        g.withSack(0.0).V().as("a").
+                repeat(__.bothE().
+                        sack(sum).
+                            by("weight").
+                        otherV().as("b").
+                        group("m").
+                            by(select("a","b").by("name")).
+                            by(sack().min()).
+                        filter(project("s","x").
+                                by(sack()).
+                                by(select("m").select(select("a", "b").by("name"))).
+                               where("s", P.eq("x"))).
+                        group("p").
+                            by(select("a","b").by("name")).
+                            by(map(union(path().by("name").by("weight"), sack()).fold()))
+                ).
+                cap("p").unfold().
+                order().
+                    by(select(Column.keys).select("a")).
+                    by(select(Column.keys).select("b")).
+                forEachRemaining(System.out::println);
     }
 
     @Test


[2/2] tinkerpop git commit: Merge branch 'TINKERPOP-1628' into tp33

Posted by dk...@apache.org.
Merge branch 'TINKERPOP-1628' into tp33


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

Branch: refs/heads/tp33
Commit: 4eeb178049e219696869608d39cbbf3d08bf61d2
Parents: edaabb4 c135da6
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Wed Apr 25 16:20:20 2018 -0700
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Wed Apr 25 16:20:20 2018 -0700

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 docs/src/recipes/shortest-path.asciidoc         |  39 +++++
 docs/src/reference/the-traversal.asciidoc       |  18 +++
 .../traversal/dsl/graph/GraphTraversal.java     |  30 ++++
 .../gremlin/process/traversal/dsl/graph/__.java |  14 ++
 .../traversal/step/map/TraversalSelectStep.java | 157 +++++++++++++++++++
 .../Process/Traversal/GraphTraversal.cs         |  18 +++
 .../src/Gremlin.Net/Process/Traversal/__.cs     |  16 ++
 gremlin-test/features/map/Select.feature        |  46 +++++-
 .../process/AbstractGremlinProcessTest.java     |  14 ++
 .../process/traversal/step/map/SelectTest.java  |  48 ++++++
 .../structure/TinkerGraphPlayTest.java          | 114 +++++++++++---
 12 files changed, 492 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4eeb1780/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index 92f11e9,ab20fff..3c5f4b8
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -25,9 -25,9 +25,10 @@@ image::https://raw.githubusercontent.co
  
  This release also includes changes from <<release-3-2-9, 3.2.9>>.
  
+ * Implemented `TraversalSelectStep` which allows to `select()` runtime-generated keys.
  * Coerced `BulkSet` to `g:List` in GraphSON 3.0.
  * Deprecated `CredentialsGraph` DSL in favor of `CredentialsTraversalDsl` which uses the recommended method for Gremlin DSL development.
 +* Allowed `iterate()` to be called after `profile()`.
  
  [[release-3-3-2]]
  === TinkerPop 3.3.2 (Release Date: April 2, 2018)