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/10/26 14:15:25 UTC

[tinkerpop] branch TINKERPOP-2059 created (now f30ae5d)

This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a change to branch TINKERPOP-2059
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


      at f30ae5d  wip

This branch includes the following new commits:

     new 75574e0  TINKERPOP-2059 wip
     new f30ae5d  wip

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[tinkerpop] 02/02: wip

Posted by dk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a commit to branch TINKERPOP-2059
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit f30ae5d33f8764b348b9eec80faf537a9a3ab058
Author: Daniel Kuppitz <da...@hotmail.com>
AuthorDate: Fri Oct 26 07:15:11 2018 -0700

    wip
---
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |  2 +
 .../traversal/step/map/PropertyMapStep.java        | 69 ++++++++++++++++-----
 .../process/traversal/step/util/WithOptions.java   | 70 ++++++++++++++++++++++
 .../strategy/decoration/PartitionStrategy.java     |  4 +-
 gremlin-dotnet/glv/WithOptions.template            | 47 +++++++++++++++
 gremlin-dotnet/glv/generate.groovy                 | 21 +++++--
 .../Gremlin.Net/Process/Traversal/WithOptions.cs   | 65 ++++++++++++++++++++
 gremlin-javascript/glv/TraversalSource.template    | 13 ++++
 gremlin-javascript/glv/generate.groovy             | 11 +++-
 .../gremlin-javascript/lib/process/traversal.js    | 28 +++++++++
 gremlin-test/features/map/ValueMap.feature         |  4 +-
 .../tinkergraph/structure/TinkerGraphPlayTest.java | 36 +++++++----
 12 files changed, 336 insertions(+), 34 deletions(-)

diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index d60502a..765bb34 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -73,6 +73,7 @@ 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.step.TraversalOptionParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
@@ -183,6 +184,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(TraversalOptionParent.Pick.class);
         CLASS_IMPORTS.add(P.class);
         CLASS_IMPORTS.add(TextP.class);
+        CLASS_IMPORTS.add(WithOptions.class);
         // remote
         CLASS_IMPORTS.add(RemoteConnection.class);
         CLASS_IMPORTS.add(RemoteGraph.class);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 1718f59..1333f39 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -20,9 +20,11 @@ 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.lambda.ElementValueTraversal;
 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.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 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;
@@ -33,12 +35,9 @@ import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -47,18 +46,28 @@ import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Daniel Kuppitz (http://gremlin.guru)
  */
-public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent, ByModulating {
+public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>>
+        implements TraversalParent, ByModulating, Configuring {
 
     protected final String[] propertyKeys;
     protected final PropertyType returnType;
-    protected final boolean includeTokens;
+
+    protected int tokens;
     protected Traversal.Admin<Element, ? extends Property> propertyTraversal;
+
+    private Parameters parameters = new Parameters();
     private TraversalRing<K, E> traversalRing;
 
+    @Deprecated
     public PropertyMapStep(final Traversal.Admin traversal, final boolean includeTokens, final PropertyType propertyType, final String... propertyKeys) {
+        this(traversal, propertyType, propertyKeys);
+        this.configure(WithOptions.tokens, includeTokens ? WithOptions.all : WithOptions.none);
+    }
+
+    public PropertyMapStep(final Traversal.Admin traversal, final PropertyType propertyType, final String... propertyKeys) {
         super(traversal);
-        this.includeTokens = includeTokens;
         this.propertyKeys = propertyKeys;
         this.returnType = propertyType;
         this.propertyTraversal = null;
@@ -70,13 +79,13 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         final Map<Object, Object> map = new LinkedHashMap<>();
         final Element element = traverser.get();
         final boolean isVertex = element instanceof Vertex;
-        if (this.returnType == PropertyType.VALUE && this.includeTokens) {
-            map.put(T.id, element.id());
+        if (this.returnType == PropertyType.VALUE) {
+            if (includeToken(WithOptions.ids)) map.put(T.id, element.id());
             if (element instanceof VertexProperty) {
-                map.put(T.key, ((VertexProperty<?>) element).key());
-                map.put(T.value, ((VertexProperty<?>) element).value());
+                if (includeToken(WithOptions.keys)) map.put(T.key, ((VertexProperty<?>) element).key());
+                if (includeToken(WithOptions.values)) map.put(T.value, ((VertexProperty<?>) element).value());
             } else {
-                map.put(T.label, element.label());
+                if (includeToken(WithOptions.labels)) map.put(T.label, element.label());
             }
         }
         final Iterator<? extends Property> properties = null == this.propertyTraversal ?
@@ -106,6 +115,29 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
     }
 
     @Override
+    public void configure(final Object... keyValues) {
+        if (keyValues[0].equals(WithOptions.tokens)) {
+            if (keyValues.length == 2 && keyValues[1] instanceof Boolean) {
+                this.tokens = ((boolean) keyValues[1]) ? WithOptions.all : WithOptions.none;
+            } else {
+                for (int i = 1; i < keyValues.length; i++) {
+                    if (!(keyValues[i] instanceof Integer))
+                        throw new IllegalArgumentException("WithOptions.tokens requires Integer arguments (possible " + "" +
+                                "values are: WithOptions.[none|ids|labels|keys|values|all])");
+                    this.tokens |= (int) keyValues[i];
+                }
+            }
+        } else {
+            this.parameters.set(this, keyValues);
+        }
+    }
+
+    @Override
+    public Parameters getParameters() {
+        return parameters;
+    }
+
+    @Override
     public List<Traversal.Admin<K, E>> getLocalChildren() {
         final List<Traversal.Admin<K, E>> result = new ArrayList<>();
         if (null != this.propertyTraversal)
@@ -131,8 +163,9 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         return propertyKeys;
     }
 
+    @Deprecated
     public boolean isIncludeTokens() {
-        return includeTokens;
+        return this.tokens != WithOptions.none;
     }
 
     public String toString() {
@@ -150,7 +183,7 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
 
     @Override
     public int hashCode() {
-        int result = super.hashCode() ^ this.returnType.hashCode() ^ Boolean.hashCode(this.includeTokens);
+        int result = super.hashCode() ^ this.returnType.hashCode() ^ Integer.hashCode(this.tokens);
         if (null != this.propertyTraversal)
             result ^= this.propertyTraversal.hashCode();
         for (final String propertyKey : this.propertyKeys) {
@@ -171,4 +204,12 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
     public Set<TraverserRequirement> getRequirements() {
         return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT);
     }
+
+    public int getIncludedTokens() {
+        return this.tokens;
+    }
+
+    private boolean includeToken(final int token) {
+        return 0 != (this.tokens & token);
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
new file mode 100644
index 0000000..3faa95d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/WithOptions.java
@@ -0,0 +1,70 @@
+/*
+ * 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.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
+/**
+ * Configuration options to be passed to the {@link GraphTraversal#with(String, Object)}.
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class WithOptions {
+
+    //
+    // PropertyMapStep
+    //
+
+    /**
+     * Configures the tokens to be included in value maps.
+     */
+    public static final String tokens = Graph.Hidden.hide("tinkerpop.valueMap.tokens");
+
+    /**
+     * Include no tokens.
+     */
+    public static int none = 0;
+
+    /**
+     * Include ids (affects all {@link org.apache.tinkerpop.gremlin.structure.Element} value maps).
+     */
+    public static int ids = 1;
+
+    /**
+     * Include labels (affects all {@link org.apache.tinkerpop.gremlin.structure.Vertex} and
+     * {@link org.apache.tinkerpop.gremlin.structure.Edge} value maps).
+     */
+    public static int labels = 2;
+
+    /**
+     * Include keys (affects all {@link org.apache.tinkerpop.gremlin.structure.VertexProperty} value maps).
+     */
+    public static int keys = 4;
+
+    /**
+     * Include keys (affects all {@link org.apache.tinkerpop.gremlin.structure.VertexProperty} value maps).
+     */
+    public static int values = 8;
+
+    /**
+     * Include all tokens.
+     */
+    public static int all = ids | labels | keys | values;
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
index 15079cb..4059191 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategy.java
@@ -43,6 +43,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -180,7 +181,8 @@ public final class PartitionStrategy extends AbstractTraversalStrategy<Traversal
                     // as this is a value map, replace that step with propertiesMap() that returns PropertyType.VALUE.
                     // from there, add the filter as shown above and then unwrap the properties as they would have
                     // been done under valueMap()
-                    final PropertyMapStep propertyMapStep = new PropertyMapStep(traversal, step.isIncludeTokens(), PropertyType.PROPERTY, step.getPropertyKeys());
+                    final PropertyMapStep propertyMapStep = new PropertyMapStep(traversal, PropertyType.PROPERTY, step.getPropertyKeys());
+                    propertyMapStep.configure(WithOptions.tokens, step.getIncludedTokens());
                     TraversalHelper.replaceStep(step, propertyMapStep, traversal);
 
                     final LambdaMapStep mapPropertiesFilterStep = new LambdaMapStep<>(traversal, new MapPropertiesFilter());
diff --git a/gremlin-dotnet/glv/WithOptions.template b/gremlin-dotnet/glv/WithOptions.template
new file mode 100644
index 0000000..f8b25a8
--- /dev/null
+++ b/gremlin-dotnet/glv/WithOptions.template
@@ -0,0 +1,47 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal.Step.Util
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     Configuration options to be passed to the <c>With()</c> modulator.
+    /// </summary>
+    public class WithOptions
+    {
+<% withOptions.each { field -> %>
+
+        public static <%= field.type %> <%= field.name %> = <%= field.value %>;
+<% } %>
+    }
+
+#pragma warning restore 1591
+}
diff --git a/gremlin-dotnet/glv/generate.groovy b/gremlin-dotnet/glv/generate.groovy
index 7985ca0..404fc41 100644
--- a/gremlin-dotnet/glv/generate.groovy
+++ b/gremlin-dotnet/glv/generate.groovy
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
 import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
 import org.apache.tinkerpop.gremlin.structure.Direction
 import java.lang.reflect.Modifier
 import java.lang.reflect.TypeVariable
@@ -114,6 +115,10 @@ def toCSharpType = { name ->
 
 def toCSharpMethodName = { symbol -> (String) Character.toUpperCase(symbol.charAt(0)) + symbol.substring(1) }
 
+def toCSharpValue = { type, value ->
+  type == String.class && value != null ? ('"' + value + '"') : value
+}
+
 def getJavaGenericTypeParameterTypeNames = { method ->
     def typeArguments = method.genericReturnType.actualTypeArguments
     return typeArguments.
@@ -133,7 +138,7 @@ def getJavaParameterTypeNames = { method ->
     return method.parameters.
             collect { param ->
                 param.type.simpleName
-            } 
+            }
 }
 
 def toCSharpParamString = { param, genTypeName ->
@@ -182,7 +187,7 @@ def getCSharpParamString = { method, useGenericParams ->
                     else if (genType instanceof GenericArrayType) {
                         if (((GenericArrayType)genType).getGenericComponentType() instanceof TypeVariable<?>) {
                             genTypeName = ((TypeVariable<?>)((GenericArrayType)genType).getGenericComponentType()).name + "[]"
-                        }                        
+                        }
                     }
                 }
                 toCSharpParamString(param, genTypeName)
@@ -263,8 +268,8 @@ def binding = ["pmethods": P.class.getMethods().
                             return ["methodName": javaMethod.name, "parameters":parameters, "paramNames":paramNames]
                         },
                "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS
-                        findAll { GraphTraversal.class.equals(it.returnType) }.          
-                // Select unique combination of C# parameter types and sort by Java parameter type combination                                                                    
+                        findAll { GraphTraversal.class.equals(it.returnType) }.
+                // Select unique combination of C# parameter types and sort by Java parameter type combination
                         sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }.
                         unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }.
                         collect { javaMethod ->
@@ -321,7 +326,9 @@ def binding = ["pmethods": P.class.getMethods().
                             return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "callGenericTypeArg":callGenericTypeArg, "graphTraversalT2":graphTraversalT2]
                         },
                "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
-               "toCSharpMethodName": toCSharpMethodName]
+               "toCSharpMethodName": toCSharpMethodName,
+               "withOptions": WithOptions.getDeclaredFields().
+                        collect {["type": toCSharpType(it.type.simpleName), "name": it.name, "value": toCSharpValue(it.type, it.get(null))]}]
 
 def engine = new groovy.text.GStringTemplateEngine()
 def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversal.template")).make(binding)
@@ -344,6 +351,10 @@ def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TextP.tem
 def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TextP.cs")
 tpFile.newWriter().withWriter{ it << tpTemplate }
 
+def withOptionsTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/WithOptions.template")).make(binding)
+def withOptionsFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/WithOptions.cs")
+withOptionsFile.newWriter().withWriter{ it << withOptionsTemplate }
+
 binding.tokens.each {k,v ->
     def tokenTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Token.template")).make([tokenFields: v, tokenName: k])
     def tokenFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/${k}.cs")
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
new file mode 100644
index 0000000..a60cfa6
--- /dev/null
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/WithOptions.cs
@@ -0,0 +1,65 @@
+#region License
+
+/*
+ * 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.
+ */
+
+#endregion
+
+// THIS IS A GENERATED FILE - DO NOT MODIFY THIS FILE DIRECTLY - see pom.xml
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Gremlin.Net.Process.Traversal.Step.Util
+{
+#pragma warning disable 1591
+
+    /// <summary>
+    ///     Configuration options to be passed to the <c>With()</c> modulator.
+    /// </summary>
+    public class WithOptions
+    {
+
+
+        public static string tokens = "~tinkerpop.valueMap.tokens";
+
+
+        public static int none = 0;
+
+
+        public static int ids = 1;
+
+
+        public static int labels = 2;
+
+
+        public static int keys = 4;
+
+
+        public static int values = 8;
+
+
+        public static int all = 15;
+
+    }
+
+#pragma warning restore 1591
+}
diff --git a/gremlin-javascript/glv/TraversalSource.template b/gremlin-javascript/glv/TraversalSource.template
index cdbec26..7fc716a 100644
--- a/gremlin-javascript/glv/TraversalSource.template
+++ b/gremlin-javascript/glv/TraversalSource.template
@@ -215,6 +215,14 @@ class TraversalSideEffects {
 
 }
 
+class WithOptions {
+  constructor() {
+<% withOptions.each { %>
+    this.<%= it.name %> = <%= it.value %>;
+<% } %>
+  }
+}
+
 function toEnum(typeName, keys) {
   const result = {};
   keys.split(' ').forEach(k => {
@@ -242,10 +250,15 @@ module.exports = {
   EnumValue,
   P,
   TextP,
+  WithOptions,
   IO,
   Traversal,
   TraversalSideEffects,
   Traverser<%
+withOptions.each { option ->
+    out.print ",\n  " + option.name + ": " + "WithOption." + option.name
+}
+%><%
 enums.each{ enumClass ->
     out.print ",\n  " + decapitalize.call(enumClass.simpleName) + ": toEnum('" + enumClass.simpleName + "', '" +
         enumClass.getEnumConstants().sort { a, b -> a.name() <=> b.name() }.collect { toJs.call(it.name()) }.join(' ') + "')"
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index 575f847..cd3e899 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P
 import org.apache.tinkerpop.gremlin.process.traversal.TextP
 import org.apache.tinkerpop.gremlin.process.traversal.IO
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions
 import java.lang.reflect.Modifier
 
 def toJsMap = ["in": "in_",
@@ -39,6 +40,10 @@ def toJsMap = ["in": "in_",
 
 def toJs = { symbol -> toJsMap.getOrDefault(symbol, symbol) }
 
+def toJSValue = { type, value ->
+  type == String.class && value != null ? ('"' + value + '"') : value
+}
+
 def decapitalize = {
     String string = it;
     if (string == null || string.length() == 0) {
@@ -109,7 +114,9 @@ def binding = ["enums": CoreImports.getClassImports()
                "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]),
                "toJs": toJs,
                "version": determineVersion(),
-               "decapitalize": decapitalize]
+               "decapitalize": decapitalize,
+               "withOptions": WithOptions.getDeclaredFields().
+                        collect {["name": it.name, "value": toJSValue(it.type, it.get(null))]}]
 
 def engine = new GStringTemplateEngine()
 def graphTraversalTemplate = engine.createTemplate(new File("${project.basedir}/glv/GraphTraversalSource.template"))
@@ -124,4 +131,4 @@ traversalFile.newWriter().withWriter{ it << traversalTemplate }
 
 def packageJsonTemplate = engine.createTemplate(new File("${project.basedir}/glv/PackageJson.template")).make(binding)
 def packageJsonFile = new File("${project.basedir}/src/main/javascript/gremlin-javascript/package.json")
-packageJsonFile.newWriter().withWriter{ it << packageJsonTemplate }
\ No newline at end of file
+packageJsonFile.newWriter().withWriter{ it << packageJsonTemplate }
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
index 81853a6..0a732ad 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal.js
@@ -388,6 +388,26 @@ class TraversalSideEffects {
 
 }
 
+class WithOptions {
+  constructor() {
+
+    this.tokens = "~tinkerpop.valueMap.tokens";
+
+    this.none = 0;
+
+    this.ids = 1;
+
+    this.labels = 2;
+
+    this.keys = 4;
+
+    this.values = 8;
+
+    this.all = 15;
+
+  }
+}
+
 function toEnum(typeName, keys) {
   const result = {};
   keys.split(' ').forEach(k => {
@@ -415,10 +435,18 @@ module.exports = {
   EnumValue,
   P,
   TextP,
+  WithOptions,
   IO,
   Traversal,
   TraversalSideEffects,
   Traverser,
+  tokens: WithOption.tokens,
+  none: WithOption.none,
+  ids: WithOption.ids,
+  labels: WithOption.labels,
+  keys: WithOption.keys,
+  values: WithOption.values,
+  all: WithOption.all,
   barrier: toEnum('Barrier', 'normSack'),
   cardinality: toEnum('Cardinality', 'list set single'),
   column: toEnum('Column', 'keys values'),
diff --git a/gremlin-test/features/map/ValueMap.feature b/gremlin-test/features/map/ValueMap.feature
index 109318f..d9e5034 100644
--- a/gremlin-test/features/map/ValueMap.feature
+++ b/gremlin-test/features/map/ValueMap.feature
@@ -97,11 +97,11 @@ Feature: Step - valueMap()
     Given the modern graph
     And the traversal of
       """
-      g.V().hasLabel("person").filter(__.outE("created")).valueMap(true)
+      g.V().hasLabel("person").filter(__.outE("created")).valueMap().with(tokens)
       """
     When iterated to list
     Then the result should be unordered
       | result |
       | m[{"name": ["marko"], "age": [29], "t[label]":"person", "t[id]":"v[marko].id"}] |
       | m[{"name": ["josh"], "age": [32], "t[label]":"person", "t[id]":"v[josh].id"}] |
-      | m[{"name": ["peter"], "age": [35], "t[label]":"person", "t[id]":"v[peter].id"}] |
\ No newline at end of file
+      | m[{"name": ["peter"], "age": [35], "t[label]":"person", "t[id]":"v[peter].id"}] |
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 8cc714a..a2019ae 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,8 +19,6 @@
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
-import org.apache.tinkerpop.gremlin.process.traversal.IO;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -28,10 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import org.apache.tinkerpop.gremlin.structure.*;
-import org.apache.tinkerpop.gremlin.structure.io.IoTest;
 import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLIo;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader;
-import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -39,15 +34,14 @@ 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.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions.*;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -125,10 +119,32 @@ public class TinkerGraphPlayTest {
     @Ignore
     public void testPlayDK() throws Exception {
         TinkerGraph graph = TinkerFactory.createTheCrew();
-        GraphTraversalSource g = graph.traversal();
-        GraphTraversalSource sg = g.withStrategies(
+        GraphTraversalSource g = graph.traversal().withStrategies(
                 SubgraphStrategy.build().vertexProperties(hasNot("endTime")).create());
-        sg.V().valueMap().forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()) ---");
+        g.V().valueMap().forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()) ---");
+        g.V().valueMap().by(unfold()).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens) ---");
+        g.V().valueMap().by(unfold()).with(tokens).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, false) ---");
+        g.V().valueMap().by(unfold()).with(tokens, false).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids) ---");
+        g.V().valueMap().by(unfold()).with(tokens, ids).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, labels) ---");
+        g.V().valueMap().by(unfold()).with(tokens, labels).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, all) ---");
+        g.V().valueMap().by(unfold()).with(tokens, all).forEachRemaining(System.out::println);
+
+        System.out.println("\n--- valueMap().by(unfold()).with(tokens, ids | labels) ---");
+        g.V().valueMap().by(unfold()).with(tokens, ids | labels).forEachRemaining(System.out::println);
     }
 
     @Test


[tinkerpop] 01/02: TINKERPOP-2059 wip

Posted by dk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dkuppitz pushed a commit to branch TINKERPOP-2059
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 75574e07df198b8d70db11d3ae515301b809d53b
Author: Daniel Kuppitz <da...@hotmail.com>
AuthorDate: Tue Oct 23 13:04:20 2018 -0700

    TINKERPOP-2059 wip
---
 .../traversal/step/map/PropertyMapStep.java        | 82 +++++++++++--------
 .../tinkergraph/structure/TinkerGraphPlayTest.java | 92 ++--------------------
 2 files changed, 57 insertions(+), 117 deletions(-)

diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 9ac7d3d..1718f59 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -20,8 +20,11 @@ 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.lambda.ElementValueTraversal;
+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.Element;
 import org.apache.tinkerpop.gremlin.structure.Property;
@@ -30,12 +33,14 @@ import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -43,12 +48,13 @@ import java.util.Set;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent {
+public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements TraversalParent, ByModulating {
 
     protected final String[] propertyKeys;
     protected final PropertyType returnType;
     protected final boolean includeTokens;
     protected Traversal.Admin<Element, ? extends Property> propertyTraversal;
+    private TraversalRing<K, E> traversalRing;
 
     public PropertyMapStep(final Traversal.Admin traversal, final boolean includeTokens, final PropertyType propertyType, final String... propertyKeys) {
         super(traversal);
@@ -56,45 +62,61 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         this.propertyKeys = propertyKeys;
         this.returnType = propertyType;
         this.propertyTraversal = null;
+        this.traversalRing = new TraversalRing<>();
     }
 
     @Override
     protected Map<K, E> map(final Traverser.Admin<Element> traverser) {
-        final Map<Object, Object> map = new HashMap<>();
+        final Map<Object, Object> map = new LinkedHashMap<>();
         final Element element = traverser.get();
-        final boolean isVertex = traverser.get() instanceof Vertex;
+        final boolean isVertex = element instanceof Vertex;
+        if (this.returnType == PropertyType.VALUE && this.includeTokens) {
+            map.put(T.id, element.id());
+            if (element instanceof VertexProperty) {
+                map.put(T.key, ((VertexProperty<?>) element).key());
+                map.put(T.value, ((VertexProperty<?>) element).value());
+            } else {
+                map.put(T.label, element.label());
+            }
+        }
         final Iterator<? extends Property> properties = null == this.propertyTraversal ?
                 element.properties(this.propertyKeys) :
                 TraversalUtil.applyAll(traverser, this.propertyTraversal);
+        //final Iterator<? extends Property> properties = element.properties(this.propertyKeys);
         while (properties.hasNext()) {
             final Property<?> property = properties.next();
+            final Object value = this.returnType == PropertyType.VALUE ? property.value() : property;
             if (isVertex) {
-                List<Object> values = (List<Object>) map.get(property.key());
-                if (null == values) {
-                    values = new ArrayList<>();
-                    map.put(property.key(), values);
-                }
-                values.add(this.returnType == PropertyType.VALUE ? property.value() : property);
-            } else
-                map.put(property.key(), this.returnType == PropertyType.VALUE ? property.value() : property);
-        }
-        if (this.returnType == PropertyType.VALUE && this.includeTokens) {
-        	// add tokens, as string keys
-            if (element instanceof VertexProperty) {
-                map.put(T.id, element.id());
-                map.put(T.key, ((VertexProperty<?>) element).key());
-                map.put(T.value, ((VertexProperty<?>) element).value());
+                map.compute(property.key(), (k, v) -> {
+                    final List<Object> values = v != null ? (List<Object>) v : new ArrayList<>();
+                    values.add(value);
+                    return values;
+                });
             } else {
-                map.put(T.id, element.id());
-                map.put(T.label, element.label());
+                map.put(property.key(), value);
             }
         }
+        if (!traversalRing.isEmpty()) {
+            for (final Object key : map.keySet()) {
+                map.compute(key, (k, v) -> TraversalUtil.applyNullable(v, (Traversal.Admin) this.traversalRing.next()));
+            }
+            this.traversalRing.reset();
+        }
         return (Map) map;
     }
 
     @Override
-    public List<Traversal.Admin<Element, ? extends Property>> getLocalChildren() {
-        return null == this.propertyTraversal ? Collections.emptyList() : Collections.singletonList(this.propertyTraversal);
+    public List<Traversal.Admin<K, E>> getLocalChildren() {
+        final List<Traversal.Admin<K, E>> result = new ArrayList<>();
+        if (null != this.propertyTraversal)
+            result.add((Traversal.Admin) propertyTraversal);
+        result.addAll(this.traversalRing.getTraversals());
+        return Collections.unmodifiableList(result);
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> selectTraversal) {
+        this.traversalRing.addTraversal(this.integrateChild(selectTraversal));
     }
 
     public void setPropertyTraversal(final Traversal.Admin<Element, ? extends Property> propertyTraversal) {
@@ -114,9 +136,7 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
     }
 
     public String toString() {
-        return null != this.propertyTraversal ?
-                StringFactory.stepString(this, this.propertyTraversal, this.returnType.name().toLowerCase()) :
-                StringFactory.stepString(this, Arrays.asList(this.propertyKeys), this.returnType.name().toLowerCase());
+        return StringFactory.stepString(this, this.traversalRing, this.returnType.name().toLowerCase());
     }
 
     @Override
@@ -124,20 +144,19 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         final PropertyMapStep<K,E> clone = (PropertyMapStep<K,E>) super.clone();
         if (null != this.propertyTraversal)
             clone.propertyTraversal = this.propertyTraversal.clone();
+        clone.traversalRing = this.traversalRing.clone();
         return clone;
     }
 
     @Override
     public int hashCode() {
         int result = super.hashCode() ^ this.returnType.hashCode() ^ Boolean.hashCode(this.includeTokens);
-        if (null == this.propertyTraversal) {
-            for (final String propertyKey : this.propertyKeys) {
-                result ^= propertyKey.hashCode();
-            }
-        } else {
+        if (null != this.propertyTraversal)
             result ^= this.propertyTraversal.hashCode();
+        for (final String propertyKey : this.propertyKeys) {
+            result ^= propertyKey.hashCode();
         }
-        return result;
+        return result ^ this.traversalRing.hashCode();
     }
 
     @Override
@@ -145,6 +164,7 @@ public class PropertyMapStep<K,E> extends MapStep<Element, Map<K, E>> implements
         super.setTraversal(parentTraversal);
         if (null != this.propertyTraversal)
             this.integrateChild(this.propertyTraversal);
+        this.traversalRing.getTraversals().forEach(this::integrateChild);
     }
 
     @Override
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 a590835..8cc714a 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
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 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.decoration.SubgraphStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
 import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.structure.io.IoTest;
@@ -123,92 +124,11 @@ public class TinkerGraphPlayTest {
     @Test
     @Ignore
     public void testPlayDK() throws Exception {
-
-        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);
+        TinkerGraph graph = TinkerFactory.createTheCrew();
+        GraphTraversalSource g = graph.traversal();
+        GraphTraversalSource sg = g.withStrategies(
+                SubgraphStrategy.build().vertexProperties(hasNot("endTime")).create());
+        sg.V().valueMap().forEachRemaining(System.out::println);
     }
 
     @Test