Skip to content

Commit 277612e

Browse files
author
Vaibhav Malhotra
committed
Added PopContaining interface, and its implementation in Scoping.java
and TraversalParent.java, and classes that use these interfaces.
1 parent b5a2da8 commit 277612e

28 files changed

Lines changed: 407 additions & 328 deletions

CHANGELOG.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
3030
[[release-4-0-0-beta-1]]
3131
=== TinkerPop 4.0.0-beta.1 (January 17, 2025)
3232
33-
* Added a utility function `getScopingInfo()` in all classes implementing `Scoping` and a method `getScopingInfoForTraversal` to get the labels needed by a traversal.
33+
* Added an interface `PopContaining` which is implemented by `Scoping` and `TraversalParent`. Used to get label, and Pop info for a step/traversal. The information is wrapped in a `PopInstruction` object
3434
* Added support for deserialization of `Set` for `gremlin-javascript`.
3535
* Added grammar-based `Translator` for all languages including explicit ones for Java and anonymization.
3636
* Removed old `Translator` infrastructure.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.tinkerpop.gremlin.process.traversal.step;
20+
21+
import java.util.HashSet;
22+
import java.util.Objects;
23+
24+
import org.apache.tinkerpop.gremlin.process.traversal.Pop;
25+
26+
/**
27+
* The {@code PopContaining} interface is implemented by traversal steps that maintain Pop instructions
28+
* for label access. It provides a mechanism to track and manage how labeled elements should
29+
* be accessed using {@link Pop} semantics (first, last, all, or mixed).
30+
*
31+
* In Gremlin traversals, various elements can be labeled and later accessed via these labels.
32+
* The {@link Pop} enum determines how to access these labeled elements when there are multiple
33+
* values associated with the same label.
34+
*
35+
* <pre>
36+
* {@code
37+
* // Simple example with default Pop.last behavior
38+
* gremlin> g.V().as("a").out().as("a").select("a")
39+
* ==>[v[2]] // returns the last element labeled "a"
40+
*
41+
* // Using Pop.first to get the first labeled element
42+
* gremlin> g.V().as("a").out().as("a").select(first, "a")
43+
* ==>[v[1]] // returns the first element labeled "a"
44+
*
45+
* // Using Pop.all to get all labeled elements
46+
* gremlin> g.V().as("a").out().as("a").select(all, "a")
47+
* ==>[v[1], v[2]] // returns all elements labeled "a"
48+
* }
49+
* </pre>
50+
*
51+
* Steps implementing this interface maintain a collection of {@link PopInstruction} objects, each containing
52+
* a label and a {@link Pop} value that specifies how to access elements with that label.
53+
*
54+
* @author Vaibhav Malhotra
55+
*/
56+
public interface PopContaining {
57+
public default HashSet<PopInstruction> getPopInstructions() {
58+
return new HashSet<PopInstruction>();
59+
}
60+
61+
/**
62+
* A class for storing the Scope Context. It has two elements:
63+
* - label: String
64+
* - pop: Pop value
65+
*/
66+
class PopInstruction {
67+
public Pop pop;
68+
public String label;
69+
70+
public PopInstruction(String label, Pop pop) {
71+
this.pop = pop;
72+
this.label = label;
73+
}
74+
75+
public PopInstruction(Pop pop, String label) {
76+
this.pop = pop;
77+
this.label = label;
78+
}
79+
80+
public PopInstruction() {
81+
this.pop = null;
82+
this.label = "";
83+
}
84+
85+
public String getLabel() {
86+
return label;
87+
}
88+
89+
public Pop getPop() {
90+
return pop;
91+
}
92+
93+
@Override
94+
public boolean equals(Object o) {
95+
if (o == null || getClass() != o.getClass()) {
96+
return false;
97+
}
98+
final PopInstruction that = (PopInstruction) o;
99+
return getPop() == that.getPop() && Objects.equals(getLabel(), that.getLabel());
100+
}
101+
102+
@Override
103+
public int hashCode() {
104+
return Objects.hash(getPop(), getLabel());
105+
}
106+
}
107+
}

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/Scoping.java

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import org.apache.tinkerpop.gremlin.process.traversal.Step;
2424
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
2525

26+
import java.util.HashSet;
2627
import java.util.Map;
27-
import java.util.Objects;
2828
import java.util.Set;
2929

3030
/**
@@ -106,7 +106,7 @@
106106
* @author Marko A. Rodriguez (http://markorodriguez.com)
107107
* @author Stephen Mallette (http://stephen.genoprime.com)
108108
*/
109-
public interface Scoping {
109+
public interface Scoping extends PopContaining {
110110

111111
public enum Variable {START, END}
112112

@@ -168,11 +168,21 @@ public default <S> S getNullableScopeValue(final Pop pop, final String key, fina
168168
public Set<String> getScopeKeys();
169169

170170
/**
171-
* Used to get ScopingInfo of a Step that implements Scoping. Scoping info includes the labels it needs, and the pop type for each label.
171+
* Used to get PopInstruction of a Step that implements Scoping. PopInstruction includes the labels it needs, and the
172+
* pop type for each label.
172173
*
173-
* @return A Set of {@link ScopingInfo} values which contain the label and Pop value
174+
* @return A Set of {@link org.apache.tinkerpop.gremlin.process.traversal.step.PopContaining.PopInstruction} values which contain the label and Pop value
174175
*/
175-
public default Set<ScopingInfo> getScopingInfo() {return null; }
176+
@Override
177+
public default HashSet<PopInstruction> getPopInstructions() {
178+
final Set<String> labels = this.getScopeKeys();
179+
final HashSet<PopInstruction> scopingInfoSet = new HashSet<>();
180+
for (String label : labels) {
181+
final PopInstruction scopingInfo = new PopInstruction(Pop.last, label);
182+
scopingInfoSet.add(scopingInfo);
183+
}
184+
return scopingInfoSet;
185+
}
176186

177187
public static class KeyNotFoundException extends Exception {
178188

@@ -193,39 +203,4 @@ public Scoping getStep() {
193203
return step;
194204
}
195205
}
196-
197-
198-
/**
199-
* A class for storing the Scoping information. It has two elements:
200-
* - label: String
201-
* - pop: Pop value
202-
*/
203-
public static class ScopingInfo {
204-
public String label;
205-
public Pop pop;
206-
207-
public ScopingInfo() {
208-
this.label = "";
209-
this.pop = null;
210-
}
211-
212-
public ScopingInfo(String label, Pop pop) {
213-
this.label = label;
214-
this.pop = pop;
215-
}
216-
217-
@Override
218-
public boolean equals(Object o) {
219-
if (o == null || getClass() != o.getClass()) {
220-
return false;
221-
}
222-
ScopingInfo that = (ScopingInfo) o;
223-
return Objects.equals(label, that.label) && pop == that.pop;
224-
}
225-
226-
@Override
227-
public int hashCode() {
228-
return Objects.hash(label, pop);
229-
}
230-
}
231206
}

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/TraversalParent.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@
2121
import org.apache.tinkerpop.gremlin.process.traversal.Step;
2222
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
2323
import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
24+
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
2425

2526
import java.util.Collections;
2627
import java.util.EnumSet;
28+
import java.util.HashSet;
2729
import java.util.List;
2830
import java.util.Set;
2931

3032
/**
3133
* @author Marko A. Rodriguez (http://markorodriguez.com)
3234
*/
33-
public interface TraversalParent extends AutoCloseable {
35+
public interface TraversalParent extends PopContaining, AutoCloseable {
3436

3537
public default <S, E> List<Traversal.Admin<S, E>> getGlobalChildren() {
3638
return Collections.emptyList();
@@ -95,4 +97,16 @@ default void close() throws Exception {
9597
traversal.close();
9698
}
9799
}
100+
101+
@Override
102+
public default HashSet<PopInstruction> getPopInstructions() {
103+
final HashSet<PopInstruction> scopingInfos = new HashSet<>();
104+
for (final Traversal.Admin local: this.getLocalChildren()) {
105+
scopingInfos.addAll(TraversalHelper.getPopInstructions(local));
106+
}
107+
for (final Traversal.Admin global: this.getGlobalChildren()) {
108+
scopingInfos.addAll(TraversalHelper.getPopInstructions(global));
109+
}
110+
return scopingInfos;
111+
}
98112
}

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,11 @@ public Set<String> getScopeKeys() {
190190
}
191191

192192
@Override
193-
public Set<ScopingInfo> getScopingInfo() {
194-
final Set<String> labels = this.getScopeKeys();
195-
final Set<ScopingInfo> scopingInfoSet = new HashSet<>();
196-
for (String label : labels) {
197-
ScopingInfo scopingInfo = new ScopingInfo();
198-
scopingInfo.label = label;
199-
scopingInfo.pop = Pop.last;
200-
scopingInfoSet.add(scopingInfo);
201-
}
202-
return scopingInfoSet;
193+
public HashSet<PopInstruction> getPopInstructions() {
194+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
195+
popInstructions.addAll(Scoping.super.getPopInstructions());
196+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
197+
return popInstructions;
203198
}
204199

205200
@Override

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,11 @@ public Set<String> getScopeKeys() {
133133
}
134134

135135
@Override
136-
public Set<ScopingInfo> getScopingInfo() {
137-
final Set<String> labels = this.getScopeKeys();
138-
final Set<ScopingInfo> scopingInfoSet = new HashSet<>();
139-
for (String label : labels) {
140-
final ScopingInfo scopingInfo = new ScopingInfo();
141-
scopingInfo.label = label;
142-
scopingInfo.pop = Pop.last;
143-
scopingInfoSet.add(scopingInfo);
144-
}
145-
return scopingInfoSet;
136+
public HashSet<PopInstruction> getPopInstructions() {
137+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
138+
popInstructions.addAll(Scoping.super.getPopInstructions());
139+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
140+
return popInstructions;
146141
}
147142

148143
@Override

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTraversalStep.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,11 @@ public Set<String> getKeepLabels() {
148148
}
149149

150150
@Override
151-
public Set<ScopingInfo> getScopingInfo() {
152-
final Set<String> labels = this.getScopeKeys();
153-
final Set<ScopingInfo> scopingInfoSet = new HashSet<>();
154-
for (String label : labels) {
155-
final ScopingInfo scopingInfo = new ScopingInfo();
156-
scopingInfo.label = label;
157-
scopingInfo.pop = Pop.last;
158-
scopingInfoSet.add(scopingInfo);
159-
}
160-
return scopingInfoSet;
151+
public HashSet<PopInstruction> getPopInstructions() {
152+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
153+
popInstructions.addAll(Scoping.super.getPopInstructions());
154+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
155+
return popInstructions;
161156
}
162157

163158
//////////////////////////////

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStartStep.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
4444
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
4545

46+
import java.util.HashSet;
4647
import java.util.List;
4748
import java.util.Set;
4849

@@ -89,6 +90,14 @@ public Set<String> getScopeKeys() {
8990
return this.parameters.getReferencedLabels();
9091
}
9192

93+
@Override
94+
public HashSet<PopInstruction> getPopInstructions() {
95+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
96+
popInstructions.addAll(Scoping.super.getPopInstructions());
97+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
98+
return popInstructions;
99+
}
100+
92101
@Override
93102
public void configure(final Object... keyValues) {
94103
this.parameters.set(this, keyValues);

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddEdgeStep.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
4141
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
4242

43+
import java.util.HashSet;
4344
import java.util.List;
4445
import java.util.Set;
4546

@@ -86,6 +87,14 @@ public Set<String> getScopeKeys() {
8687
return this.parameters.getReferencedLabels();
8788
}
8889

90+
@Override
91+
public HashSet<PopInstruction> getPopInstructions() {
92+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
93+
popInstructions.addAll(Scoping.super.getPopInstructions());
94+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
95+
return popInstructions;
96+
}
97+
8998
@Override
9099
public void configure(final Object... keyValues) {
91100
this.parameters.set(this, keyValues);

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.apache.tinkerpop.gremlin.structure.Vertex;
3939
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
4040

41+
import java.util.HashSet;
4142
import java.util.List;
4243
import java.util.Set;
4344

@@ -85,6 +86,14 @@ public Set<String> getScopeKeys() {
8586
return this.parameters.getReferencedLabels();
8687
}
8788

89+
@Override
90+
public HashSet<PopInstruction> getPopInstructions() {
91+
final HashSet<PopInstruction> popInstructions = new HashSet<>();
92+
popInstructions.addAll(Scoping.super.getPopInstructions());
93+
popInstructions.addAll(TraversalParent.super.getPopInstructions());
94+
return popInstructions;
95+
}
96+
8897
@Override
8998
public <S, E> List<Traversal.Admin<S, E>> getLocalChildren() {
9099
return this.parameters.getTraversals();

0 commit comments

Comments
 (0)