Improve "Connection" Java type checks
ConnectionFieldTypeVisitor now also checks if the container type ends on "Connection", and if so it lets it pass through. See gh-709
This commit is contained in:
@@ -62,15 +62,15 @@ final class CompositeConnectionAdapter implements ConnectionAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionAdapter getRequiredAdapter(Object container) {
|
private ConnectionAdapter getRequiredAdapter(Object container) {
|
||||||
ConnectionAdapter adapter = getAdapter(container);
|
ConnectionAdapter adapter = getAdapter(container.getClass());
|
||||||
Assert.notNull(adapter, "No ConnectionAdapter for: " + container.getClass().getName());
|
Assert.notNull(adapter, "No ConnectionAdapter for: " + container.getClass().getName());
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ConnectionAdapter getAdapter(Object container) {
|
private ConnectionAdapter getAdapter(Class<?> containerType) {
|
||||||
for (ConnectionAdapter adapter : this.adapters) {
|
for (ConnectionAdapter adapter : this.adapters) {
|
||||||
if (adapter.supports(container.getClass())) {
|
if (adapter.supports(containerType)) {
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,19 +195,24 @@ public final class ConnectionFieldTypeVisitor extends GraphQLTypeVisitorStub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private <T> Object adapt(@Nullable Object container) {
|
||||||
private <T> Connection<T> adapt(@Nullable Object container) {
|
if (container == null) {
|
||||||
if (container instanceof Connection<?> connection) {
|
return EMPTY_CONNECTION;
|
||||||
return (Connection<T>) connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<T> nodes = (container != null ?
|
if (container instanceof Connection<?>) {
|
||||||
this.adapter.getContent(container) : Collections.emptyList());
|
return container;
|
||||||
|
|
||||||
if (nodes.isEmpty()) {
|
|
||||||
return (Connection<T>) EMPTY_CONNECTION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.adapter.supports(container.getClass())) {
|
||||||
|
if (container.getClass().getName().endsWith("Connection")) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"No ConnectionAdapter for: " + container.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<T> nodes = this.adapter.getContent(container);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
List<Edge<T>> edges = new ArrayList<>(nodes.size());
|
List<Edge<T>> edges = new ArrayList<>(nodes.size());
|
||||||
for (T node : nodes) {
|
for (T node : nodes) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.graphql.Book;
|
||||||
import org.springframework.graphql.BookSource;
|
import org.springframework.graphql.BookSource;
|
||||||
import org.springframework.graphql.ExecutionGraphQlResponse;
|
import org.springframework.graphql.ExecutionGraphQlResponse;
|
||||||
import org.springframework.graphql.GraphQlSetup;
|
import org.springframework.graphql.GraphQlSetup;
|
||||||
@@ -51,7 +52,7 @@ public class ConnectionFieldTypeVisitorTests {
|
|||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void paginationDataFetcher() {
|
void paginatedTypeIsAdapted() {
|
||||||
|
|
||||||
ListConnectionAdapter adapter = new ListConnectionAdapter();
|
ListConnectionAdapter adapter = new ListConnectionAdapter();
|
||||||
adapter.setInitialOffset(30);
|
adapter.setInitialOffset(30);
|
||||||
@@ -83,6 +84,39 @@ public class ConnectionFieldTypeVisitorTests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-709
|
||||||
|
void customConnectionTypeIsPassedThrough() {
|
||||||
|
|
||||||
|
List<MyEdge<Book>> edges = BookSource.books().stream().map(book -> new MyEdge<>("0_" + book.getId(), book)).toList();
|
||||||
|
MyPageInfo pageInfo = new MyPageInfo(edges.get(0).cursor(), edges.get(edges.size() - 1).cursor, true, true);
|
||||||
|
MyConnection<Book> connection = new MyConnection<>(edges, pageInfo);
|
||||||
|
|
||||||
|
Mono<ExecutionGraphQlResponse> response = GraphQlSetup.schemaResource(BookSource.paginationSchema)
|
||||||
|
.dataFetcher("Query", "books", env -> connection)
|
||||||
|
.connectionSupport(new ListConnectionAdapter())
|
||||||
|
.toGraphQlService()
|
||||||
|
.execute(BookSource.booksConnectionQuery(null));
|
||||||
|
|
||||||
|
ResponseHelper.forResponse(response).assertData(
|
||||||
|
"{\"books\":{" +
|
||||||
|
"\"edges\":[" +
|
||||||
|
"{\"cursor\":\"0_1\",\"node\":{\"id\":\"1\",\"name\":\"Nineteen Eighty-Four\"}}," +
|
||||||
|
"{\"cursor\":\"0_2\",\"node\":{\"id\":\"2\",\"name\":\"The Great Gatsby\"}}," +
|
||||||
|
"{\"cursor\":\"0_3\",\"node\":{\"id\":\"3\",\"name\":\"Catch-22\"}}," +
|
||||||
|
"{\"cursor\":\"0_4\",\"node\":{\"id\":\"4\",\"name\":\"To The Lighthouse\"}}," +
|
||||||
|
"{\"cursor\":\"0_5\",\"node\":{\"id\":\"5\",\"name\":\"Animal Farm\"}}," +
|
||||||
|
"{\"cursor\":\"0_53\",\"node\":{\"id\":\"53\",\"name\":\"Breaking Bad\"}}," +
|
||||||
|
"{\"cursor\":\"0_42\",\"node\":{\"id\":\"42\",\"name\":\"Hitchhiker's Guide to the Galaxy\"}}" +
|
||||||
|
"]," +
|
||||||
|
"\"pageInfo\":{" +
|
||||||
|
"\"startCursor\":\"0_1\"," +
|
||||||
|
"\"endCursor\":\"0_42\"," +
|
||||||
|
"\"hasPreviousPage\":true," +
|
||||||
|
"\"hasNextPage\":true}" +
|
||||||
|
"}}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test // gh-707
|
@Test // gh-707
|
||||||
void nullValueTreatedAsEmptyConnection() {
|
void nullValueTreatedAsEmptyConnection() {
|
||||||
|
|
||||||
@@ -226,4 +260,14 @@ public class ConnectionFieldTypeVisitorTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private record MyConnection<T>(List<MyEdge<T>> edges, MyPageInfo pageInfo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MyEdge<T>(String cursor, T node) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private record MyPageInfo(String startCursor, String endCursor, boolean hasPreviousPage, boolean hasNextPage) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user