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 d5dd5c9e5089d07767cfca9f92b85b19197618c5 Author: Daniel Kuppitz <daniel_kupp...@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 6ccf2e8..59f8a22 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 @@ -74,6 +74,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; @@ -184,6 +185,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