From de306e34c74c25c980f17546ec73935432509bff Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Wed, 6 Dec 2023 11:31:05 -0800 Subject: [PATCH] Implement none() --- .../grammar/DefaultGremlinBaseVisitor.java | 4 + .../grammar/TraversalMethodVisitor.java | 11 +- .../traversal/dsl/graph/GraphTraversal.java | 17 +- .../process/traversal/dsl/graph/__.java | 5 + .../traversal/step/filter/NoneStep.java | 87 +++++++++ .../traversal/util/BytecodeHelper.java | 2 + .../traversal/step/filter/NoneStepTest.java | 105 +++++++++++ .../traversal/step/filter/bugtest.java | 108 +++++++++++ .../Process/Traversal/GraphTraversal.cs | 9 + .../src/Gremlin.Net/Process/Traversal/__.cs | 12 +- .../Gherkin/Gremlin.cs | 13 ++ gremlin-go/driver/anonymousTraversal.go | 7 + gremlin-go/driver/cucumber/gremlin.go | 13 ++ gremlin-go/driver/graphTraversal.go | 6 + .../lib/process/graph-traversal.js | 11 ++ .../test/cucumber/gremlin.js | 13 ++ gremlin-language/src/main/antlr4/Gremlin.g4 | 5 + .../gremlin_python/process/graph_traversal.py | 4 + .../src/main/python/radish/gremlin.py | 13 ++ .../gremlin/test/features/filter/None.feature | 168 ++++++++++++++++++ 20 files changed, 607 insertions(+), 6 deletions(-) create mode 100644 gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java create mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java create mode 100644 gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/bugtest.java create mode 100644 gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature 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 ef6f632f191..f89c3037d98 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 @@ -615,6 +615,10 @@ protected void notImplemented(final ParseTree ctx) { * {@inheritDoc} */ @Override public T visitTraversalMethod_min_Scope(final GremlinParser.TraversalMethod_min_ScopeContext ctx) { notImplemented(ctx); return null; } + /** + * {@inheritDoc} + */ + @Override public T visitTraversalMethod_none_P(final GremlinParser.TraversalMethod_none_PContext ctx) { notImplemented(ctx); return null; } /** * {@inheritDoc} */ 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 d5124e20b33..01e28844765 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 @@ -18,16 +18,13 @@ */ package org.apache.tinkerpop.gremlin.language.grammar; -import org.apache.tinkerpop.gremlin.process.traversal.Merge; import org.apache.tinkerpop.gremlin.process.traversal.Operator; import org.apache.tinkerpop.gremlin.process.traversal.Order; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.structure.VertexProperty.Cardinality; -import java.util.LinkedHashMap; import java.util.Map; - import java.util.function.BiFunction; import static org.apache.tinkerpop.gremlin.process.traversal.SackFunctions.Barrier.normSack; @@ -1082,6 +1079,14 @@ public GraphTraversal visitTraversalMethod_min_Scope(final GremlinParser.Travers return graphTraversal.min(antlr.argumentVisitor.parseScope(ctx.traversalScopeArgument())); } + /** + * {@inheritDoc} + */ + @Override + public GraphTraversal visitTraversalMethod_none_P(final GremlinParser.TraversalMethod_none_PContext ctx) { + return graphTraversal.none(antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate())); + } + /** * {@inheritDoc} */ diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java index 47620276812..b7839868637 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java @@ -68,6 +68,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep; @@ -171,6 +172,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.sideEffect.AggregateGlobalStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.FailStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep; @@ -182,7 +184,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SackValueStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectCapStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.StartStep; -import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateLocalStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SubgraphStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TraversalSideEffectStep; import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.TreeSideEffectStep; @@ -2829,6 +2830,19 @@ public default GraphTraversal any(final P predicate) { return this.asAdmin().addStep(new AnyStep<>(this.asAdmin(), predicate)); } + /** + * Filters E lists given the provided {@code predicate}. + * + * @param predicate the filter to apply + * @return the traversal with an appended {@link NoneStep} + * @see Reference Documentation - None Step + * @since 4.0.0 + */ + public default GraphTraversal none(final P predicate) { + this.asAdmin().getBytecode().addStep(Symbols.none, predicate); + return this.asAdmin().addStep(new NoneStep<>(this.asAdmin(), predicate)); + } + ///////////////////// SIDE-EFFECT STEPS ///////////////////// /** @@ -4078,6 +4092,7 @@ private Symbols() { public static final String dateDiff = "dateDiff"; public static final String all = "all"; public static final String any = "any"; + public static final String none = "none"; public static final String merge = "merge"; public static final String product = "product"; public static final String combine = "combine"; diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java index 5a662c4eadb..e0443586267 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java @@ -1195,6 +1195,11 @@ public static GraphTraversal drop() { */ public static GraphTraversal any(final P predicate) { return __.start().any(predicate); } + /** + * @see GraphTraversal#none(P) + */ + public static GraphTraversal none(final P predicate) { return __.start().none(predicate); } + ///////////////////// SIDE-EFFECT STEPS ///////////////////// /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java new file mode 100644 index 00000000000..a2f4ee103d2 --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java @@ -0,0 +1,87 @@ +/* + * 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.filter; + +import org.apache.tinkerpop.gremlin.process.traversal.GremlinTypeErrorException; +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; +import org.apache.tinkerpop.gremlin.structure.util.StringFactory; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; + +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; + +public final class NoneStep extends FilterStep { + + private P predicate; + + public NoneStep(final Traversal.Admin traversal, final P predicate) { + super(traversal); + + if (null == predicate) { + throw new IllegalArgumentException("Input predicate to none step can't be null."); + } + + this.predicate = predicate; + } + + @Override + protected boolean filter(final Traverser.Admin traverser) { + final S item = traverser.get(); + + if (item instanceof Iterable || item instanceof Iterator || ((item != null) && item.getClass().isArray())) { + GremlinTypeErrorException typeError = null; + final Iterator iterator = IteratorUtils.asIterator(item); + while (iterator.hasNext()) { + try { + if (this.predicate.test(iterator.next())) { + return false; + } + } catch (GremlinTypeErrorException gtee) { + // hold onto it until the end in case any other element evaluates to TRUE + typeError = gtee; + } + } + if (typeError != null) throw typeError; + return true; + } + + return false; + } + + @Override + public String toString() { + return StringFactory.stepString(this, this.predicate); + } + + @Override + public NoneStep clone() { + final NoneStep clone = (NoneStep) super.clone(); + clone.predicate = this.predicate.clone(); + return clone; + } + + @Override + public Set getRequirements() { + return EnumSet.of(TraverserRequirement.OBJECT); + } +} diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java index aca26d11dc0..534a36bc2f3 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java @@ -48,6 +48,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.LambdaFilterStep; +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NoneStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep; import org.apache.tinkerpop.gremlin.process.traversal.step.filter.PathFilterStep; @@ -248,6 +249,7 @@ public final class BytecodeHelper { put(GraphTraversal.Symbols.dateDiff, Collections.singletonList(DateDiffStep.class)); put(GraphTraversal.Symbols.all, Collections.singletonList(AllStep.class)); put(GraphTraversal.Symbols.any, Collections.singletonList(AnyStep.class)); + put(GraphTraversal.Symbols.none, Collections.singletonList(NoneStep.class)); put(GraphTraversal.Symbols.combine, Collections.singletonList(CombineStep.class)); put(GraphTraversal.Symbols.difference, Collections.singletonList(DifferenceStep.class)); put(GraphTraversal.Symbols.disjunct, Collections.singletonList(DisjunctStep.class)); diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java new file mode 100644 index 00000000000..ef10a7b6807 --- /dev/null +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStepTest.java @@ -0,0 +1,105 @@ +/* + * 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.filter; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.TextP; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.any; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +public class NoneStepTest extends StepTest { + + @Override + protected List getTraversals() { return Collections.singletonList(__.none(P.gt(0))); } + + @Test + public void testReturnTypes() { + assertTrue(__.__(new int[]{}).none(P.gt(7)).hasNext()); + assertArrayEquals(new int[] {5, 6}, __.__(new int[] {5, 8, 10}, new int[] {5, 6}).not(any(P.gte(7))).next()); + assertArrayEquals(new long[] {5L, 6L}, __.__(new long[] {5L, 8L, 10L}, new long[] {5L, 6L}).none(P.gte(7)).next()); + assertArrayEquals(new Long[] {5L, 6L}, __.__(1).constant(new Long[] {5L, 6L}).none(P.gte(7)).next()); + assertArrayEquals(new double[] {5.1, 6.5}, __.__(new double[] {5.5, 8.0, 10.1}, new double[] {5.1, 6.5}).none(P.gte(7.0)).next(), 0.01); + } + + @Test + public void testNullParameter() { + final Throwable thrown = assertThrows(IllegalArgumentException.class, () -> __.__(new int[]{1}).none(null).hasNext()); + assertEquals("Input predicate to none step can't be null.", thrown.getMessage()); + } + + @Test + public void testSetTraverser() { + final Set numbers = new HashSet<>(); + numbers.add(5); + numbers.add(6); + + assertTrue(__.__(numbers).none(P.gt(7)).hasNext()); + } + + @Test + public void testListIteratorTraverser() { + final List numbers = new ArrayList<>(); + numbers.add(10); + numbers.add(11); + + assertTrue(__.__(numbers.iterator()).none(P.lt(10)).hasNext()); + } + + @Test + public void testCornerCases() { + final List validOne = new ArrayList() {{ add(20); }}; + final List validTwo = new ArrayList() {{ add(21); add(25);}}; + final List validThree = new ArrayList() {{ add(51); add(57); add(71); }}; + final List containsNull = new ArrayList() {{ add(50); add(null); add(60); }}; + final List containsNull2 = new ArrayList() {{ add(1); add(null); add(2); }}; + final List empty = new ArrayList(); + final List incorrectType = new ArrayList() {{ add(100); add("25"); }}; + final List valueTooSmall = new ArrayList() {{ add(101); add(1); add(10);}}; + + final List bcd = new ArrayList() {{ add(null); add("bcd"); }}; + final List bcdnull = new ArrayList() {{ add("bcd"); }}; + final List abc = new ArrayList() {{ add("abc"); }}; + final List abcnull = new ArrayList() {{ add("abc"); add(null); }}; + + assertEquals(4L, __.__(validOne, null, containsNull, empty, incorrectType, valueTooSmall, validTwo, validThree) + .none(P.lte(3)).count().next().longValue()); + assertEquals(1L, __.__(bcd).none(TextP.startingWith("a")).count().next().longValue()); // e 0 a 0 + assertEquals(1L, __.__(bcdnull).none(TextP.startingWith("a")).count().next().longValue()); // actual 1 + assertEquals(0L, __.__(abc).none(TextP.startingWith("a")).count().next().longValue()); // actual 0 + assertEquals(0L, __.__(abcnull).none(TextP.startingWith("a")).count().next().longValue()); // actual 0 + + assertEquals(1L, __.__(bcd).all(TextP.startingWith("a")).count().next().longValue()); // actual 0 + assertEquals(1L, __.__(bcdnull).all(TextP.startingWith("a")).count().next().longValue()); // actual 1 + assertEquals(0L, __.__(abcnull).all(TextP.startingWith("a")).count().next().longValue()); // actual 0 + } +} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/bugtest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/bugtest.java new file mode 100644 index 00000000000..c121ce63fa8 --- /dev/null +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/bugtest.java @@ -0,0 +1,108 @@ +/* + * 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.filter; + +import org.apache.tinkerpop.gremlin.process.traversal.P; +import org.apache.tinkerpop.gremlin.process.traversal.TextP; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class bugtest extends StepTest { + + @Override + protected List getTraversals() { return Collections.singletonList(__.none(P.gt(0))); } + + final List bcd = new ArrayList() {{ add("bcd"); }}; + final List bcdnull = new ArrayList() {{ add(null); add("bcd"); }}; + final List abc = new ArrayList() {{ add("abc"); }}; + final List abcnull = new ArrayList() {{ add("abc"); add(null); }}; + + @Test + public void bcdnull_textpeq_a() { + assertEquals(1L, __.__(bcdnull).none(TextP.eq("a")).count().next().longValue()); + } + @Test + public void bcdnull_textpeq_bcd() { + assertEquals(0L, __.__(bcdnull).none(TextP.eq("bcd")).count().next().longValue()); + } + @Test + public void bcdnull_eq_a() { + assertEquals(1L, __.__(bcdnull).none(P.eq("a")).count().next().longValue()); + } + @Test + public void bcdnull_eq_bcd() { + assertEquals(0L, __.__(bcdnull).none(P.eq("bcd")).count().next().longValue()); + } + @Test + public void bcd() { + assertEquals(1L, __.__(bcd).none(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void bcdnull() { + assertEquals(1L, __.__(bcdnull).none(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abc() { + assertEquals(0L, __.__(abc).none(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abcnull() { + assertEquals(0L, __.__(abcnull).none(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void bcd_all() { + assertEquals(0L, __.__(bcd).all(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void bcdnull_all() { + assertEquals(0L, __.__(bcdnull).all(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abc_all() { + assertEquals(1L, __.__(abc).all(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abcnull_all() { + assertEquals(0L, __.__(abcnull).all(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void bcd_any() { + assertEquals(0L, __.__(bcd).any(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void bcdnull_any() { + assertEquals(0L, __.__(bcdnull).any(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abc_any() { + assertEquals(1L, __.__(abc).any(TextP.startingWith("a")).count().next().longValue()); + } + @Test + public void abcnull_any() { + assertEquals(1L, __.__(abcnull).any(TextP.startingWith("a")).count().next().longValue()); + } +} diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs index 8b1b4a74535..34a3341ca1a 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs @@ -1500,6 +1500,15 @@ public GraphTraversal Min (Scope scope) return Wrap(this); } + /// + /// Adds the none step to this . + /// + public GraphTraversal None (P? predicate) + { + Bytecode.AddStep("none", predicate); + return Wrap(this); + } + /// /// Adds the not step to this . /// diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs index 0c28513a011..f04d9d7018a 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs @@ -117,7 +117,7 @@ public static GraphTraversal Aggregate(string sideEffectKey) } /// - /// Spawns a all adds the all step to that traversal. + /// Spawns a and adds the all step to that traversal. /// public static GraphTraversal All(P? predicate) { @@ -135,7 +135,7 @@ public static GraphTraversal And(params ITraversal[] andTraversa } /// - /// Spawns a any adds the any step to that traversal. + /// Spawns a and adds the any step to that traversal. /// public static GraphTraversal Any(P? predicate) { @@ -1096,6 +1096,14 @@ public static GraphTraversal Min(Scope scope) return new GraphTraversal().Min(scope); } + /// + /// Spawns a and adds the none step to that traversal. + /// + public static GraphTraversal None(P? predicate) + { + return new GraphTraversal().None(predicate); + } + /// /// Spawns a and adds the not step to that traversal. /// diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs index 505f6e64e09..f19a69f78ff 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs @@ -315,6 +315,19 @@ private static IDictionary, ITraversal>> {(g,p) =>g.V().Values("age").Is(P.Gte(29)).Is(P.Lt(34))}}, {"g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(1)).Values("name")}}, {"g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX", new List, ITraversal>> {(g,p) =>g.V().Where(__.In("created").Count().Is(P.Gte(2))).Values("name")}}, + {"g_V_valuesXageX_noneXgtX32XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").None(P.Gt(32))}}, + {"g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Where(__.Is(P.Gt(33))).Fold().None(P.Lte(33))}}, + {"g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Order().By(Order.Desc).Fold().None(P.Lt(10))}}, + {"g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX", new List, ITraversal>> {(g,p) =>g.V().Values("age").Order().By(Order.Desc).Fold().None(P.Gt(30))}}, + {"g_injectXabc_bcdX_noneXeqXbcdXX", new List, ITraversal>> {(g,p) =>g.Inject(new List {"abc", "bcd"}).None(P.Eq("bcd"))}}, + {"g_injectXbcd_bcdX_noneXeqXabcXX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).None(P.Eq("abc"))}}, + {"g_injectXnull_bcdX_noneXTextP_startingWithXaXX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).None(TextP.StartingWith("a"))}}, + {"g_injectX5_8_10_10_7X_noneXltX7XX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"],p["xx2"]).None(P.Lt(7))}}, + {"g_injectXnullX_noneXeqXnullXX", new List, ITraversal>> {(g,p) =>g.Inject(null).None(P.Eq(null))}}, + {"g_injectX7X_noneXeqX7XX", new List, ITraversal>> {(g,p) =>g.Inject(7).None(P.Eq(7))}}, + {"g_injectXnull_1_emptyX_noneXeqXnullXX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"],p["xx2"]).None(P.Eq(null))}}, + {"g_injectXnull_nullX_noneXnotXnullXX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).None(P.Neq(null))}}, + {"g_injectX3_threeX_noneXeqX3XX", new List, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).None(P.Eq(3))}}, {"g_V_orXhasXage_gt_27X__outE_count_gte_2X_name", new List, ITraversal>> {(g,p) =>g.V().Or(__.Has("age",P.Gt(27)),__.OutE().Count().Is(P.Gte(2))).Values("name")}}, {"g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name", new List, ITraversal>> {(g,p) =>g.V().Or(__.OutE("knows"),__.Has(T.Label,"software").Or().Has("age",P.Gte(35))).Values("name")}}, {"g_V_asXaX_orXselectXaX_selectXaXX", new List, ITraversal>> {(g,p) =>g.V().As("a").Or(__.Select("a"),__.Select("a"))}}, diff --git a/gremlin-go/driver/anonymousTraversal.go b/gremlin-go/driver/anonymousTraversal.go index a766c4983cc..504917c00da 100644 --- a/gremlin-go/driver/anonymousTraversal.go +++ b/gremlin-go/driver/anonymousTraversal.go @@ -207,6 +207,8 @@ type AnonymousTraversal interface { MergeV(args ...interface{}) *GraphTraversal // Min adds the min step to the GraphTraversal. Min(args ...interface{}) *GraphTraversal + // None adds the none step to the GraphTraversal. + None(args ...interface{}) *GraphTraversal // Not adds the not step to the GraphTraversal. Not(args ...interface{}) *GraphTraversal // Option adds the option step to the GraphTraversal. @@ -726,6 +728,11 @@ func (anonymousTraversal *anonymousTraversal) Min(args ...interface{}) *GraphTra return anonymousTraversal.graphTraversal().Min(args...) } +// None adds the none step to the GraphTraversal. +func (anonymousTraversal *anonymousTraversal) None(args ...interface{}) *GraphTraversal { + return anonymousTraversal.graphTraversal().None(args...) +} + // Not adds the not step to the GraphTraversal. func (anonymousTraversal *anonymousTraversal) Not(args ...interface{}) *GraphTraversal { return anonymousTraversal.graphTraversal().Not(args...) diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go index e3f932b4123..d6a9d01c747 100644 --- a/gremlin-go/driver/cucumber/gremlin.go +++ b/gremlin-go/driver/cucumber/gremlin.go @@ -286,6 +286,19 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[ "g_V_valuesXageX_isXgte_29X_isXlt_34X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Is(gremlingo.P.Gte(29)).Is(gremlingo.P.Lt(34))}}, "g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(1)).Values("name")}}, "g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Where(gremlingo.T__.In("created").Count().Is(gremlingo.P.Gte(2))).Values("name")}}, + "g_V_valuesXageX_noneXgtX32XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").None(gremlingo.P.Gt(32))}}, + "g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Where(gremlingo.T__.Is(gremlingo.P.Gt(33))).Fold().None(gremlingo.P.Lte(33))}}, + "g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().None(gremlingo.P.Lt(10))}}, + "g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("age").Order().By(gremlingo.Order.Desc).Fold().None(gremlingo.P.Gt(30))}}, + "g_injectXabc_bcdX_noneXeqXbcdXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject([]interface{}{"abc", "bcd"}).None(gremlingo.P.Eq("bcd"))}}, + "g_injectXbcd_bcdX_noneXeqXabcXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Eq("abc"))}}, + "g_injectXnull_bcdX_noneXTextP_startingWithXaXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.TextP.StartingWith("a"))}}, + "g_injectX5_8_10_10_7X_noneXltX7XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx2"]).None(gremlingo.P.Lt(7))}}, + "g_injectXnullX_noneXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(nil).None(gremlingo.P.Eq(nil))}}, + "g_injectX7X_noneXeqX7XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(7).None(gremlingo.P.Eq(7))}}, + "g_injectXnull_1_emptyX_noneXeqXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"], p["xx2"]).None(gremlingo.P.Eq(nil))}}, + "g_injectXnull_nullX_noneXnotXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Neq(nil))}}, + "g_injectX3_threeX_noneXeqX3XX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(p["xx1"]).None(gremlingo.P.Eq(3))}}, "g_V_orXhasXage_gt_27X__outE_count_gte_2X_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Or(gremlingo.T__.Has("age", gremlingo.P.Gt(27)), gremlingo.T__.OutE().Count().Is(gremlingo.P.Gte(2))).Values("name")}}, "g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Or(gremlingo.T__.OutE("knows"), gremlingo.T__.Has(gremlingo.T.Label, "software").Or().Has("age", gremlingo.P.Gte(35))).Values("name")}}, "g_V_asXaX_orXselectXaX_selectXaXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().As("a").Or(gremlingo.T__.Select("a"), gremlingo.T__.Select("a"))}}, diff --git a/gremlin-go/driver/graphTraversal.go b/gremlin-go/driver/graphTraversal.go index d0a6403876c..657e5ea9881 100644 --- a/gremlin-go/driver/graphTraversal.go +++ b/gremlin-go/driver/graphTraversal.go @@ -524,6 +524,12 @@ func (g *GraphTraversal) Min(args ...interface{}) *GraphTraversal { return g } +// None adds the none step to the GraphTraversal. +func (g *GraphTraversal) None(args ...interface{}) *GraphTraversal { + g.Bytecode.AddStep("none", args...) + return g +} + // Not adds the not step to the GraphTraversal. func (g *GraphTraversal) Not(args ...interface{}) *GraphTraversal { g.Bytecode.AddStep("not", args...) diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js index 3992e0db24d..f2dee066003 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js @@ -1121,6 +1121,16 @@ class GraphTraversal extends Traversal { return this; } + /** + * Graph traversal none method. + * @param {...Object} args + * @returns {GraphTraversal} + */ + none(...args) { + this.bytecode.addStep('none', args); + return this; + } + /** * Graph traversal not method. * @param {...Object} args @@ -1799,6 +1809,7 @@ const statics = { mergeE: (...args) => callOnEmptyTraversal('mergeE', args), mergeV: (...args) => callOnEmptyTraversal('mergeV', args), min: (...args) => callOnEmptyTraversal('min', args), + none: (...args) => callOnEmptyTraversal('none', args), not: (...args) => callOnEmptyTraversal('not', args), optional: (...args) => callOnEmptyTraversal('optional', args), or: (...args) => callOnEmptyTraversal('or', args), diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js index 8b3b9542f5d..a371e9a4b3f 100644 --- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js +++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js @@ -306,6 +306,19 @@ const gremlins = { g_V_valuesXageX_isXgte_29X_isXlt_34X: [function({g}) { return g.V().values("age").is(P.gte(29)).is(P.lt(34)) }], g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(1)).values("name") }], g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX: [function({g}) { return g.V().where(__.in_("created").count().is(P.gte(2))).values("name") }], + g_V_valuesXageX_noneXgtX32XX: [function({g}) { return g.V().values("age").none(P.gt(32)) }], + g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX: [function({g}) { return g.V().values("age").where(__.is(P.gt(33))).fold().none(P.lte(33)) }], + g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().none(P.lt(10)) }], + g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX: [function({g}) { return g.V().values("age").order().by(Order.desc).fold().none(P.gt(30)) }], + g_injectXabc_bcdX_noneXeqXbcdXX: [function({g}) { return g.inject(["abc", "bcd"]).none(P.eq("bcd")) }], + g_injectXbcd_bcdX_noneXeqXabcXX: [function({g, xx1}) { return g.inject(xx1).none(P.eq("abc")) }], + g_injectXnull_bcdX_noneXTextP_startingWithXaXX: [function({g, xx1}) { return g.inject(xx1).none(TextP.startingWith("a")) }], + g_injectX5_8_10_10_7X_noneXltX7XX: [function({g, xx1, xx2}) { return g.inject(xx1,xx2).none(P.lt(7)) }], + g_injectXnullX_noneXeqXnullXX: [function({g}) { return g.inject(null).none(P.eq(null)) }], + g_injectX7X_noneXeqX7XX: [function({g}) { return g.inject(7).none(P.eq(7)) }], + g_injectXnull_1_emptyX_noneXeqXnullXX: [function({g, xx1, xx2}) { return g.inject(xx1,xx2).none(P.eq(null)) }], + g_injectXnull_nullX_noneXnotXnullXX: [function({g, xx1}) { return g.inject(xx1).none(P.neq(null)) }], + g_injectX3_threeX_noneXeqX3XX: [function({g, xx1}) { return g.inject(xx1).none(P.eq(3)) }], g_V_orXhasXage_gt_27X__outE_count_gte_2X_name: [function({g}) { return g.V().or(__.has("age",P.gt(27)),__.outE().count().is(P.gte(2))).values("name") }], g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name: [function({g}) { return g.V().or(__.outE("knows"),__.has(T.label,"software").or().has("age",P.gte(35))).values("name") }], g_V_asXaX_orXselectXaX_selectXaXX: [function({g}) { return g.V().as("a").or(__.select("a"),__.select("a")) }], diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4 index 4cb4c076b73..107396547b9 100644 --- a/gremlin-language/src/main/antlr4/Gremlin.g4 +++ b/gremlin-language/src/main/antlr4/Gremlin.g4 @@ -240,6 +240,7 @@ traversalMethod | traversalMethod_max | traversalMethod_mean | traversalMethod_min + | traversalMethod_none | traversalMethod_not | traversalMethod_option | traversalMethod_optional @@ -626,6 +627,10 @@ traversalMethod_min | 'min' LPAREN traversalScopeArgument RPAREN #traversalMethod_min_Scope ; +traversalMethod_none + : 'none' LPAREN traversalPredicate RPAREN #traversalMethod_none_P + ; + traversalMethod_not : 'not' LPAREN nestedTraversal RPAREN ; diff --git a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py index a5466669ed0..87ea849feb7 100644 --- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py +++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py @@ -1440,6 +1440,10 @@ def merge_v(cls, *args): def min_(cls, *args): return cls.graph_traversal(None, None, Bytecode()).min_(*args) + @classmethod + def none(cls, *args): + return cls.graph_traversal(None, None, Bytecode()).none(*args) + @classmethod def not_(cls, *args): return cls.graph_traversal(None, None, Bytecode()).not_(*args) diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py index b028c17af1d..6950d05a42b 100644 --- a/gremlin-python/src/main/python/radish/gremlin.py +++ b/gremlin-python/src/main/python/radish/gremlin.py @@ -288,6 +288,19 @@ 'g_V_valuesXageX_isXgte_29X_isXlt_34X': [(lambda g:g.V().age.is_(P.gte(29)).is_(P.lt(34)))], 'g_V_whereXinXcreatedX_count_isX1XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(1)).name)], 'g_V_whereXinXcreatedX_count_isXgte_2XX_valuesXnameX': [(lambda g:g.V().where(__.in_('created').count().is_(P.gte(2))).name)], + 'g_V_valuesXageX_noneXgtX32XX': [(lambda g:g.V().age.none(P.gt(32)))], + 'g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX': [(lambda g:g.V().age.where(__.is_(P.gt(33))).fold().none(P.lte(33)))], + 'g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX': [(lambda g:g.V().age.order().by(Order.desc).fold().none(P.lt(10)))], + 'g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX': [(lambda g:g.V().age.order().by(Order.desc).fold().none(P.gt(30)))], + 'g_injectXabc_bcdX_noneXeqXbcdXX': [(lambda g:g.inject(['abc','bcd']).none(P.eq('bcd')))], + 'g_injectXbcd_bcdX_noneXeqXabcXX': [(lambda g, xx1=None:g.inject(xx1).none(P.eq('abc')))], + 'g_injectXnull_bcdX_noneXTextP_startingWithXaXX': [(lambda g, xx1=None:g.inject(xx1).none(TextP.startingWith('a')))], + 'g_injectX5_8_10_10_7X_noneXltX7XX': [(lambda g, xx1=None,xx2=None:g.inject(xx1,xx2).none(P.lt(7)))], + 'g_injectXnullX_noneXeqXnullXX': [(lambda g:g.inject(None).none(P.eq(None)))], + 'g_injectX7X_noneXeqX7XX': [(lambda g:g.inject(7).none(P.eq(7)))], + 'g_injectXnull_1_emptyX_noneXeqXnullXX': [(lambda g, xx1=None,xx2=None:g.inject(xx1,xx2).none(P.eq(None)))], + 'g_injectXnull_nullX_noneXnotXnullXX': [(lambda g, xx1=None:g.inject(xx1).none(P.neq(None)))], + 'g_injectX3_threeX_noneXeqX3XX': [(lambda g, xx1=None:g.inject(xx1).none(P.eq(3)))], 'g_V_orXhasXage_gt_27X__outE_count_gte_2X_name': [(lambda g:g.V().or_(__.has('age',P.gt(27)),__.outE().count().is_(P.gte(2))).name)], 'g_V_orXoutEXknowsX__hasXlabel_softwareX_or_hasXage_gte_35XX_name': [(lambda g:g.V().or_(__.outE('knows'),__.has(T.label,'software').or_().has('age',P.gte(35))).name)], 'g_V_asXaX_orXselectXaX_selectXaXX': [(lambda g:g.V().as_('a').or_(__.select('a'),__.select('a')))], diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature new file mode 100644 index 00000000000..b16ec5fc68f --- /dev/null +++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/filter/None.feature @@ -0,0 +1,168 @@ +# 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. + +@StepClassFilter @StepNone +Feature: Step - none() + + Scenario: g_V_valuesXageX_noneXgtX32XX + Given the modern graph + And the traversal of + """ + g.V().values("age").none(P.gt(32)) + """ + When iterated to list + Then the result should be empty + + Scenario: g_V_valuesXageX_whereXisXP_gtX33XXX_fold_noneXlteX33XX + Given the modern graph + And the traversal of + """ + g.V().values("age").where(__.is(P.gt(33))).fold().none(P.lte(33)) + """ + When iterated to list + Then the result should be unordered + | result | + | l[d[35].i] | + + Scenario: g_V_valuesXageX_order_byXdescX_fold_noneXltX10XX + Given the modern graph + And the traversal of + """ + g.V().values("age").order().by(desc).fold().none(P.lt(10)) + """ + When iterated to list + Then the result should be unordered + | result | + | l[d[35].i,d[32].i,d[29].i,d[27].i] | + + Scenario: g_V_valuesXageX_order_byXdescX_fold_noneXgtX30XX + Given the modern graph + And the traversal of + """ + g.V().values("age").order().by(desc).fold().none(P.gt(30)) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXabc_bcdX_noneXeqXbcdXX + Given the empty graph + And the traversal of + """ + g.inject(["abc","bcd"]).none(P.eq("bcd")) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXbcd_bcdX_noneXeqXabcXX + Given the empty graph + And using the parameter xx1 defined as "l[bcd,bcd]" + And the traversal of + """ + g.inject(xx1).none(P.eq("abc")) + """ + When iterated to list + Then the result should be unordered + | result | + | l[bcd,bcd] | + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXnull_bcdX_noneXP_eqXabcXX + Given the empty graph + And using the parameter xx1 defined as "l[null,bcd]" + And the traversal of + """ + g.inject(xx1).none(P.eq("abc")) + """ + When iterated to list + Then the result should be unordered + | result | + | l[null,bcd] | + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectX5_8_10_10_7X_noneXltX7XX + Given the empty graph + And using the parameter xx1 defined as "l[d[5].i,d[8].i,d[10].i]" + And using the parameter xx2 defined as "l[d[10].i,d[7].i]" + And the traversal of + """ + g.inject(xx1,xx2).none(P.lt(7)) + """ + When iterated to list + Then the result should be unordered + | result | + | l[d[10].i,d[7].i] | + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXnullX_noneXeqXnullXX + Given the empty graph + And the traversal of + """ + g.inject(null).none(P.eq(null)) + """ + When iterated to list + Then the result should be empty + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectX7X_noneXeqX7XX + Given the empty graph + And the traversal of + """ + g.inject(7).none(P.eq(7)) + """ + When iterated to list + Then the result should be empty + + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXnull_1_emptyX_noneXeqXnullXX + Given the empty graph + And using the parameter xx1 defined as "l[null,1]" + And using the parameter xx2 defined as "l[]" + And the traversal of + """ + g.inject(xx1,xx2).none(P.eq(null)) + """ + When iterated to list + Then the result should be unordered + | result | + | l[] | + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectXnull_nullX_noneXnotXnullXX + Given the empty graph + And using the parameter xx1 defined as "l[null,null]" + And the traversal of + """ + g.inject(xx1).none(P.neq(null)) + """ + When iterated to list + Then the result should be unordered + | result | + | l[null,null] | + + @GraphComputerVerificationInjectionNotSupported + Scenario: g_injectX3_threeX_noneXeqX3XX + Given the empty graph + And using the parameter xx1 defined as "l[d[3].i,three]" + And the traversal of + """ + g.inject(xx1).none(P.eq(3)) + """ + When iterated to list + Then the result should be empty \ No newline at end of file