Skip to content

Commit f383835

Browse files
committed
PropertySelection nests within Connection/edges/node
Closes gh-723
1 parent 6e1e9b7 commit f383835

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/query/PropertySelection.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.function.Function;
2424

2525
import graphql.schema.DataFetchingFieldSelectionSet;
26+
import graphql.schema.GraphQLNamedOutputType;
2627
import graphql.schema.SelectedField;
2728

2829
import org.springframework.data.mapping.PropertyPath;
@@ -83,6 +84,12 @@ private static List<PropertyPath> getPropertyPaths(
8384
String propertyName = selectedField.getName();
8485
TypeInformation<?> propertyTypeInfo = typeInfo.getProperty(propertyName);
8586
if (propertyTypeInfo == null) {
87+
if (isConnectionEdges(selectedField)) {
88+
getConnectionPropertyPaths(typeInfo, selection, pathFactory, selectedField, result);
89+
}
90+
else if (isConnectionEdgeNode(selectedField)) {
91+
getConnectionPropertyPaths(typeInfo, selection, pathFactory, selectedField, result);
92+
}
8693
continue;
8794
}
8895

@@ -102,6 +109,30 @@ private static List<PropertyPath> getPropertyPaths(
102109
return result;
103110
}
104111

112+
private static boolean isConnectionEdges(SelectedField selectedField) {
113+
return selectedField.getName().equals("edges") &&
114+
selectedField.getParentField().getType() instanceof GraphQLNamedOutputType namedType &&
115+
namedType.getName().endsWith("Connection");
116+
}
117+
118+
private static boolean isConnectionEdgeNode(SelectedField selectedField) {
119+
return selectedField.getName().equals("node") && isConnectionEdges(selectedField.getParentField());
120+
}
121+
122+
private static void getConnectionPropertyPaths(
123+
TypeInformation<?> typeInfo, FieldSelection selection, Function<String, PropertyPath> pathFactory,
124+
SelectedField selectedField, List<PropertyPath> result) {
125+
126+
FieldSelection nestedSelection = selection.select(selectedField);
127+
if (!nestedSelection.isEmpty()) {
128+
TypeInformation<?> actualType = typeInfo.getRequiredActualType();
129+
List<PropertyPath> paths = getPropertyPaths(actualType, nestedSelection, pathFactory);
130+
if (!CollectionUtils.isEmpty(paths)) {
131+
result.addAll(paths);
132+
}
133+
}
134+
}
135+
105136

106137
/**
107138
* Hierarchical representation of selected fields. Allows traversing the
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.data.query;
18+
19+
import java.util.List;
20+
import java.util.concurrent.atomic.AtomicReference;
21+
22+
import graphql.schema.DataFetcher;
23+
import graphql.schema.DataFetchingFieldSelectionSet;
24+
import org.junit.jupiter.api.Test;
25+
26+
import org.springframework.data.util.TypeInformation;
27+
import org.springframework.graphql.BookSource;
28+
import org.springframework.graphql.GraphQlSetup;
29+
import org.springframework.graphql.execution.ConnectionTypeDefinitionConfigurer;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
/**
34+
* Unit test for {@link PropertySelection}.
35+
*
36+
* @author Rossen Stoyanchev
37+
*/
38+
public class PropertySelectionTests {
39+
40+
@Test
41+
void propertySelectionWithConnection() {
42+
43+
AtomicReference<DataFetchingFieldSelectionSet> ref = new AtomicReference<>();
44+
DataFetcher<?> dataFetcher = environment -> {
45+
ref.set(environment.getSelectionSet());
46+
return null;
47+
};
48+
49+
GraphQlSetup.schemaResource(BookSource.paginationSchema)
50+
.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer())
51+
.dataFetcher("Query", "books", dataFetcher)
52+
.toGraphQlService()
53+
.execute(BookSource.booksConnectionQuery(""))
54+
.block();
55+
56+
TypeInformation<Book> typeInfo = TypeInformation.of(Book.class);
57+
58+
List<String> list = PropertySelection.create(typeInfo, ref.get()).toList();
59+
assertThat(list).containsExactly("id", "name");
60+
}
61+
62+
}

0 commit comments

Comments
 (0)