This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 250b4eaa44583af3021e4bc722b671ca5308c123 Author: Stephen Mallette <[email protected]> AuthorDate: Wed Mar 26 16:12:48 2025 -0400 Fixed all the go vet problems. Still some issues here with how strategies are being handled. Needs review. CTR --- .../translator/DotNetTranslateVisitor.java | 3 +- .../language/translator/GoTranslateVisitor.java | 27 ++++-- .../language/translator/GremlinTranslatorTest.java | 11 ++- gremlin-go/driver/cucumber/gremlin.go | 4 +- gremlin-go/driver/strategies.go | 107 +++++++++++++++------ gremlin-go/driver/strategies_test.go | 6 +- .../ReservedKeysVerificationStrategy.feature | 2 +- 7 files changed, 115 insertions(+), 45 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java index 83ce667f4e..2522845147 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java @@ -288,7 +288,8 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor { } else if (ctx.getChild(0).getText().equals("keys")) { // find the last "List" in sb and replace it with "HashSet" final int ix = sb.lastIndexOf("List<object>"); - sb.replace(ix, ix + 12, "List<string>"); + if (ix > -1) + sb.replace(ix, ix + 12, "List<string>"); } return null; diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java index c6df7f29d6..47ed839dac 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java @@ -23,6 +23,7 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; import org.apache.commons.lang3.StringUtils; import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser; +import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.apache.tinkerpop.gremlin.util.DatetimeHelper; @@ -196,20 +197,32 @@ public class GoTranslateVisitor extends AbstractTranslateVisitor { else { String strategyName = ctx.getChild(0).getText().equals("new") ? ctx.getChild(1).getText() : ctx.getChild(0).getText(); sb.append(GO_PACKAGE_NAME).append(strategyName).append("("); - sb.append(GO_PACKAGE_NAME + strategyName + "Config{"); // get a list of all the arguments to the strategy - i.e. anything not a terminal node final List<ParseTree> configs = ctx.children.stream(). filter(c -> c instanceof GremlinParser.ConfigurationContext).collect(Collectors.toList()); - // the rest are the arguments to the strategy - for (int ix = 0; ix < configs.size(); ix++) { - visit(configs.get(ix)); - if (ix < configs.size() - 1) - sb.append(", "); + if (configs.size() > 0 && ctx.children.stream().anyMatch(t -> t.getText().equals(OptionsStrategy.class.getSimpleName()))) { + sb.append("map[string]interface{}{"); + for (int ix = 0; ix < configs.size(); ix++) { + sb.append("\"").append(configs.get(ix).getChild(0).getText()).append("\":"); + visit(configs.get(ix).getChild(2)); + if (ix < configs.size() - 1) + sb.append(", "); + } + sb.append("}"); + } else { + // the rest are the arguments to the strategy + sb.append(GO_PACKAGE_NAME + strategyName + "Config{"); + for (int ix = 0; ix < configs.size(); ix++) { + visit(configs.get(ix)); + if (ix < configs.size() - 1) + sb.append(", "); + } + sb.append("}"); } - sb.append("})"); + sb.append(")"); } return null; diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java index 2a7f51c1b7..3cf5a1fce3 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java @@ -583,6 +583,15 @@ public class GremlinTranslatorTest { null, null, "g.with_bulk(x)"}, + {"g.withStrategies(ReservedKeysVerificationStrategy(keys:{'x','y'}))", /// if you happen to do [] you get a List in translation........... + "g.withStrategies(ReservedKeysVerificationStrategy(keys:{'x', 'y'}))", + "g.withStrategies(ReservedKeysVerificationStrategy(keys:set0))", + "g.WithStrategies(new ReservedKeysVerificationStrategy(keys: new HashSet<object> { \"x\", \"y\" }))", + "g.WithStrategies(gremlingo.ReservedKeysVerificationStrategy(gremlingo.ReservedKeysVerificationStrategyConfig{Keys: gremlingo.NewSimpleSet(\"x\", \"y\")}))", + "g.withStrategies(new ReservedKeysVerificationStrategy(keys:['x', 'y'] as Set))", + "g.withStrategies(ReservedKeysVerificationStrategy.build().keys(new HashSet<Object>() {{ add(\"x\"); add(\"y\"); }}).create())", + "g.withStrategies(new ReservedKeysVerificationStrategy({keys: new Set([\"x\", \"y\"])}))", + "g.with_strategies(ReservedKeysVerificationStrategy(keys={'x', 'y'}))"}, {"g.withStrategies(ReadOnlyStrategy)", null, null, @@ -596,7 +605,7 @@ public class GremlinTranslatorTest { null, "g.withStrategies(new OptionsStrategy(myVar:number0))", "g.WithStrategies(new OptionsStrategy(new Dictionary<string, object> {{\"myVar\",10000},}))", - "g.WithStrategies(gremlingo.OptionsStrategy(gremlingo.OptionsStrategyConfig{MyVar: 10000}))", ////////////////////////SO NOT RIGHT + "g.WithStrategies(gremlingo.OptionsStrategy(map[string]interface{}{\"myVar\":10000}))", null, "g.withStrategies(OptionsStrategy.build().with(\"myVar\", 10000).create())", "g.withStrategies(new OptionsStrategy({myVar: 10000}))", diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go index f2c7887bf1..d43c14010b 100644 --- a/gremlin-go/driver/cucumber/gremlin.go +++ b/gremlin-go/driver/cucumber/gremlin.go @@ -419,7 +419,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_coworker": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Filter(gremlingo.T__.OutE("created")).Aggregate("p").As("p1").Values("name").As("p1n").Select("p").Unfold().Where(gremlingo.P.Neq("p1")).As("p2").Values("name").As("p2n").Select("p2").Out("created").Choose(gremlingo.T__.In("created").Where(gremlingo.P.Eq("p1")), gremlingo.T__.Values("name"), gremlingo.T__.Constant(p["xx1"])).Group().By(gremling [...] "g_V_coworker_with_midV": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasLabel("person").Filter(gremlingo.T__.OutE("created")).As("p1").V().HasLabel("person").Where(gremlingo.P.Neq("p1")).Filter(gremlingo.T__.OutE("created")).As("p2").Map(gremlingo.T__.Out("created").Where(gremlingo.T__.In("created").As("p1")).Values("name").Fold()).Group().By(gremlingo.T__.Select("p1").By("name")).By(gremlingo.T__.Group().By(gremlingo.T_ [...] "g_withStrategiesXOptionsStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.OptionsStrategy()).V()}}, - "g_withStrategiesXOptionsStrategyXmyVar_myValueXX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.OptionsStrategy(gremlingo.OptionsStrategyConfig{MyVar: "myValue"})).V()}}, + "g_withStrategiesXOptionsStrategyXmyVar_myValueXX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.OptionsStrategy(map[string]interface{}{"myVar":"myValue"})).V()}}, "g_withoutStrategiesXOptionsStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.OptionsStrategy).V()}}, "g_withStrategiesXOrderLimitStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.OrderLimitStrategy()).V()}}, "g_withoutStrategiesXOrderLimitStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.OrderLimitStrategy).V()}}, @@ -469,7 +469,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_withStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.RepeatUnrollStrategy()).V().Repeat(gremlingo.T__.Out()).Times(2)}}, "g_withoutStrategiesXRepeatUnrollStrategyX_V_repeatXoutX_timesX2X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.RepeatUnrollStrategy).V().Repeat(gremlingo.T__.Out()).Times(2)}}, "g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXid_123X_propertyXname_markoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.ReservedKeysVerificationStrategy(gremlingo.ReservedKeysVerificationStrategyConfig{ThrowException: true})).AddV("person").Property("id", 123).Property("name", "marko")}}, - "g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.ReservedKeysVerificationStrategy(gremlingo.ReservedKeysVerificationStrategyConfig{ThrowException: true, Keys: []interface{}{"age"}})).AddV("person").Property("age", 29).Property("name", "marko")}}, + "g_withStrategiesXReservedKeysVerificationStrategyXthrowException_trueXX_addVXpersonX_propertyXage_29X_propertyXname_markoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.ReservedKeysVerificationStrategy(gremlingo.ReservedKeysVerificationStrategyConfig{ThrowException: true, Keys: gremlingo.NewSimpleSet("age")})).AddV("person").Property("age", 29).Property("name", "marko")}}, "g_withoutStrategiesXReservedKeysVerificationStrategyX_addVXpersonX_propertyXid_123X_propertyXname_markoX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.ReservedKeysVerificationStrategy).AddV("person").Property("id", 123).Property("name", "marko")}}, "g_withStrategiesXSeedStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithStrategies(gremlingo.SeedStrategy(gremlingo.SeedStrategyConfig{Seed: 7})).V().Coin(0.5)}}, "g_withoutStrategiesXSeedStrategyX_V": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.WithoutStrategies(gremlingo.SeedStrategy).V()}}, diff --git a/gremlin-go/driver/strategies.go b/gremlin-go/driver/strategies.go index a2573c5fcc..9108e6b419 100644 --- a/gremlin-go/driver/strategies.go +++ b/gremlin-go/driver/strategies.go @@ -20,12 +20,15 @@ under the License. package gremlingo const ( - baseNamespace = "org.apache.tinkerpop.gremlin.process.traversal.strategy." - decorationNamespace = baseNamespace + "decoration." - finalizationNamespace = baseNamespace + "finalization." - optimizationNamespace = baseNamespace + "optimization." - verificationNamespace = baseNamespace + "verification." - computerDecorationNamespace = "org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration." + baseNamespace = "org.apache.tinkerpop.gremlin.process.traversal.strategy." + decorationNamespace = baseNamespace + "decoration." + finalizationNamespace = baseNamespace + "finalization." + optimizationNamespace = baseNamespace + "optimization." + verificationNamespace = baseNamespace + "verification." + computerDecorationNamespace = "org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration." + computerVerificationNamespace = "org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.verification." + computerFinalizationNamespace = "org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.finalization." + computerOptimizationNamespace = "org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization." ) type TraversalStrategy interface { @@ -55,8 +58,8 @@ func ElementIdStrategy() TraversalStrategy { func HaltedTraverserStrategy(config HaltedTraverserStrategyConfig) TraversalStrategy { configMap := make(map[string]interface{}) - if config.HaltedTraverserFactoryName != "" { - configMap["haltedTraverserFactory"] = config.HaltedTraverserFactoryName + if config.HaltedTraverserFactory != "" { + configMap["haltedTraverserFactory"] = config.HaltedTraverserFactory } return &traversalStrategy{name: decorationNamespace + "HaltedTraverserStrategy", configuration: configMap} } @@ -64,15 +67,22 @@ func HaltedTraverserStrategy(config HaltedTraverserStrategyConfig) TraversalStra // HaltedTraverserStrategyConfig provides configuration options for HaltedTraverserStrategy. // Zeroed (unset) values are ignored. type HaltedTraverserStrategyConfig struct { - HaltedTraverserFactoryName string + HaltedTraverserFactory string } // OptionsStrategy will not alter the Traversal. It is only a holder for configuration options associated with the // Traversal meant to be accessed by steps or other classes that might have some interaction with it. It is // essentially a way for users to provide Traversal level configuration options that can be used in various ways // by different Graph providers. -func OptionsStrategy(options map[string]interface{}) TraversalStrategy { - return &traversalStrategy{name: decorationNamespace + "OptionsStrategy", configuration: options} +func OptionsStrategy(options ...map[string]interface{}) TraversalStrategy { + var opts map[string]interface{} + if len(options) > 0 { + opts = options[0] + } else { + opts = make(map[string]interface{}) + } + + return &traversalStrategy{name: decorationNamespace + "OptionsStrategy", configuration: opts} } // PartitionStrategy partitions the Vertices, Edges and Vertex properties of a Graph into String named @@ -146,27 +156,32 @@ type SubgraphStrategyConfig struct { CheckAdjacentVertices interface{} } -func VertexProgramStrategy(config VertexProgramStrategyConfig) TraversalStrategy { +func VertexProgramStrategy(config ...VertexProgramStrategyConfig) TraversalStrategy { + var cfg VertexProgramStrategyConfig + if len(config) > 0 { + cfg = config[0] + } + configMap := make(map[string]interface{}) - if config.GraphComputer != "" { - configMap["graphComputer"] = config.GraphComputer + if cfg.GraphComputer != "" { + configMap["graphComputer"] = cfg.GraphComputer } - if config.Workers != 0 { - configMap["workers"] = config.Workers + if cfg.Workers != 0 { + configMap["workers"] = cfg.Workers } - if config.Persist != "" { - configMap["persist"] = config.Persist + if cfg.Persist != "" { + configMap["persist"] = cfg.Persist } - if config.Result != "" { - configMap["result"] = config.Result + if cfg.Result != "" { + configMap["result"] = cfg.Result } - if config.Vertices != nil { - configMap["vertices"] = config.Vertices + if cfg.Vertices != nil { + configMap["vertices"] = cfg.Vertices } - if config.Edges != nil { - configMap["edges"] = config.Edges + if cfg.Edges != nil { + configMap["edges"] = cfg.Edges } - for k, v := range config.Configuration { + for k, v := range cfg.Configuration { configMap[k] = v } return &traversalStrategy{name: computerDecorationNamespace + "VertexProgramStrategy", configuration: configMap} @@ -184,6 +199,38 @@ type VertexProgramStrategyConfig struct { Configuration map[string]interface{} } +func ProfileStrategy() TraversalStrategy { + return &traversalStrategy{name: finalizationNamespace + "ProfileStrategy"} +} + +func ReferenceElementStrategy() TraversalStrategy { + return &traversalStrategy{name: finalizationNamespace + "ReferenceElementStrategy"} +} + +func StandardVerificationStrategy() TraversalStrategy { + return &traversalStrategy{name: finalizationNamespace + "StandardVerificationStrategy"} +} + +func ComputerFinalizationStrategy() TraversalStrategy { + return &traversalStrategy{name: computerFinalizationNamespace + "ComputerFinalizationStrategy"} +} + +func ComputerVerificationStrategy() TraversalStrategy { + return &traversalStrategy{name: computerVerificationNamespace + "ComputerVerificationStrategy"} +} + +func VertexProgramRestrictionStrategy() TraversalStrategy { + return &traversalStrategy{name: computerVerificationNamespace + "VertexProgramRestrictionStrategy"} +} + +func GraphFilterStrategy() TraversalStrategy { + return &traversalStrategy{name: computerOptimizationNamespace + "GraphFilterStrategy"} +} + +func MessagePassingReductionStrategy() TraversalStrategy { + return &traversalStrategy{name: computerOptimizationNamespace + "MessagePassingReductionStrategy"} +} + // Finalization strategies func MatchAlgorithmStrategy(config MatchAlgorithmStrategyConfig) TraversalStrategy { @@ -208,7 +255,7 @@ type MatchAlgorithmStrategyConfig struct { func EdgeLabelVerificationStrategy(config EdgeLabelVerificationStrategyConfig) TraversalStrategy { configMap := map[string]interface{}{ "logWarning": config.LogWarning, - "throwException": config.ThrowExcecption, + "throwException": config.ThrowException, } return &traversalStrategy{name: verificationNamespace + "EdgeLabelVerificationStrategy", configuration: configMap} @@ -217,8 +264,8 @@ func EdgeLabelVerificationStrategy(config EdgeLabelVerificationStrategyConfig) T // EdgeLabelVerificationStrategyConfig provides configuration options for EdgeLabelVerificationStrategy. // Zeroed (unset) values are used. type EdgeLabelVerificationStrategyConfig struct { - LogWarning bool - ThrowExcecption bool + LogWarning bool + ThrowException bool } // LambdaRestrictionStrategy does not allow lambdas to be used in a Traversal. The contents of a lambda @@ -241,7 +288,7 @@ func ReservedKeysVerificationStrategy(config ReservedKeysVerificationStrategyCon "logWarning": config.LogWarning, "throwException": config.ThrowException, } - if len(config.Keys) != 0 { + if len(config.Keys.ToSlice()) != 0 { configMap["keys"] = config.Keys } return &traversalStrategy{name: verificationNamespace + "ReservedKeysVerificationStrategy", configuration: configMap} @@ -252,7 +299,7 @@ func ReservedKeysVerificationStrategy(config ReservedKeysVerificationStrategyCon type ReservedKeysVerificationStrategyConfig struct { LogWarning bool ThrowException bool - Keys []string + Keys Set } // Optimization strategies diff --git a/gremlin-go/driver/strategies_test.go b/gremlin-go/driver/strategies_test.go index 3323a78954..db5695e9c6 100644 --- a/gremlin-go/driver/strategies_test.go +++ b/gremlin-go/driver/strategies_test.go @@ -336,8 +336,8 @@ func TestStrategy(t *testing.T) { defer g.remoteConnection.Close() config := EdgeLabelVerificationStrategyConfig{ - LogWarning: true, - ThrowExcecption: true, + LogWarning: true, + ThrowException: true, } count, err := g.WithStrategies(EdgeLabelVerificationStrategy(config)).V().Count().ToList() assert.Nil(t, err) @@ -389,7 +389,7 @@ func TestStrategy(t *testing.T) { config := ReservedKeysVerificationStrategyConfig{ LogWarning: true, ThrowException: true, - Keys: []string{"xyz"}, + Keys: NewSimpleSet("xyz"), } strategy := ReservedKeysVerificationStrategy(config) count, err := g.WithStrategies(strategy).V().Count().ToList() diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/ReservedKeysVerificationStrategy.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/ReservedKeysVerificationStrategy.feature index 88142b0c2d..4a9f4cd28e 100644 --- a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/ReservedKeysVerificationStrategy.feature +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/integrated/ReservedKeysVerificationStrategy.feature @@ -33,7 +33,7 @@ Feature: Step - ReservedKeysVerificationStrategy Given the empty graph And the traversal of """ - g.withStrategies(ReservedKeysVerificationStrategy(throwException: true, keys: ["age"])).addV("person").property("age", 29).property("name", "marko") + g.withStrategies(ReservedKeysVerificationStrategy(throwException: true, keys: {"age"})).addV("person").property("age", 29).property("name", "marko") """ When iterated to list Then the traversal will raise an error with message containing text of "is setting a property key to a reserved word: age"
