You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2023/06/21 19:43:27 UTC
[tinkerpop] 01/02: wip
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2957
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit e0036006d9724412f2393ff26f25c15a94e1aa83
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Mon Jun 19 11:27:12 2023 -0400
wip
---
.../grammar/DefaultGremlinBaseVisitor.java | 5 ++
.../language/grammar/GenericLiteralVisitor.java | 19 +++++
.../process/traversal/CardinalityValue.java | 81 ++++++++++++++++++++++
.../grammar/GeneralLiteralVisitorTest.java | 34 +++++++++
.../process/traversal/CardinalityValueTest.java | 64 +++++++++++++++++
gremlin-language/src/main/antlr4/Gremlin.g4 | 7 ++
6 files changed, 210 insertions(+)
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 39dac7efa5..e24640eeb1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -1432,4 +1432,9 @@ public class DefaultGremlinBaseVisitor<T> extends AbstractParseTreeVisitor<T> im
* {@inheritDoc}
*/
@Override public T visitTraversalMethod_mergeE_empty(final GremlinParser.TraversalMethod_mergeE_emptyContext ctx) { notImplemented(ctx); return null; }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T visitTraversalCardinalityValue(final GremlinParser.TraversalCardinalityValueContext ctx) { notImplemented(ctx); return null; }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 78d144616f..7e604efe80 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.language.grammar;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.commons.text.StringEscapeUtils;
+import org.apache.tinkerpop.gremlin.process.traversal.CardinalityValue;
import org.apache.tinkerpop.gremlin.process.traversal.Merge;
import org.apache.tinkerpop.gremlin.process.traversal.Pick;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -612,4 +613,22 @@ public class GenericLiteralVisitor extends DefaultGremlinBaseVisitor<Object> {
return result;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object visitTraversalCardinalityValue(final GremlinParser.TraversalCardinalityValueContext ctx) {
+ // could be CardinalityValue.single or single so grab the right child index based on number of children
+ final int idx = ctx.getChildCount() == 5 ? 1 : 0;
+ final String specifiedCard = ctx.children.get(idx).getText();
+ if (specifiedCard.equals(VertexProperty.Cardinality.single.name()))
+ return CardinalityValue.single(visitGenericLiteral(ctx.genericLiteral()));
+ else if (specifiedCard.equals(VertexProperty.Cardinality.list.name()))
+ return CardinalityValue.list(visitGenericLiteral(ctx.genericLiteral()));
+ else if (specifiedCard.equals(VertexProperty.Cardinality.set.name()))
+ return CardinalityValue.set(visitGenericLiteral(ctx.genericLiteral()));
+ else
+ throw new GremlinParserException(String.format(
+ "A CardinalityValue must be defined as one of the available Cardinality values, not %s", specifiedCard));
+ }
}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValue.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValue.java
new file mode 100644
index 0000000000..a2461060ca
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValue.java
@@ -0,0 +1,81 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+import java.util.Objects;
+
+/**
+ * Wraps a {@link VertexProperty.Cardinality} with the value it is associated.
+ */
+public class CardinalityValue<T> {
+
+ private final VertexProperty.Cardinality cardinality;
+
+ private final T value;
+
+ private CardinalityValue(final VertexProperty.Cardinality cardinality, final T value) {
+ this.cardinality = cardinality;
+ this.value = value;
+ }
+
+ public static <T> CardinalityValue<T> single(final T value) {
+ return new CardinalityValue<T>(VertexProperty.Cardinality.single, value);
+ }
+
+ public static <T> CardinalityValue<T> list(final T value) {
+ return new CardinalityValue<T>(VertexProperty.Cardinality.list, value);
+ }
+
+ public static <T> CardinalityValue<T> set(final T value) {
+ return new CardinalityValue<T>(VertexProperty.Cardinality.set, value);
+ }
+
+ public VertexProperty.Cardinality getCardinality() {
+ return cardinality;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CardinalityValue)) return false;
+
+ CardinalityValue<?> that = (CardinalityValue<?>) o;
+
+ if (cardinality != that.cardinality) return false;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = cardinality.hashCode();
+ result = 31 * result + (value != null ? value.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "cv[" + cardinality + ", " + Objects.toString(value) + "]";
+ }
+}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index 1350b03202..7e066adc88 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -20,6 +20,8 @@ package org.apache.tinkerpop.gremlin.language.grammar;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.apache.tinkerpop.gremlin.process.traversal.CardinalityValue;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
@@ -673,4 +675,36 @@ public class GeneralLiteralVisitorTest {
assertEquals(Double.NEGATIVE_INFINITY, GenericLiteralVisitor.instance().visitInfLiteral(ctx));
}
}
+
+ @RunWith(Parameterized.class)
+ public static class CardinalityValueTest {
+ @Parameterized.Parameter(value = 0)
+ public String script;
+
+ @Parameterized.Parameter(value = 1)
+ public CardinalityValue expected;
+
+ @Parameterized.Parameters()
+ public static Iterable<Object[]> generateTestParameters() {
+ return Arrays.asList(new Object[][]{
+ {"single(\"test\")", CardinalityValue.single("test")},
+ {"list(\"test\")", CardinalityValue.list("test")},
+ {"set(\"test\")", CardinalityValue.set("test")},
+ {"CardinalityValue.single(\"test\")", CardinalityValue.single("test")},
+ {"CardinalityValue.list(\"test\")", CardinalityValue.list("test")},
+ {"CardinalityValue.set(\"test\")", CardinalityValue.set("test")},
+ {"single(1l)", CardinalityValue.single(1L)},
+ {"list(1l)", CardinalityValue.list(1L)},
+ {"set(1l)", CardinalityValue.set(1L)},
+ });
+ }
+
+ @Test
+ public void shouldParse() {
+ final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString(script));
+ final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
+ final GremlinParser.TraversalCardinalityValueContext ctx = parser.traversalCardinalityValue();
+ assertEquals(expected, GenericLiteralVisitor.instance().visitTraversalCardinalityValue(ctx));
+ }
+ }
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValueTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValueTest.java
new file mode 100644
index 0000000000..221b13f085
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/CardinalityValueTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class CardinalityValueTest {
+
+ @Test
+ public void shouldCreateSingle() {
+ final CardinalityValue<String> cv = CardinalityValue.single("test");
+ assertEquals("test", cv.getValue());
+ assertEquals(VertexProperty.Cardinality.single, cv.getCardinality());
+ }
+
+ @Test
+ public void shouldCreateSet() {
+ final CardinalityValue<String> cv = CardinalityValue.set("test");
+ assertEquals("test", cv.getValue());
+ assertEquals(VertexProperty.Cardinality.set, cv.getCardinality());
+ }
+
+ @Test
+ public void shouldCreateList() {
+ final CardinalityValue<String> cv = CardinalityValue.list("test");
+ assertEquals("test", cv.getValue());
+ assertEquals(VertexProperty.Cardinality.list, cv.getCardinality());
+ }
+
+ @Test
+ public void shouldBeEqual() {
+ assertEquals(CardinalityValue.single("test"), CardinalityValue.single("test"));
+ assertEquals(CardinalityValue.single(1), CardinalityValue.single(1));
+ assertEquals(CardinalityValue.single(null), CardinalityValue.single(null));
+ }
+
+ @Test
+ public void shouldNotBeEqual() {
+ assertNotEquals(CardinalityValue.single(100), CardinalityValue.single("testing"));
+ assertNotEquals(CardinalityValue.single("test"), CardinalityValue.single("testing"));
+ assertNotEquals(CardinalityValue.single(100), CardinalityValue.single(1));
+ assertNotEquals(CardinalityValue.single("null"), CardinalityValue.single(null));
+ }
+}
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 2e0ce504f5..3f9d7afaf3 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -915,6 +915,12 @@ traversalCardinality
| 'list' | 'Cardinality.list'
;
+traversalCardinalityValue
+ : 'CardinalityValue.'? 'single' LPAREN genericLiteral RPAREN
+ | 'CardinalityValue.'? 'set' LPAREN genericLiteral RPAREN
+ | 'CardinalityValue.'? 'list' LPAREN genericLiteral RPAREN
+ ;
+
traversalColumn
: 'keys' | 'Column.keys'
| 'values' | 'Column.values'
@@ -1376,6 +1382,7 @@ genericLiteral
| infLiteral
// Allow the generic literal to match specific gremlin tokens also
| traversalToken
+ | traversalCardinalityValue
| traversalCardinality
| traversalDirection
| traversalMerge