Skip to content

Commit ad2f45b

Browse files
gkeslerandimarek
authored andcommitted
- further simplified bootstrapping Traverser's initial context
* provided fluent api to add a bootstrap variable or a set of variables
1 parent 6c64ffa commit ad2f45b

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

src/main/java/graphql/analysis/QueryTraversal.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
import static graphql.Assert.assertNotNull;
3737
import static graphql.Assert.assertShouldNeverHappen;
38+
import java.util.Collections;
39+
import java.util.HashMap;
3840

3941
@Internal
4042
public class QueryTraversal {
@@ -112,20 +114,10 @@ private void visitImpl(QueryVisitor visitor, SelectionSet selectionSet, GraphQLC
112114
// we always can obtain the root QueryTraversalContext,
113115
// we are subclassing here TraverserStack to set up a BARRIER
114116
// parent that stores root QueryTraversalContext
115-
new Traverser<Selection>(createStack(context), this::childrenOf)
117+
Traverser.depthFirst(this::childrenOf)
118+
.rootVar(QueryTraversalContext.class, context)
116119
.traverse(selectionSet.getSelections(), null, delegate);
117120
}
118-
119-
private TraverserStack<Selection> createStack (QueryTraversalContext root) {
120-
return new TraverserStack<Selection>() {
121-
@Override
122-
public void addAll(Collection<? extends Selection> col) {
123-
TraverserContext<Selection> rootContext = newContext(null, null)
124-
.setVar(QueryTraversalContext.class, root);
125-
addAll(col, rootContext);
126-
}
127-
};
128-
}
129121

130122
private class QueryTraversalDelegate extends NodeVisitorStub<TraverserContext<Selection>> {
131123

src/main/java/graphql/util/RecursionState.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void addAll(Collection<? extends T> col) {
4141
addAll(col, null);
4242
}
4343

44-
protected void addAll(Collection<? extends T> col, TraverserContext<T> root) {
44+
public void addAll(Collection<? extends T> col, TraverserContext<T> root) {
4545
assertNotNull(col).stream().map((x) -> newContext(x, root)).collect(Collectors.toCollection(() -> delegate));
4646
}
4747

@@ -54,7 +54,13 @@ public void clear() {
5454
visitedMap.clear();
5555
}
5656

57-
public TraverserContext<T> newContext(final T o, final TraverserContext<T> parent) {
57+
public TraverserContext<T> newContext(T o, TraverserContext<T> parent) {
58+
return newContext(o, parent, new ConcurrentHashMap<>());
59+
}
60+
61+
public TraverserContext<T> newContext(T o, TraverserContext<T> parent, Map<Class<?>, Object> vars) {
62+
assertNotNull(vars);
63+
5864
return new TraverserContext<T>() {
5965
@Override
6066
public T thisNode() {
@@ -86,8 +92,6 @@ public <S> TraverserContext<T> setVar(Class<? super S> key, S value) {
8692
vars.put(key, value);
8793
return this;
8894
}
89-
90-
final Map<Class<?>, Object> vars = new HashMap<>();
9195
};
9296
}
9397

src/main/java/graphql/util/Traverser.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
import java.util.function.Function;
99

1010
import static graphql.Assert.assertNotNull;
11+
import java.util.Map;
12+
import java.util.concurrent.ConcurrentHashMap;
1113

1214
@Internal
1315
public class Traverser<T> {
1416

1517
private final RecursionState<T> stack;
1618
private final Function<? super T, ? extends List<T>> getChildren;
19+
private final Map<Class<?>, Object> rootVars = new ConcurrentHashMap<>();
1720

1821
/**
1922
* Instantiates a depth-first Traverser object with a given method to extract
@@ -39,7 +42,32 @@ public Traverser(RecursionState<T> stack, Function<? super T, ? extends List<T>>
3942
this.stack = assertNotNull(stack);
4043
this.getChildren = assertNotNull(getChildren);
4144
}
42-
45+
46+
/**
47+
* Bootstraps the very root (BARRIER) TraverserContext as a common parent for
48+
* all traversal roots' contexts with the provided set of root variables
49+
*
50+
* @param rootVars root variables
51+
* @return this Traverser instance to allow chaining
52+
*/
53+
public Traverser<T> rootVars (Map<Class<?>, Object> rootVars) {
54+
rootVars.putAll(assertNotNull(rootVars));
55+
return this;
56+
}
57+
58+
/**
59+
* Bootstraps the very root (BARRIER) TraverserContext as a common parent for
60+
* all traversal roots' contexts with the provided root variable
61+
*
62+
* @param key key to store root variable
63+
* @param value value of the root variable
64+
* @return this Traverser instance to allow chaining
65+
*/
66+
public Traverser<T> rootVar (Class<?> key, Object value) {
67+
rootVars.put(key, value);
68+
return this;
69+
}
70+
4371
/**
4472
* Creates a standard Traverser suitable for depth-first traversal (both pre- and post- order)
4573
*
@@ -107,7 +135,7 @@ public <U> Object traverse(Collection<T> roots, U data, TraverserVisitor<? super
107135
assertNotNull(roots);
108136
assertNotNull(visitor);
109137

110-
stack.addAll(roots);
138+
stack.addAll(roots, stack.newContext(null, null, rootVars));
111139

112140
Object d = data;
113141
while (!(stack.isEmpty() || (d = traverseOne((TraverserVisitor<T, U>) visitor, (U) d)) == TraverserMarkers.QUIT))

0 commit comments

Comments
 (0)