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.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import graphql.language.FieldDefinition; import graphql.language.FieldDefinition;
@@ -49,19 +48,15 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
private final static Log logger = LogFactory.getLog(AutoRegistrationRuntimeWiringConfigurer.class); 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 * Constructor with a Map of GraphQL type names as keys, and
* can be performed. * {@code DataFetcher} factories as values.
* @param dataFetcherFactories Map with GraphQL type names as keys, and
* functions to create a corresponding {@link DataFetcher} as values.
*/ */
AutoRegistrationRuntimeWiringConfigurer( AutoRegistrationRuntimeWiringConfigurer(Map<String, DataFetcherFactory> factories) {
Map<String, Function<Boolean, DataFetcher<?>>> dataFetcherFactories) { this.dataFetcherFactories = factories;
this.dataFetcherFactories = dataFetcherFactories;
} }
@@ -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 class AutoRegistrationWiringFactory implements WiringFactory {
private final RuntimeWiring.Builder builder; private final RuntimeWiring.Builder builder;
@@ -112,16 +125,21 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
@Nullable @Nullable
private String getOutputTypeName(FieldWiringEnvironment environment) { private String getOutputTypeName(FieldWiringEnvironment environment) {
GraphQLType outputType = (environment.getFieldType() instanceof GraphQLList ? GraphQLType outputType = removeNonNullWrapper(environment.getFieldType());
((GraphQLList) environment.getFieldType()).getWrappedType() :
environment.getFieldType());
if (outputType instanceof GraphQLNonNull) { if (outputType instanceof GraphQLList) {
outputType = ((GraphQLNonNull) outputType).getWrappedType(); outputType = removeNonNullWrapper(((GraphQLList) outputType).getWrappedType());
} }
return (outputType instanceof GraphQLNamedOutputType ? if (outputType instanceof GraphQLNamedOutputType namedType) {
((GraphQLNamedOutputType) outputType).getName() : null); return namedType.getName();
}
return null;
}
private GraphQLType removeNonNullWrapper(GraphQLType outputType) {
return (outputType instanceof GraphQLNonNull wrapper ? wrapper.getWrappedType() : outputType);
} }
private boolean hasDataFetcherFor(FieldDefinition fieldDefinition) { private boolean hasDataFetcherFor(FieldDefinition fieldDefinition) {
@@ -132,13 +150,11 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
return this.existingQueryDataFetcherPredicate.test(fieldDefinition.getName()); return this.existingQueryDataFetcherPredicate.test(fieldDefinition.getName());
} }
private void logTraceMessage( private void logTraceMessage(FieldWiringEnvironment environment, @Nullable String typeName, boolean match) {
FieldWiringEnvironment environment, @Nullable String outputTypeName, boolean match) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
String query = environment.getFieldDefinition().getName(); String query = environment.getFieldDefinition().getName();
logger.trace((match ? "Matched" : "Skipped") + logger.trace((match ? "Matched" : "Skipped") +
" output typeName " + (outputTypeName != null ? "'" + outputTypeName + "'" : "null") + " output typeName " + (typeName != null ? "'" + typeName + "'" : "null") +
" for query '" + query + "'"); " for query '" + query + "'");
} }
} }
@@ -149,11 +165,16 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer
String outputTypeName = getOutputTypeName(environment); String outputTypeName = getOutputTypeName(environment);
logTraceMessage(environment, outputTypeName, true); 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 + "'"); Assert.notNull(factory, "Expected DataFetcher factory for typeName '" + outputTypeName + "'");
boolean single = !(environment.getFieldType() instanceof GraphQLList); GraphQLType outputType = removeNonNullWrapper(environment.getFieldType());
return factory.apply(single); 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.data.util.TypeInformation;
import org.springframework.graphql.data.GraphQlArgumentBinder; import org.springframework.graphql.data.GraphQlArgumentBinder;
import org.springframework.graphql.data.GraphQlRepository; 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.RuntimeWiringConfigurer;
import org.springframework.graphql.execution.SelfDescribingDataFetcher; import org.springframework.graphql.execution.SelfDescribingDataFetcher;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@@ -195,13 +196,23 @@ public abstract class QueryByExampleDataFetcher<T> {
List<QueryByExampleExecutor<?>> executors, List<QueryByExampleExecutor<?>> executors,
List<ReactiveQueryByExampleExecutor<?>> reactiveExecutors) { List<ReactiveQueryByExampleExecutor<?>> reactiveExecutors) {
Map<String, Function<Boolean, DataFetcher<?>>> factories = new HashMap<>(); Map<String, DataFetcherFactory> factories = new HashMap<>();
for (QueryByExampleExecutor<?> executor : executors) { for (QueryByExampleExecutor<?> executor : executors) {
String typeName = RepositoryUtils.getGraphQlTypeName(executor); String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) { if (typeName != null) {
Builder<?, ?> builder = customize(executor, builder(executor)); 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); String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) { if (typeName != null) {
ReactiveBuilder<?, ?> builder = customize(executor, builder(executor)); 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.repository.query.FluentQuery.FetchableFluentQuery;
import org.springframework.data.util.TypeInformation; import org.springframework.data.util.TypeInformation;
import org.springframework.graphql.data.GraphQlRepository; 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.RuntimeWiringConfigurer;
import org.springframework.graphql.execution.SelfDescribingDataFetcher; import org.springframework.graphql.execution.SelfDescribingDataFetcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@@ -219,13 +220,23 @@ public abstract class QuerydslDataFetcher<T> {
List<QuerydslPredicateExecutor<?>> executors, List<QuerydslPredicateExecutor<?>> executors,
List<ReactiveQuerydslPredicateExecutor<?>> reactiveExecutors) { List<ReactiveQuerydslPredicateExecutor<?>> reactiveExecutors) {
Map<String, Function<Boolean, DataFetcher<?>>> factories = new HashMap<>(); Map<String, DataFetcherFactory> factories = new HashMap<>();
for (QuerydslPredicateExecutor<?> executor : executors) { for (QuerydslPredicateExecutor<?> executor : executors) {
String typeName = RepositoryUtils.getGraphQlTypeName(executor); String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) { if (typeName != null) {
Builder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor))); 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); String typeName = RepositoryUtils.getGraphQlTypeName(executor);
if (typeName != null) { if (typeName != null) {
ReactiveBuilder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor))); 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();
}
});
} }
} }