This is an automated email from the ASF dual-hosted git repository. danhaywood pushed a commit to branch CAUSEWAY-3676 in repository https://gitbox.apache.org/repos/asf/causeway.git
commit d5ea89dada2fb574b78a5e27413aaea90ceb05f1 Author: danhaywood <[email protected]> AuthorDate: Fri Jan 19 11:25:23 2024 +0000 CAUSEWAY-3676: introduces GraphQLTypeRegistry --- .../integration/GraphQlSourceForCauseway.java | 13 +- .../graphql/viewer/source/GraphQLTypeRegistry.java | 135 +++++++++++++++++++++ .../graphql/viewer/source/ObjectTypeFactory.java | 82 ++----------- 3 files changed, 149 insertions(+), 81 deletions(-) diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java index 2e697b6a5b..536b72c2e2 100644 --- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java +++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java @@ -33,8 +33,7 @@ import org.apache.causeway.applib.id.HasLogicalType; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; -import org.apache.causeway.viewer.graphql.viewer.integration.AsyncExecutionStrategyResolvingWithinInteraction; - +import org.apache.causeway.viewer.graphql.viewer.source.GraphQLTypeRegistry; import org.apache.causeway.viewer.graphql.viewer.source.ObjectTypeFactory; import org.apache.causeway.viewer.graphql.viewer.source.QueryFieldFactory; @@ -68,6 +67,7 @@ public class GraphQlSourceForCauseway implements GraphQlSource { private final AsyncExecutionStrategyResolvingWithinInteraction executionStrategy; private final ObjectTypeFactory objectTypeFactory; private final QueryFieldFactory queryFieldFactory; + private final GraphQLTypeRegistry graphQLTypeRegistry; @PostConstruct public void init() { @@ -96,12 +96,10 @@ public class GraphQlSourceForCauseway implements GraphQlSource { final GraphQLObjectType.Builder queryBuilder = newObject().name("Query"); final GraphQLCodeRegistry.Builder codeRegistryBuilder = GraphQLCodeRegistry.newCodeRegistry(); - Set<GraphQLType> graphQLObjectTypes = new HashSet<>(); - specificationLoader.snapshotSpecifications() .distinct((a, b) -> a.getLogicalTypeName().equals(b.getLogicalTypeName())) .sorted(Comparator.comparing(HasLogicalType::getLogicalTypeName)) - .forEach(objectSpec -> handleObjectSpec(objectSpec, graphQLObjectTypes, queryBuilder, codeRegistryBuilder)); + .forEach(objectSpec -> handleObjectSpec(objectSpec, queryBuilder, codeRegistryBuilder)); val query_numServices = newFieldDefinition() .name("numServices") @@ -120,14 +118,13 @@ public class GraphQlSourceForCauseway implements GraphQlSource { return GraphQLSchema.newSchema() .query(query) - .additionalTypes(graphQLObjectTypes) + .additionalTypes(graphQLTypeRegistry.getGraphQLObjectTypes()) .codeRegistry(codeRegistry) .build(); } private void handleObjectSpec( final ObjectSpecification objectSpec, - final Set<GraphQLType> graphQLObjectTypes, final GraphQLObjectType.Builder queryBuilder, final GraphQLCodeRegistry.Builder codeRegistryBuilder ) { @@ -139,7 +136,7 @@ public class GraphQlSourceForCauseway implements GraphQlSource { case ENTITY: // @DomainObject(nature=ENTITY) // TODO: App interface should map to gql interfaces? - objectTypeFactory.objectTypeFromObjectSpecification(objectSpec, graphQLObjectTypes, codeRegistryBuilder); + objectTypeFactory.objectTypeFromObjectSpecification(objectSpec, codeRegistryBuilder); break; diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GraphQLTypeRegistry.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GraphQLTypeRegistry.java new file mode 100644 index 0000000000..a5fb72e23d --- /dev/null +++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GraphQLTypeRegistry.java @@ -0,0 +1,135 @@ +package org.apache.causeway.viewer.graphql.viewer.source; + +import graphql.schema.GraphQLInputObjectType; +import graphql.schema.GraphQLNamedType; +import graphql.schema.GraphQLObjectType; +import graphql.schema.GraphQLType; + +import lombok.extern.log4j.Log4j2; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.stereotype.Component; + +@Component +@Log4j2 +public class GraphQLTypeRegistry { + + + Set<GraphQLType> graphQLObjectTypes = new HashSet<>(); + + public Set<GraphQLType> getGraphQLObjectTypes() { + return Collections.unmodifiableSet(graphQLObjectTypes); + } + + + void addTypeIfNotAlreadyPresent( + final GraphQLType typeToAdd, + final String logicalTypeName) { + + if (typeToAdd instanceof GraphQLObjectType) { + addTypeIfNotAlreadyPresent((GraphQLObjectType) typeToAdd, logicalTypeName); + return; + } + + if (typeToAdd instanceof GraphQLInputObjectType) { + addTypeIfNotAlreadyPresent((GraphQLInputObjectType) typeToAdd, logicalTypeName); + return; + } + + // TODO: none of these types yet handled + // GraphQLTypeReference + // GraphQLScalarType + // GraphQLCompositeType + // GraphQLUnionType + // GraphQLEnumType + // GraphQLInterfaceType + // GraphQLList + // GraphQLNonNull + log.warn("GraphQLType {} not yet implemented", typeToAdd.getClass().getName()); + } + + void addTypeIfNotAlreadyPresent( + final GraphQLInputObjectType typeToAdd, + final String logicalTypeName) { + if (isPresent(typeToAdd, GraphQLInputObjectType.class)){ + // For now we just log and skip + log.info("GraphQLInputObjectType for {} already present", logicalTypeName); + return; + } + graphQLObjectTypes.add(typeToAdd); + } + + void addTypeIfNotAlreadyPresent( + final GraphQLObjectType typeToAdd, + final String logicalTypeName){ + + if (isPresent(typeToAdd, GraphQLObjectType.class)){ + // For now we just log and skip + log.info("GraphQLObjectType for {} already present", logicalTypeName); + return; + } + graphQLObjectTypes.add(typeToAdd); + } + + + public void addTypeIfNotAlreadyPresent(final GraphQLType typeToAdd) { + + if (typeToAdd instanceof GraphQLObjectType) { + addTypeIfNotAlreadyPresent((GraphQLObjectType) typeToAdd); + return; + } + + if (typeToAdd instanceof GraphQLInputObjectType) { + addTypeIfNotAlreadyPresent((GraphQLInputObjectType) typeToAdd); + return; + } + + // TODO: none of these types yet handled + // GraphQLTypeReference + // GraphQLScalarType + // GraphQLCompositeType + // GraphQLUnionType + // GraphQLEnumType + // GraphQLInterfaceType + // GraphQLList + // GraphQLNonNull + log.warn("GraphQLType {} not yet implemented", typeToAdd.getClass().getName()); + } + + void addTypeIfNotAlreadyPresent(final GraphQLObjectType typeToAdd){ + if (isPresent(typeToAdd, GraphQLObjectType.class)){ + // For now we just log and skip + log.info("GraphQLObjectType for {} already present", typeToAdd.getName()); + return; + } + add(typeToAdd); + } + + + void addTypeIfNotAlreadyPresent(final GraphQLInputObjectType typeToAdd) { + if (isPresent(typeToAdd, GraphQLInputObjectType.class)){ + // For now we just log and skip + log.info("GraphQLInputObjectType for {} already present", typeToAdd.getName()); + return; + } + add(typeToAdd); + } + + private boolean isPresent( + final GraphQLNamedType typeToAdd, + final Class<? extends GraphQLNamedType> cls) { + return graphQLObjectTypes.stream() + .filter(o -> o.getClass().isAssignableFrom(cls)) + .map(cls::cast) + .anyMatch(ot -> ot.getName().equals(typeToAdd.getName())); + } + + + private void add(GraphQLType typeToAdd) { + graphQLObjectTypes.add(typeToAdd); + } + +} diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/ObjectTypeFactory.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/ObjectTypeFactory.java index 4490daf6c9..0810a15e90 100644 --- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/ObjectTypeFactory.java +++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/ObjectTypeFactory.java @@ -54,7 +54,6 @@ import graphql.schema.GraphQLFieldDefinition; import graphql.schema.GraphQLInputObjectField; import graphql.schema.GraphQLInputObjectType; import graphql.schema.GraphQLInputType; -import graphql.schema.GraphQLNamedType; import graphql.schema.GraphQLObjectType; import graphql.schema.GraphQLOutputType; import graphql.schema.GraphQLType; @@ -63,7 +62,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.experimental.UtilityClass; -import lombok.extern.java.Log; import lombok.extern.log4j.Log4j2; import lombok.val; @@ -73,10 +71,11 @@ import lombok.val; public class ObjectTypeFactory { final static String GQL_INPUTTYPE_PREFIX = "_gql_input__"; - final static String GQL_MUTATTIONS_FIELDNAME = "_gql_mutations"; + final static String GQL_MUTATIONS_FIELDNAME = "_gql_mutations"; private final BookmarkService bookmarkService; private final SpecificationLoader specificationLoader; private final ObjectManager objectManager; + private final GraphQLTypeRegistry graphQLTypeRegistry; static String mutatorsTypeName(final String logicalTypeNameSanitized){ return logicalTypeNameSanitized + "__DomainObject_mutators"; @@ -106,7 +105,6 @@ public class ObjectTypeFactory { public void objectTypeFromObjectSpecification( final ObjectSpecification objectSpec, - final Set<GraphQLType> graphQLObjectTypes, final GraphQLCodeRegistry.Builder codeRegistryBuilder) { val gqlvObjectSpec = new GqlvObjectSpec(objectSpec); @@ -117,7 +115,7 @@ public class ObjectTypeFactory { GraphQLObjectType metaType = gqlvObjectSpec.getMetaType(); - addTypeIfNotAlreadyPresent(graphQLObjectTypes, metaType, logicalTypeNameSanitized); + graphQLTypeRegistry.addTypeIfNotAlreadyPresent(metaType, logicalTypeNameSanitized); // add meta field val _gql_meta_Field = newFieldDefinition().name("_gql_meta").type(metaType).build(); @@ -133,7 +131,7 @@ public class ObjectTypeFactory { .build()); GraphQLInputType inputType = inputTypeBuilder.build(); - addTypeIfNotAlreadyPresent(graphQLObjectTypes, inputType, inputTypeName); + graphQLTypeRegistry.addTypeIfNotAlreadyPresent(inputType, inputTypeName); // add fields gqlvObjectSpec.addFields(); @@ -143,11 +141,11 @@ public class ObjectTypeFactory { // add actions MutatorsDataForEntity mutatorsDataForEntity = - addActions(gqlvObjectSpec.getLogicalTypeNameSanitized(), objectSpec, gqlvObjectSpec.getObjectTypeBuilder(), graphQLObjectTypes); + addActions(gqlvObjectSpec.getLogicalTypeNameSanitized(), objectSpec, gqlvObjectSpec.getObjectTypeBuilder()); // build and register object type GraphQLObjectType graphQLObjectType = gqlvObjectSpec.getObjectTypeBuilder().build(); - addTypeIfNotAlreadyPresent(graphQLObjectTypes, graphQLObjectType, gqlvObjectSpec.getLogicalTypeNameSanitized()); + graphQLTypeRegistry.addTypeIfNotAlreadyPresent(graphQLObjectType, gqlvObjectSpec.getLogicalTypeNameSanitized()); // create and register data fetchers createAndRegisterDataFetchersForMetaData( @@ -168,67 +166,6 @@ public class ObjectTypeFactory { } - void addTypeIfNotAlreadyPresent( - final Set<GraphQLType> graphQLObjectTypes, - final GraphQLType typeToAdd, - final String logicalTypeName) { - - if (typeToAdd instanceof GraphQLObjectType) { - addTypeIfNotAlreadyPresent(graphQLObjectTypes, (GraphQLObjectType) typeToAdd, logicalTypeName); - return; - } - - if (typeToAdd instanceof GraphQLInputObjectType) { - addTypeIfNotAlreadyPresent(graphQLObjectTypes, (GraphQLInputObjectType) typeToAdd, logicalTypeName); - return; - } - - // TODO: none of these types yet handled - // GraphQLTypeReference - // GraphQLScalarType - // GraphQLCompositeType - // GraphQLUnionType - // GraphQLEnumType - // GraphQLInterfaceType - // GraphQLList - // GraphQLNonNull - log.warn("GraphQLType {} not yet implemented", typeToAdd.getClass().getName()); - } - - private static void addTypeIfNotAlreadyPresent( - final Set<GraphQLType> graphQLObjectTypes, - final GraphQLInputObjectType typeToAdd, - final String logicalTypeName) { - if (isPresent(graphQLObjectTypes, typeToAdd, GraphQLInputObjectType.class)){ - // For now we just log and skip - log.info("GraphQLInputObjectType for {} already present", logicalTypeName); - return; - } - graphQLObjectTypes.add(typeToAdd); - } - - void addTypeIfNotAlreadyPresent( - final Set<GraphQLType> graphQLObjectTypes, - final GraphQLObjectType typeToAdd, - final String logicalTypeName){ - - if (isPresent(graphQLObjectTypes, typeToAdd, GraphQLObjectType.class)){ - // For now we just log and skip - log.info("GraphQLObjectType for {} already present", logicalTypeName); - return; - } - graphQLObjectTypes.add(typeToAdd); - } - - private static boolean isPresent( - final Set<GraphQLType> graphQLObjectTypes, - final GraphQLNamedType typeToAdd, - final Class<? extends GraphQLNamedType> cls) { - return graphQLObjectTypes.stream() - .filter(o -> o.getClass().isAssignableFrom(cls)) - .map(cls::cast) - .anyMatch(ot -> ot.getName().equals(typeToAdd.getName())); - } void createAndRegisterDataFetchersForField( final ObjectSpecification objectSpecification, @@ -256,8 +193,7 @@ public class ObjectTypeFactory { MutatorsDataForEntity addActions( final String logicalTypeNameSanitized, final ObjectSpecification objectSpecification, - final GraphQLObjectType.Builder objectTypeBuilder, - final Set<GraphQLType> graphQLObjectTypes) { + final GraphQLObjectType.Builder objectTypeBuilder) { MutatorManager result = mutatorManager(logicalTypeNameSanitized); @@ -268,9 +204,9 @@ public class ObjectTypeFactory { if (!result.mutatorsTypeFields.isEmpty()){ GraphQLObjectType mutatorsType = result.mutatorsTypeBuilder.build(); - addTypeIfNotAlreadyPresent(graphQLObjectTypes, mutatorsType, result.mutatorsTypeName); + graphQLTypeRegistry.addTypeIfNotAlreadyPresent(mutatorsType, result.mutatorsTypeName); GraphQLFieldDefinition gql_mutations = newFieldDefinition() - .name(GQL_MUTATTIONS_FIELDNAME) + .name(GQL_MUTATIONS_FIELDNAME) .type(mutatorsType) .build(); objectTypeBuilder.field(gql_mutations);
