AutoRegistrationRuntimeWiringConfigurer refactoring

This commit is contained in:
rstoyanchev
2023-03-31 12:09:37 +01:00
parent 3ebdce0f7a
commit 2d071a42ee
3 changed files with 93 additions and 30 deletions

View File

@@ -17,7 +17,6 @@ package org.springframework.graphql.data.query;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import graphql.language.FieldDefinition;
@@ -49,19 +48,15 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
private final static Log logger = LogFactory.getLog(AutoRegistrationRuntimeWiringConfigurer.class);
private final Map<String, Function<Boolean, DataFetcher<?>>> dataFetcherFactories;
private final Map<String, DataFetcherFactory> dataFetcherFactories;
/**
* Constructor with a Map of GraphQL type names for which auto-registration
* can be performed.
* @param dataFetcherFactories Map with GraphQL type names as keys, and
* functions to create a corresponding {@link DataFetcher} as values.
* Constructor with a Map of GraphQL type names as keys, and
* {@code DataFetcher} factories as values.
*/
AutoRegistrationRuntimeWiringConfigurer(
Map<String, Function<Boolean, DataFetcher<?>>> dataFetcherFactories) {
this.dataFetcherFactories = dataFetcherFactories;
AutoRegistrationRuntimeWiringConfigurer(Map<String, DataFetcherFactory> factories) {
this.dataFetcherFactories = factories;
}
@@ -75,6 +70,24 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
}
/**
* Callback interface to create the desired type of {@code DataFetcher}.
*/
interface DataFetcherFactory {
/**
* Create a singe item {@code DataFetcher}.
*/
DataFetcher<?> single();
/**
* Create {@code DataFetcher} for multiple items.
*/
DataFetcher<?> many();
}
private class AutoRegistrationWiringFactory implements WiringFactory {
private final RuntimeWiring.Builder builder;
@@ -112,16 +125,21 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
@Nullable
private String getOutputTypeName(FieldWiringEnvironment environment) {
GraphQLType outputType = (environment.getFieldType() instanceof GraphQLList ?
((GraphQLList) environment.getFieldType()).getWrappedType() :
environment.getFieldType());
GraphQLType outputType = removeNonNullWrapper(environment.getFieldType());
if (outputType instanceof GraphQLNonNull) {
outputType = ((GraphQLNonNull) outputType).getWrappedType();
if (outputType instanceof GraphQLList) {
outputType = removeNonNullWrapper(((GraphQLList) outputType).getWrappedType());
}
return (outputType instanceof GraphQLNamedOutputType ?
((GraphQLNamedOutputType) outputType).getName() : null);
if (outputType instanceof GraphQLNamedOutputType namedType) {
return namedType.getName();
}
return null;
}
private GraphQLType removeNonNullWrapper(GraphQLType outputType) {
return (outputType instanceof GraphQLNonNull wrapper ? wrapper.getWrappedType() : outputType);
}
private boolean hasDataFetcherFor(FieldDefinition fieldDefinition) {
@@ -132,13 +150,11 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
return this.existingQueryDataFetcherPredicate.test(fieldDefinition.getName());
}
private void logTraceMessage(
FieldWiringEnvironment environment, @Nullable String outputTypeName, boolean match) {
private void logTraceMessage(FieldWiringEnvironment environment, @Nullable String typeName, boolean match) {
if (logger.isTraceEnabled()) {
String query = environment.getFieldDefinition().getName();
logger.trace((match ? "Matched" : "Skipped") +
" output typeName " + (outputTypeName != null ? "'" + outputTypeName + "'" : "null") +
" output typeName " + (typeName != null ? "'" + typeName + "'" : "null") +
" for query '" + query + "'");
}
}
@@ -149,11 +165,16 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
String outputTypeName = getOutputTypeName(environment);
logTraceMessage(environment, outputTypeName, true);
Function<Boolean, DataFetcher<?>> factory = dataFetcherFactories.get(outputTypeName);
DataFetcherFactory factory = dataFetcherFactories.get(outputTypeName);
Assert.notNull(factory, "Expected DataFetcher factory for typeName '" + outputTypeName + "'");
boolean single = !(environment.getFieldType() instanceof GraphQLList);
return factory.apply(single);
GraphQLType outputType = removeNonNullWrapper(environment.getFieldType());
if (outputType instanceof GraphQLList) {
return factory.many();
}
else {
return factory.single();
}
}
}

View File

@@ -42,6 +42,7 @@ import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.data.util.TypeInformation;
import org.springframework.graphql.data.GraphQlArgumentBinder;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
import org.springframework.lang.Nullable;
@@ -195,13 +196,23 @@ public abstract class QueryByExampleDataFetcher<T> {
List<QueryByExampleExecutor<?>> executors,
List<ReactiveQueryByExampleExecutor<?>> reactiveExecutors) {
Map<String, Function<Boolean, DataFetcher<?>>> factories = new HashMap<>();
Map<String, DataFetcherFactory> factories = new HashMap<>();
for (QueryByExampleExecutor<?> executor : executors) {
String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) {
Builder<?, ?> builder = customize(executor, builder(executor));
factories.put(typeName, single -> single ? builder.single() : builder.many());
factories.put(typeName, new DataFetcherFactory() {
@Override
public DataFetcher<?> single() {
return builder.single();
}
@Override
public DataFetcher<?> many() {
return builder.many();
}
});
}
}
@@ -209,7 +220,17 @@ public abstract class QueryByExampleDataFetcher<T> {
String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) {
ReactiveBuilder<?, ?> builder = customize(executor, builder(executor));
factories.put(typeName, single -> single ? builder.single() : builder.many());
factories.put(typeName, new DataFetcherFactory() {
@Override
public DataFetcher<?> single() {
return builder.single();
}
@Override
public DataFetcher<?> many() {
return builder.many();
}
});
}
}

View File

@@ -47,6 +47,7 @@ import org.springframework.data.repository.query.FluentQuery;
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
import org.springframework.data.util.TypeInformation;
import org.springframework.graphql.data.GraphQlRepository;
import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.graphql.execution.SelfDescribingDataFetcher;
import org.springframework.util.Assert;
@@ -219,13 +220,23 @@ public abstract class QuerydslDataFetcher<T> {
List<QuerydslPredicateExecutor<?>> executors,
List<ReactiveQuerydslPredicateExecutor<?>> reactiveExecutors) {
Map<String, Function<Boolean, DataFetcher<?>>> factories = new HashMap<>();
Map<String, DataFetcherFactory> factories = new HashMap<>();
for (QuerydslPredicateExecutor<?> executor : executors) {
String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) {
Builder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor)));
factories.put(typeName, single -> single ? builder.single() : builder.many());
factories.put(typeName, new DataFetcherFactory() {
@Override
public DataFetcher<?> single() {
return builder.single();
}
@Override
public DataFetcher<?> many() {
return builder.many();
}
});
}
}
@@ -233,7 +244,17 @@ public abstract class QuerydslDataFetcher<T> {
String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) {
ReactiveBuilder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor)));
factories.put(typeName, single -> single ? builder.single() : builder.many());
factories.put(typeName, new DataFetcherFactory() {
@Override
public DataFetcher<?> single() {
return builder.single();
}
@Override
public DataFetcher<?> many() {
return builder.many();
}
});
}
}