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


The following commit(s) were added to refs/heads/CAUSEWAY-3676 by this push:
     new ec9cd01626 CAUSEWAY-3676: wip on QueryFieldFactory
ec9cd01626 is described below

commit ec9cd016261c14c3cddb6c7f2d01b160c2bc6204
Author: danhaywood <[email protected]>
AuthorDate: Fri Jan 19 15:55:14 2024 +0000

    CAUSEWAY-3676: wip on QueryFieldFactory
---
 .../integration/GraphQlSourceForCauseway.java      |  16 ++-
 .../graphql/viewer/source/GqlvObjectBehaviour.java |  22 ++-
 .../viewer/source/GqlvServiceBehaviour.java        |  10 ++
 .../GqlvTopLevelQueryBehaviour.java                |  18 +--
 .../graphql/viewer/source/QueryFieldFactory.java   | 151 +++++++++++----------
 5 files changed, 123 insertions(+), 94 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 4482c39756..baf0d56f75 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
@@ -31,6 +31,7 @@ import org.apache.causeway.applib.id.HasLogicalType;
 
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 
+import 
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryBehaviour;
 import 
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryStructure;
 import org.apache.causeway.viewer.graphql.viewer.source.GraphQLTypeRegistry;
 import org.apache.causeway.viewer.graphql.viewer.source.ObjectTypeFactory;
@@ -93,6 +94,9 @@ public class GraphQlSourceForCauseway implements 
GraphQlSource {
 
         final GraphQLCodeRegistry.Builder codeRegistryBuilder = 
GraphQLCodeRegistry.newCodeRegistry();
 
+
+        // add to the top-level query
+        // (and also add behaviour to the child types)
         val topLevelQueryStructure = new GqlvTopLevelQueryStructure();
 
         specificationLoader.snapshotSpecifications()
@@ -102,11 +106,16 @@ public class GraphQlSourceForCauseway implements 
GraphQlSource {
 
         topLevelQueryStructure.buildQueryType();
 
-        val topLevelQueryBehaviour = new 
GqlvTopLevelQueryBehaviour(topLevelQueryStructure, serviceRegistry);
-        topLevelQueryBehaviour.addFetchersTo(codeRegistryBuilder);
 
+        // add behaviour to the top-level query's own fields
+        val topLevelQueryBehaviour = new 
GqlvTopLevelQueryBehaviour(topLevelQueryStructure, codeRegistryBuilder, 
serviceRegistry);
+        topLevelQueryBehaviour.addFetchers();
+
+        // finalize the fetcher/mutator code that's been registered
         val codeRegistry = codeRegistryBuilder.build();
 
+
+        // build the schema
         return GraphQLSchema.newSchema()
                 .query(topLevelQueryStructure.getQueryType())
                 .additionalTypes(graphQLTypeRegistry.getGraphQLObjectTypes())
@@ -116,7 +125,8 @@ public class GraphQlSourceForCauseway implements 
GraphQlSource {
 
     private void addToSchema(
             final ObjectSpecification objectSpec,
-            final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure, final 
GraphQLCodeRegistry.Builder codeRegistryBuilder) {
+            final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure,
+            final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
 
         switch (objectSpec.getBeanSort()) {
 
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
index b257628460..fca594cad5 100644
--- 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
@@ -25,7 +25,7 @@ import static graphql.schema.GraphQLObjectType.newObject;
 @RequiredArgsConstructor
 public class GqlvObjectBehaviour {
 
-    private final GqlvObjectStructure gqlvObjectStructure;
+    private final GqlvObjectStructure structure;
     private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
     private final BookmarkService bookmarkService;
     private final ObjectManager objectManager;
@@ -36,32 +36,30 @@ public class GqlvObjectBehaviour {
     public void createAndRegisterDataFetchersForMetaData() {
 
         codeRegistryBuilder.dataFetcher(
-                
FieldCoordinates.coordinates(gqlvObjectStructure.getGqlObjectType(), 
gqlvObjectStructure.getMetaField()),
+                FieldCoordinates.coordinates(structure.getGqlObjectType(), 
structure.getMetaField()),
                 (DataFetcher<Object>) environment -> {
                     return bookmarkService.bookmarkFor(environment.getSource())
                             .map(bookmark -> new GqlvMeta(bookmark, 
bookmarkService, objectManager))
                             .orElse(null); //TODO: is this correct ?
                 });
 
-        GraphQLObjectType metaType = gqlvObjectStructure.getMetaType();
-        gqlvObjectStructure.getMetaField().getType();
         codeRegistryBuilder.dataFetcher(
-                FieldCoordinates.coordinates(metaType, 
GqlvObjectStructure.Fields.id),
+                FieldCoordinates.coordinates(structure.getMetaType(), 
GqlvObjectStructure.Fields.id),
                 (DataFetcher<Object>) environment -> {
                     GqlvMeta gqlvMeta = environment.getSource();
                     return gqlvMeta.id();
                 });
 
         codeRegistryBuilder.dataFetcher(
-                
FieldCoordinates.coordinates(gqlvObjectStructure.getMetaType(), 
GqlvObjectStructure.Fields.logicalTypeName),
+                FieldCoordinates.coordinates(structure.getMetaType(), 
GqlvObjectStructure.Fields.logicalTypeName),
                 (DataFetcher<Object>) environment -> {
                     GqlvMeta gqlvMeta = environment.getSource();
                     return gqlvMeta.logicalTypeName();
                 });
 
-        if (gqlvObjectStructure.getBeanSort() == BeanSort.ENTITY) {
+        if (structure.getBeanSort() == BeanSort.ENTITY) {
             codeRegistryBuilder.dataFetcher(
-                    
FieldCoordinates.coordinates(gqlvObjectStructure.getMetaType(), 
GqlvObjectStructure.Fields.version),
+                    FieldCoordinates.coordinates(structure.getMetaType(), 
GqlvObjectStructure.Fields.version),
                     (DataFetcher<Object>) environment -> {
                         GqlvMeta gqlvMeta = environment.getSource();
                         return gqlvMeta.version();
@@ -71,19 +69,19 @@ public class GqlvObjectBehaviour {
 
 
     public void createAndRegisterDataFetchersForField() {
-        gqlvObjectStructure.getObjectSpec().streamProperties(MixedIn.INCLUDED)
+        structure.getObjectSpec().streamProperties(MixedIn.INCLUDED)
                 
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
     }
 
     void createAndRegisterDataFetchersForCollection() {
-        gqlvObjectStructure.getObjectSpec().streamCollections(MixedIn.INCLUDED)
+        structure.getObjectSpec().streamCollections(MixedIn.INCLUDED)
                 
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
     }
 
 
     private void createAndRegisterDataFetcherForObjectAssociation(final 
ObjectAssociation otom) {
 
-        final GraphQLObjectType graphQLObjectType = 
gqlvObjectStructure.getGqlObjectType();
+        final GraphQLObjectType graphQLObjectType = 
structure.getGqlObjectType();
 
         ObjectSpecification fieldObjectSpecification = otom.getElementType();
         BeanSort beanSort = fieldObjectSpecification.getBeanSort();
@@ -152,7 +150,7 @@ public class GqlvObjectBehaviour {
             final Set<GraphQLType> graphQLObjectTypes) {
 
         //TODO: this is not going to work, because we need to dynamically add 
fields
-        String mutatorsTypeName = 
gqlvObjectStructure.getLogicalTypeNameSanitized() + "__DomainObject_mutators";
+        String mutatorsTypeName = structure.getLogicalTypeNameSanitized() + 
"__DomainObject_mutators";
         GraphQLObjectType.Builder mutatorsTypeBuilder = 
newObject().name(mutatorsTypeName);
         GraphQLObjectType mutatorsType = mutatorsTypeBuilder.build();
         graphQLObjectTypes.add(mutatorsType);
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
new file mode 100644
index 0000000000..2cf79f14a7
--- /dev/null
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
@@ -0,0 +1,10 @@
+package org.apache.causeway.viewer.graphql.viewer.source;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class GqlvServiceBehaviour {
+
+    private final GqlvServiceStructure structure;
+
+}
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
similarity index 53%
rename from 
incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
rename to 
incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
index 7ac8b4b26e..d09c3a4398 100644
--- 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
@@ -1,30 +1,32 @@
-package org.apache.causeway.viewer.graphql.viewer.integration;
+package org.apache.causeway.viewer.graphql.viewer.source;
 
 import graphql.schema.DataFetcher;
 import graphql.schema.GraphQLCodeRegistry;
 
 import org.apache.causeway.applib.services.registry.ServiceRegistry;
-import 
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryStructure;
 
 import static graphql.schema.FieldCoordinates.coordinates;
 
 public class GqlvTopLevelQueryBehaviour {
 
-    private final GqlvTopLevelQueryStructure topLevelQueryStructure;
+    private final GqlvTopLevelQueryStructure structure;
+    private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
     private final ServiceRegistry serviceRegistry;
 
     public GqlvTopLevelQueryBehaviour(
-            final GqlvTopLevelQueryStructure topLevelQueryStructure,
+            final GqlvTopLevelQueryStructure structure,
+            final GraphQLCodeRegistry.Builder codeRegistryBuilder,
             final ServiceRegistry serviceRegistry) {
-        this.topLevelQueryStructure = topLevelQueryStructure;
+        this.structure = structure;
+        this.codeRegistryBuilder = codeRegistryBuilder;
         this.serviceRegistry = serviceRegistry;
     }
 
-    public void addFetchersTo(GraphQLCodeRegistry.Builder codeRegistryBuilder) 
{
+    public void addFetchers() {
         codeRegistryBuilder
                 .dataFetcher(
-                        coordinates(topLevelQueryStructure.getQueryType(), 
topLevelQueryStructure.getNumServicesField()),
+                        coordinates(structure.getQueryType(), 
structure.getNumServicesField()),
                         (DataFetcher<Object>) environment -> 
this.serviceRegistry.streamRegisteredBeans().count());
-
     }
+
 }
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
index 45b1237325..f6eba0b533 100644
--- 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
@@ -61,102 +61,111 @@ public class QueryFieldFactory {
 
     public void queryFieldFromObjectSpecification(
             final ObjectSpecification objectSpec,
-            final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure,
+            final GqlvTopLevelQueryStructure topLevelQueryStructure,
             final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
 
-        final GraphQLObjectType.Builder queryBuilder = 
gqlvTopLevelQueryStructure.getQueryBuilder();
-
-        String logicalTypeNameSanitized = _LTN.sanitized(objectSpec);
-
         serviceRegistry.lookupBeanById(objectSpec.getLogicalTypeName())
         .ifPresent(service -> {
+            addService(objectSpec, service, topLevelQueryStructure, 
codeRegistryBuilder);
+        });
+    }
 
-            List<ObjectAction> objectActionList = 
objectSpec.streamRuntimeActions(MixedIn.INCLUDED)
-                    .map(ObjectAction.class::cast)
-                    .filter((final ObjectAction x) -> 
x.containsFacet(ActionSemanticsFacet.class))
-//                            .filter(x -> 
x.getFacet(ActionSemanticsFacet.class).value() == SemanticsOf.SAFE)
-                    .collect(Collectors.toList());
+    private void addService(
+            final ObjectSpecification objectSpec,
+            final Object service,
+            final GqlvTopLevelQueryStructure topLevelQueryStructure,
+            final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
 
-            // for now filters when no safe actions
-            if (!objectActionList.isEmpty()) {
+        final GraphQLObjectType.Builder queryBuilder = 
topLevelQueryStructure.getQueryBuilder();
 
-                val serviceAsGraphQlType = 
newObject().name(logicalTypeNameSanitized);
+        List<ObjectAction> objectActionList = 
objectSpec.streamRuntimeActions(MixedIn.INCLUDED)
+                .map(ObjectAction.class::cast)
+                .filter((final ObjectAction x) -> 
x.containsFacet(ActionSemanticsFacet.class))
+//                            .filter(x -> 
x.getFacet(ActionSemanticsFacet.class).value() == SemanticsOf.SAFE)
+                .collect(Collectors.toList());
 
-                objectActionList
-                .forEach(objectAction -> {
-                    String fieldName = objectAction.getId();
+        // for now filters when no safe actions
+        if (!objectActionList.isEmpty()) {
 
-                    GraphQLFieldDefinition.Builder builder = 
newFieldDefinition()
-                            .name(fieldName)
-                            .type((GraphQLOutputType) 
TypeMapper.typeForObjectAction(objectAction));
-                    if (objectAction.getParameters().isNotEmpty()) {
-                        builder.arguments(objectAction.getParameters().stream()
-                                .map(objectActionParameter -> 
GraphQLArgument.newArgument()
-                                        .name(objectActionParameter.getId())
-                                        
.type(TypeMapper.inputTypeFor(objectActionParameter))
-                                        .build())
-                                .collect(Collectors.toList()));
-                    }
-                    serviceAsGraphQlType
-                            .field(builder
-                                    .build());
+            val serviceAsGraphQlType = 
newObject().name(_LTN.sanitized(objectSpec));
 
-                });
+            objectActionList
+            .forEach(objectAction -> {
+                addAction(objectAction, serviceAsGraphQlType);
+            });
 
-                GraphQLObjectType graphQLObjectType = 
serviceAsGraphQlType.build();
+            GraphQLObjectType graphQLObjectType = serviceAsGraphQlType.build();
 
-                objectActionList
-                .forEach(objectAction -> {
+            objectActionList
+            .forEach(objectAction -> {
 
-                    String fieldName = objectAction.getId();
-                    codeRegistryBuilder
-                    .dataFetcher(
-                        FieldCoordinates.coordinates(graphQLObjectType, 
fieldName),
-                        new DataFetcher<Object>() {
+                String fieldName = objectAction.getId();
+                codeRegistryBuilder
+                .dataFetcher(
+                    FieldCoordinates.coordinates(graphQLObjectType, fieldName),
+                    new DataFetcher<Object>() {
 
-                            @Override
-                            public Object get(final DataFetchingEnvironment 
dataFetchingEnvironment) throws Exception {
+                        @Override
+                        public Object get(final DataFetchingEnvironment 
dataFetchingEnvironment) throws Exception {
 
-                                Object domainObjectInstance = 
dataFetchingEnvironment.getSource();
+                            Object domainObjectInstance = 
dataFetchingEnvironment.getSource();
 
-                                Class<?> domainObjectInstanceClass = 
domainObjectInstance.getClass();
-                                ObjectSpecification specification = 
specificationLoader
-                                        
.loadSpecification(domainObjectInstanceClass);
+                            Class<?> domainObjectInstanceClass = 
domainObjectInstance.getClass();
+                            ObjectSpecification specification = 
specificationLoader
+                                    
.loadSpecification(domainObjectInstanceClass);
 
-                                ManagedObject owner = 
ManagedObject.adaptSingular(specification, domainObjectInstance);
+                            ManagedObject owner = 
ManagedObject.adaptSingular(specification, domainObjectInstance);
 
-                                ActionInteractionHead actionInteractionHead = 
objectAction.interactionHead(owner);
+                            ActionInteractionHead actionInteractionHead = 
objectAction.interactionHead(owner);
 
-                                Map<String, Object> arguments = 
dataFetchingEnvironment.getArguments();
-                                Can<ObjectActionParameter> parameters = 
objectAction.getParameters();
-                                Can<ManagedObject> canOfParams = parameters
-                                        .map(oap -> {
-                                            Object argumentValue = 
arguments.get(oap.getId());
-                                            return 
ManagedObject.adaptParameter(oap, argumentValue);
-                                        });
+                            Map<String, Object> arguments = 
dataFetchingEnvironment.getArguments();
+                            Can<ObjectActionParameter> parameters = 
objectAction.getParameters();
+                            Can<ManagedObject> canOfParams = parameters
+                                    .map(oap -> {
+                                        Object argumentValue = 
arguments.get(oap.getId());
+                                        return 
ManagedObject.adaptParameter(oap, argumentValue);
+                                    });
 
-                                ManagedObject managedObject = objectAction
-                                        .execute(actionInteractionHead, 
canOfParams, InteractionInitiatedBy.USER);
+                            ManagedObject managedObject = objectAction
+                                    .execute(actionInteractionHead, 
canOfParams, InteractionInitiatedBy.USER);
 
-                                return managedObject.getPojo();
-                            }
+                            return managedObject.getPojo();
+                        }
 
-                        });
+                    });
 
-                });
+            });
 
-                queryBuilder.field(newFieldDefinition()
-                        .name(logicalTypeNameSanitized)
+            queryBuilder.field(newFieldDefinition()
+                    .name(_LTN.sanitized(objectSpec))
+                    .type(serviceAsGraphQlType)
+                    .build());
+            codeRegistryBuilder
+            .dataFetcher(
+                    FieldCoordinates.coordinates("Query", newFieldDefinition()
+                        .name(_LTN.sanitized(objectSpec))
                         .type(serviceAsGraphQlType)
+                        .build().getName()),
+                    (DataFetcher<Object>) environment -> service);
+        }
+    }
+
+    private static void addAction(ObjectAction objectAction, 
GraphQLObjectType.Builder serviceAsGraphQlType) {
+        String fieldName = objectAction.getId();
+
+        GraphQLFieldDefinition.Builder builder = newFieldDefinition()
+                .name(fieldName)
+                .type((GraphQLOutputType) 
TypeMapper.typeForObjectAction(objectAction));
+        if (objectAction.getParameters().isNotEmpty()) {
+            builder.arguments(objectAction.getParameters().stream()
+                    .map(objectActionParameter -> GraphQLArgument.newArgument()
+                            .name(objectActionParameter.getId())
+                            
.type(TypeMapper.inputTypeFor(objectActionParameter))
+                            .build())
+                    .collect(Collectors.toList()));
+        }
+        serviceAsGraphQlType
+                .field(builder
                         .build());
-                codeRegistryBuilder
-                .dataFetcher(
-                        FieldCoordinates.coordinates("Query", 
newFieldDefinition()
-                            .name(logicalTypeNameSanitized)
-                            .type(serviceAsGraphQlType)
-                            .build().getName()),
-                        (DataFetcher<Object>) environment -> service);
-            }
-        });
     }
 }

Reply via email to