This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch gvalue in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 4eadba6b9880eb68ce251cc546fbcbd66ac73aeb Author: Stephen Mallette <stepm...@amazon.com> AuthorDate: Thu Aug 22 13:27:02 2024 -0400 wip - refactoring around mu steps --- .../language/grammar/TraversalMethodVisitor.java | 28 ++++----- .../grammar/TraversalSourceSpawnMethodVisitor.java | 8 +-- .../gremlin/process/traversal/step/GValue.java | 23 +++++++- .../process/traversal/step/map/AddEdgeStep.java | 8 +-- .../gremlin/process/traversal/step/GValueTest.java | 66 +++++++++++++++++++++- 5 files changed, 104 insertions(+), 29 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java index 88865786b4..011a44cf53 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java @@ -100,7 +100,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public GraphTraversal visitTraversalMethod_mergeV_Map(final GremlinParser.TraversalMethod_mergeV_MapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return graphTraversal.mergeV((GValue<Map<Object, Object>>) literalOrVar); else return graphTraversal.mergeV((Map) literalOrVar); @@ -136,7 +136,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public GraphTraversal visitTraversalMethod_mergeE_Map(final GremlinParser.TraversalMethod_mergeE_MapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return graphTraversal.mergeE((GValue<Map<Object, Object>>) literalOrVar); else return graphTraversal.mergeE((Map) literalOrVar); @@ -463,12 +463,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public GraphTraversal visitTraversalMethod_coin(final GremlinParser.TraversalMethod_coinContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitFloatArgument(ctx.floatArgument()); - if (literalOrVar instanceof Number) - return graphTraversal.coin(((Number) literalOrVar).doubleValue()); - else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType().isNumeric()) + if (GValue.valueInstanceOfNumeric(literalOrVar)) return graphTraversal.coin((GValue<Double>) literalOrVar); else - throw new IllegalArgumentException("coin argument must be a double"); + return graphTraversal.coin(((Number) literalOrVar).doubleValue()); } @@ -664,12 +662,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public Traversal visitTraversalMethod_from_Vertex(final GremlinParser.TraversalMethod_from_VertexContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument()); - if (literalOrVar instanceof Vertex) - return graphTraversal.from((Vertex) literalOrVar); - else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.VERTEX) + if (GValue.valueInstanceOf(literalOrVar, GType.VERTEX)) return graphTraversal.from((GValue<Vertex>) literalOrVar); else - throw new IllegalArgumentException("from argument must be a vertex"); + return graphTraversal.from((Vertex) literalOrVar); } /** @@ -1204,7 +1200,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public GraphTraversal visitTraversalMethod_option_Merge_Map(final GremlinParser.TraversalMethod_option_Merge_MapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return graphTraversal.option(TraversalEnumParser.parseTraversalEnumFromContext(Merge.class, ctx.traversalMerge()), (GValue<Map>) literalOrVar); else return graphTraversal.option(antlr.argumentVisitor.parseMerge(ctx.traversalMergeArgument()), (Map) literalOrVar); @@ -1712,12 +1708,10 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public Traversal visitTraversalMethod_to_Vertex(final GremlinParser.TraversalMethod_to_VertexContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitStructureVertexArgument(ctx.structureVertexArgument()); - if (literalOrVar instanceof Vertex) - return graphTraversal.to((Vertex) literalOrVar); - else if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.VERTEX) + if (GValue.valueInstanceOf(literalOrVar, GType.VERTEX)) return graphTraversal.to((GValue<Vertex>) literalOrVar); else - throw new IllegalArgumentException("from argument must be a vertex"); + return graphTraversal.to((Vertex) literalOrVar); } /** @@ -1878,7 +1872,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public Traversal visitTraversalMethod_call_string_map(final GremlinParser.TraversalMethod_call_string_mapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar); else return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar); @@ -1899,7 +1893,7 @@ public class TraversalMethodVisitor extends TraversalRootVisitor<GraphTraversal> @Override public Traversal visitTraversalMethod_call_string_map_traversal(final GremlinParser.TraversalMethod_call_string_map_traversalContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); else return graphTraversal.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal())); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java index bedf28d487..2758ea429c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalSourceSpawnMethodVisitor.java @@ -122,7 +122,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor @Override public GraphTraversal visitTraversalSourceSpawnMethod_mergeV_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeV_MapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return this.traversalSource.asAdmin().mergeV((GValue) literalOrVar); else return this.traversalSource.mergeV((Map) literalOrVar); @@ -150,7 +150,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor @Override public GraphTraversal visitTraversalSourceSpawnMethod_mergeE_Map(final GremlinParser.TraversalSourceSpawnMethod_mergeE_MapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapNullableArgument(ctx.genericLiteralMapNullableArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return this.traversalSource.asAdmin().mergeE((GValue) literalOrVar); else return this.traversalSource.mergeE((Map) literalOrVar); @@ -178,7 +178,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor @Override public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map(final GremlinParser.TraversalSourceSpawnMethod_call_string_mapContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return this.traversalSource.asAdmin().call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar); else return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar); @@ -199,7 +199,7 @@ public class TraversalSourceSpawnMethodVisitor extends DefaultGremlinBaseVisitor @Override public GraphTraversal visitTraversalSourceSpawnMethod_call_string_map_traversal(final GremlinParser.TraversalSourceSpawnMethod_call_string_map_traversalContext ctx) { final Object literalOrVar = antlr.argumentVisitor.visitGenericLiteralMapArgument(ctx.genericLiteralMapArgument()); - if (literalOrVar instanceof GValue && ((GValue) literalOrVar).getType() == GType.MAP) + if (GValue.valueInstanceOf(literalOrVar, GType.MAP)) return this.traversalSource.asAdmin().call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (GValue<Map>) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal())); else return this.traversalSource.call(antlr.argumentVisitor.parseString(ctx.stringArgument()), (Map) literalOrVar, anonymousVisitor.visitNestedTraversal(ctx.nestedTraversal())); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java index 6f5c6223f6..f7692d6866 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValue.java @@ -332,6 +332,13 @@ public class GValue<V> implements Cloneable, Serializable { return new GValue<>(name, GType.PROPERTY, value); } + /** + * If the object is a {@code GValue} then get its value, otherwise return the object as-is. + */ + public static <T> T getFrom(final Object o) { + return o instanceof GValue ? ((GValue<T>) o).get() : (T) o; + } + /** * Tests if the object is a {@link GValue} and if so, checks the type of the value against the provided * {@link GType}. @@ -340,6 +347,20 @@ public class GValue<V> implements Cloneable, Serializable { return o instanceof GValue && ((GValue) o).getType() == type; } + /** + * Tests if the object is a {@link GValue} and if so, checks if the type of the value is a collection. + */ + public static boolean valueInstanceOfCollection(final Object o) { + return o instanceof GValue && ((GValue) o).getType().isCollection(); + } + + /** + * Tests if the object is a {@link GValue} and if so, checks if the type of the value is a numeric. + */ + public static boolean valueInstanceOfNumeric(final Object o) { + return o instanceof GValue && ((GValue) o).getType().isNumeric(); + } + /** * Checks the type of the object against the provided {@link GType}. If the object is a {@link GValue} then it * can directly check the type, otherwise it will test the given object's class itself using the mappign on the @@ -352,7 +373,7 @@ public class GValue<V> implements Cloneable, Serializable { else if (o instanceof GValue) return ((GValue) o).getType() == type; else - return o.getClass().isAssignableFrom(type.getJavaType()); + return type.getJavaType().isAssignableFrom(o.getClass()); } /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java index 39c37bf9f5..db3f72cfe7 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java @@ -114,7 +114,7 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge> edgeLabel, e.getMessage())); } - if (!(theTo instanceof Vertex) || (theTo instanceof GValue && ((GValue) theTo).getType() != GType.VERTEX)) + if (!GValue.instanceOf(theTo, GType.VERTEX)) throw new IllegalStateException(String.format( "The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel, null == theTo ? "null" : theTo.getClass().getSimpleName())); @@ -128,13 +128,13 @@ public class AddEdgeStep<S> extends ScalarMapStep<S, Edge> edgeLabel, e.getMessage())); } - if (!(theFrom instanceof Vertex) || (theFrom instanceof GValue && ((GValue) theTo).getType() != GType.VERTEX)) + if (!GValue.instanceOf(theFrom, GType.VERTEX)) throw new IllegalStateException(String.format( "The value given to addE(%s).to() must resolve to a Vertex but %s was specified instead", edgeLabel, null == theFrom ? "null" : theFrom.getClass().getSimpleName())); - Vertex toVertex = theTo instanceof Vertex ? (Vertex) theTo : ((GValue<Vertex>) theTo).get(); - Vertex fromVertex = theFrom instanceof Vertex ? (Vertex) theFrom : ((GValue<Vertex>) theFrom).get(); + Vertex toVertex = GValue.getFrom(theTo); + Vertex fromVertex = GValue.getFrom(theFrom); if (toVertex instanceof Attachable) toVertex = ((Attachable<Vertex>) toVertex) diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java index 07f3fe7f7e..f6aff53c8d 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/GValueTest.java @@ -394,14 +394,14 @@ public class GValueTest { } @Test - public void valueInstanceOfShouldReturnTrueForMatchingType() { - GValue<Integer> gValue = GValue.of(123); + public void ShouldHaveForMatchingType() { + final GValue<Integer> gValue = GValue.of(123); assertThat(GValue.valueInstanceOf(gValue, GType.INTEGER), is(true)); } @Test public void valueInstanceOfShouldReturnFalseForNonMatchingType() { - GValue<Integer> gValue = GValue.of(123); + final GValue<Integer> gValue = GValue.of(123); assertThat(GValue.valueInstanceOf(gValue, GType.STRING), is(false)); } @@ -415,4 +415,64 @@ public class GValueTest { public void valueInstanceOfShouldReturnFalseForNullObject() { assertThat(GValue.valueInstanceOf(null, GType.STRING), is(false)); } + + @Test + public void getShouldReturnGValueValue() { + final GValue<Integer> gValue = GValue.of(123); + assertThat(GValue.getFrom(gValue), is(123)); + } + + @Test + public void getShouldReturnObjectAsIs() { + final String value = "test"; + assertThat(GValue.getFrom(value), is(value)); + } + + @Test + public void getShouldReturnNullForNullInput() { + assertThat(GValue.getFrom(null), is((Object) null)); + } + + @Test + public void valueInstanceOfCollectionShouldReturnTrueForGValueWithCollectionType() { + final GValue<List<String>> gValue = GValue.ofList(Arrays.asList("value1", "value2")); + assertThat(GValue.valueInstanceOfCollection(gValue), is(true)); + } + + @Test + public void valueInstanceOfCollectionShouldReturnFalseForGValueWithNonCollectionType() { + final GValue<Integer> gValue = GValue.of(123); + assertThat(GValue.valueInstanceOfCollection(gValue), is(false)); + } + + @Test + public void valueInstanceOfCollectionShouldReturnFalseForNonGValueObject() { + assertThat(GValue.valueInstanceOfCollection("test"), is(false)); + } + + @Test + public void valueInstanceOfCollectionShouldReturnFalseForNullObject() { + assertThat(GValue.valueInstanceOfCollection(null), is(false)); + } + + @Test + public void valueInstanceOfNumericShouldReturnTrueForGValueWithNumericType() { + final GValue<Integer> gValue = GValue.of(123); + assertThat(GValue.valueInstanceOfNumeric(gValue), is(true)); + } + + @Test + public void valueInstanceOfNumericShouldReturnFalseForGValueWithNonNumericType() { + assertThat(GValue.valueInstanceOfNumeric("test"), is(false)); + } + + @Test + public void valueInstanceOfNumericShouldReturnFalseForNonGValueObject() { + assertThat(GValue.valueInstanceOfNumeric("test"), is(false)); + } + + @Test + public void valueInstanceOfNumericShouldReturnFalseForNullObject() { + assertThat(GValue.valueInstanceOfNumeric(null), is(false)); + } } \ No newline at end of file