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 142407489d9591789114f5a3e056f70a6bb7fbd7
Author: danhaywood <[email protected]>
AuthorDate: Wed Jan 31 13:58:34 2024 +0000

    CAUSEWAY-3676 : refactors top-level query, similar structure to lower level
---
 .../graphql/model/domain/GqlvDomainService.java    |  40 ++--
 ...tegTest.change_department_name_visibility._.gql |  10 +
 ...change_department_name_visibility.approved.json |   0
 .../DeptHeadMutating_IntegTest.java                |  20 ++
 viewers/graphql/test/src/test/resources/schema.gql | 261 +++++++++++++++++++++
 .../integration/GraphQlSourceForCauseway.java      |   7 +-
 .../graphql/viewer/toplevel/GqlvTopLevelQuery.java |  64 +++--
 7 files changed, 351 insertions(+), 51 deletions(-)

diff --git 
a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvDomainService.java
 
b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvDomainService.java
index 0ba21a2d94..d8a98ea888 100644
--- 
a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvDomainService.java
+++ 
b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvDomainService.java
@@ -21,6 +21,7 @@ package org.apache.causeway.viewer.graphql.model.domain;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import graphql.schema.DataFetcher;
 import graphql.schema.FieldCoordinates;
 import graphql.schema.GraphQLFieldDefinition;
 import graphql.schema.GraphQLObjectType;
@@ -34,22 +35,22 @@ import 
org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
 import org.apache.causeway.viewer.graphql.model.context.Context;
 
-import static 
org.apache.causeway.core.config.CausewayConfiguration.Viewer.Graphql.ApiVariant.QUERY_WITH_MUTATIONS_NON_SPEC_COMPLIANT;
-
 import lombok.Getter;
-import lombok.val;
 
 /**
  * Exposes a domain service (view model or entity) via the GQL viewer.
  */
 public class GqlvDomainService implements GqlvAction.Holder {
 
+    private final Holder holder;
     @Getter private final ObjectSpecification objectSpecification;
     @Getter private final Object servicePojo;
     private final Context context;
 
     private final GraphQLObjectType.Builder gqlObjectTypeBuilder;
 
+    @Getter private GraphQLFieldDefinition field;
+
     String getLogicalTypeName() {
         return objectSpecification.getLogicalTypeName();
     }
@@ -62,9 +63,11 @@ public class GqlvDomainService implements GqlvAction.Holder {
     private GraphQLObjectType gqlObjectType;
 
     public GqlvDomainService(
+            final GqlvDomainService.Holder holder,
             final ObjectSpecification objectSpecification,
             final Object servicePojo,
             final Context context) {
+        this.holder = holder;
         this.objectSpecification = objectSpecification;
         this.servicePojo = servicePojo;
         this.context = context;
@@ -75,7 +78,7 @@ public class GqlvDomainService implements GqlvAction.Holder {
 
         if (hasActions()) {
             gqlObjectType = gqlObjectTypeBuilder.build();
-            addDataFetchers();
+            addFieldFor(holder);
         }
     }
 
@@ -100,10 +103,6 @@ public class GqlvDomainService implements 
GqlvAction.Holder {
         return field;
     }
 
-    void addDataFetchers() {
-        actions.forEach((id, gqlva) -> gqlva.addDataFetcher());
-    }
-
     @Override
     public FieldCoordinates coordinatesFor(GraphQLFieldDefinition 
fieldDefinition) {
         if (gqlObjectType == null) {
@@ -113,20 +112,31 @@ public class GqlvDomainService implements 
GqlvAction.Holder {
         return coordinates(gqlObjectType, fieldDefinition);
     }
 
-    public GraphQLFieldDefinition createTopLevelQueryField() {
-        if (gqlObjectType == null) {
-            throw new IllegalStateException(String.format(
-                    "GraphQLObjectType has not yet been built for %s", 
getLogicalTypeName()));
-        }
-        return newFieldDefinition()
+    public void addFieldFor(Holder holder) {
+        holder.addField(this.field = newFieldDefinition()
                 .name(TypeNames.objectTypeNameFor(objectSpecification))
                 .type(gqlObjectType)
-                .build();
+                .build());
     }
 
+    public void addDataFetchers() {
+        context.codeRegistryBuilder.dataFetcher(
+                holder.coordinatesFor(getField()),
+                (DataFetcher<Object>) environment -> getServicePojo());
+        if (hasActions()) {
+            actions.forEach((id, gqlva) -> gqlva.addDataFetcher());
+        }
+    }
+
+
     @Override
     public String toString() {
         return objectSpecification.getLogicalTypeName();
     }
 
+
+
+    public interface Holder
+            extends GqlvHolder {
+    }
 }
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.change_department_name_visibility._.gql
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.change_department_name_visibility._.gql
new file mode 100644
index 0000000000..7c654d1143
--- /dev/null
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.change_department_name_visibility._.gql
@@ -0,0 +1,10 @@
+{
+  university_dept_Department__changeName(
+      _gqlv_target: {id : "$departmentId"},
+      newName: "Classics and Ancient History"
+  ) {
+    name {
+      get
+    }
+  }
+}
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.change_department_name_visibility.approved.json
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.change_department_name_visibility.approved.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.java
 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.java
index d1f196a984..e01706df71 100644
--- 
a/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.java
+++ 
b/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/query_and_mutations/DeptHeadMutating_IntegTest.java
@@ -87,4 +87,24 @@ public class DeptHeadMutating_IntegTest extends 
Abstract_IntegTest {
         Approvals.verify(response, jsonOptions());
     }
 
+    @Test
+    @UseReporter(DiffReporter.class)
+    void change_department_name_visibility() throws Exception {
+
+        final Bookmark bookmark =
+                transactionService.callTransactional(
+                        Propagation.REQUIRED,
+                        () -> {
+                            Department department = 
departmentRepository.findByName("Classics");
+                            Optional<Bookmark> bookmark1 = 
bookmarkService.bookmarkFor(department);
+                            return bookmark1.orElseThrow();
+                        }
+                ).valueAsNonNullElseFail();
+
+        val response = submit(_Maps.unmodifiable("$departmentId", 
bookmark.getIdentifier()));
+
+        // then payload
+        Approvals.verify(response, jsonOptions());
+    }
+
 }
diff --git a/viewers/graphql/test/src/test/resources/schema.gql 
b/viewers/graphql/test/src/test/resources/schema.gql
index 7e64b45f3b..49ec448298 100644
--- a/viewers/graphql/test/src/test/resources/schema.gql
+++ b/viewers/graphql/test/src/test/resources/schema.gql
@@ -70,6 +70,7 @@ type Query {
   causeway_applib_UserMenu: causeway_applib_UserMenu
   causeway_conf_ConfigurationMenu: causeway_conf_ConfigurationMenu
   causeway_security_LogoutMenu: causeway_security_LogoutMenu
+  university_admin_AdminMenu: university_admin_AdminMenu
   university_calc_Calculator: university_calc_Calculator
   university_dept_Departments: university_dept_Departments
   university_dept_DeptHeads: university_dept_DeptHeads
@@ -1270,6 +1271,80 @@ type 
org_apache_causeway_testing_fixtures_applib_fixturescripts_FixtureScript__q
   validate(qualifiedName: String): String
 }
 
+type university_admin_AdminMenu {
+  actionWithDisabledParam: 
university_admin_AdminMenu__actionWithDisabledParam__gqlv_action
+  actionWithHiddenParam: 
university_admin_AdminMenu__actionWithHiddenParam__gqlv_action
+  adminAction: university_admin_AdminMenu__adminAction__gqlv_action
+  otherAdminAction: university_admin_AdminMenu__otherAdminAction__gqlv_action
+}
+
+type 
university_admin_AdminMenu__actionWithDisabledParam__firstParam__gqlv_action_parameter
 {
+  disabled(firstParam: String): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_admin_AdminMenu__actionWithDisabledParam__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: 
university_admin_AdminMenu__actionWithDisabledParam__gqlv_action_params
+  validate(firstParam: String, secondParam: String, thirdParameter: String): 
String
+}
+
+type university_admin_AdminMenu__actionWithDisabledParam__gqlv_action_params {
+  firstParam: 
university_admin_AdminMenu__actionWithDisabledParam__firstParam__gqlv_action_parameter
+  secondParam: 
university_admin_AdminMenu__actionWithDisabledParam__secondParam__gqlv_action_parameter
+  thirdParameter: 
university_admin_AdminMenu__actionWithDisabledParam__thirdParameter__gqlv_action_parameter
+}
+
+type 
university_admin_AdminMenu__actionWithDisabledParam__secondParam__gqlv_action_parameter
 {
+  disabled(firstParam: String, secondParam: String): String
+  hidden(firstParam: String): Boolean
+  validity: String
+}
+
+type 
university_admin_AdminMenu__actionWithDisabledParam__thirdParameter__gqlv_action_parameter
 {
+  disabled(firstParam: String, secondParam: String, thirdParameter: String): 
String
+  hidden(firstParam: String, secondParam: String): Boolean
+  validity: String
+}
+
+type 
university_admin_AdminMenu__actionWithHiddenParam__firstParam__gqlv_action_parameter
 {
+  disabled(firstParam: String): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_admin_AdminMenu__actionWithHiddenParam__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_admin_AdminMenu__actionWithHiddenParam__gqlv_action_params
+  validate(firstParam: String, secondParam: String): String
+}
+
+type university_admin_AdminMenu__actionWithHiddenParam__gqlv_action_params {
+  firstParam: 
university_admin_AdminMenu__actionWithHiddenParam__firstParam__gqlv_action_parameter
+  secondParam: 
university_admin_AdminMenu__actionWithHiddenParam__secondParam__gqlv_action_parameter
+}
+
+type 
university_admin_AdminMenu__actionWithHiddenParam__secondParam__gqlv_action_parameter
 {
+  disabled(firstParam: String, secondParam: String): String
+  hidden(firstParam: String): Boolean
+  validity: String
+}
+
+type university_admin_AdminMenu__adminAction__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  validate: String
+}
+
+type university_admin_AdminMenu__otherAdminAction__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  validate: String
+}
+
 type university_calc_Calculator {
   addBigDecimals: university_calc_Calculator__addBigDecimals__gqlv_action
   addBigIntegers: university_calc_Calculator__addBigIntegers__gqlv_action
@@ -1756,11 +1831,89 @@ type 
university_calc_Calculator__plusJodaDays__numDays__gqlv_action_parameter {
 
 type university_dept_Department {
   _gqlv_meta: university_dept_Department__gqlv_meta
+  addStaffMember: university_dept_Department__addStaffMember__gqlv_action
+  addStaffMembers: university_dept_Department__addStaffMembers__gqlv_action
+  changeDeptHead: university_dept_Department__changeDeptHead__gqlv_action
+  changeName: university_dept_Department__changeName__gqlv_action
   deptHead: university_dept_Department__deptHead__gqlv_property
   name: university_dept_Department__name__gqlv_property
+  removeStaffMember: university_dept_Department__removeStaffMember__gqlv_action
   staffMembers: university_dept_Department__staffMembers__gqlv_collection
 }
 
+type university_dept_Department__addStaffMember__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Department__addStaffMember__gqlv_action_params
+  validate(staffMember: university_dept_StaffMember__gqlv_input): String
+}
+
+type university_dept_Department__addStaffMember__gqlv_action_params {
+  staffMember: 
university_dept_Department__addStaffMember__staffMember__gqlv_action_parameter
+}
+
+type 
university_dept_Department__addStaffMember__staffMember__gqlv_action_parameter {
+  autoComplete(search: String!): [university_dept_StaffMember]
+  disabled(staffMember: university_dept_StaffMember__gqlv_input): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_dept_Department__addStaffMembers__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Department__addStaffMembers__gqlv_action_params
+  validate(staffMembers: [university_dept_StaffMember__gqlv_input]): String
+}
+
+type university_dept_Department__addStaffMembers__gqlv_action_params {
+  staffMembers: 
university_dept_Department__addStaffMembers__staffMembers__gqlv_action_parameter
+}
+
+type 
university_dept_Department__addStaffMembers__staffMembers__gqlv_action_parameter
 {
+  choices: [university_dept_StaffMember]
+  disabled(staffMembers: [university_dept_StaffMember__gqlv_input]): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_dept_Department__changeDeptHead__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Department__changeDeptHead__gqlv_action_params
+  validate(newDeptHead: university_dept_DeptHead__gqlv_input): String
+}
+
+type university_dept_Department__changeDeptHead__gqlv_action_params {
+  newDeptHead: 
university_dept_Department__changeDeptHead__newDeptHead__gqlv_action_parameter
+}
+
+type 
university_dept_Department__changeDeptHead__newDeptHead__gqlv_action_parameter {
+  autoComplete(search: String!): [university_dept_DeptHead]
+  default: university_dept_DeptHead
+  disabled(newDeptHead: university_dept_DeptHead__gqlv_input): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_dept_Department__changeName__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Department__changeName__gqlv_action_params
+  validate(newName: String): String
+}
+
+type university_dept_Department__changeName__gqlv_action_params {
+  newName: 
university_dept_Department__changeName__newName__gqlv_action_parameter
+}
+
+type university_dept_Department__changeName__newName__gqlv_action_parameter {
+  default: String
+  disabled(newName: String): String
+  hidden: Boolean
+  validity: String
+}
+
 type university_dept_Department__deptHead__gqlv_property {
   autoComplete(search: String!): [university_dept_DeptHead]
   disabled: String
@@ -1782,6 +1935,24 @@ type university_dept_Department__name__gqlv_property {
   validate(name: String): String
 }
 
+type university_dept_Department__removeStaffMember__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Department__removeStaffMember__gqlv_action_params
+  validate(staffMember: university_dept_StaffMember__gqlv_input): String
+}
+
+type university_dept_Department__removeStaffMember__gqlv_action_params {
+  staffMember: 
university_dept_Department__removeStaffMember__staffMember__gqlv_action_parameter
+}
+
+type 
university_dept_Department__removeStaffMember__staffMember__gqlv_action_parameter
 {
+  choices: [university_dept_StaffMember]
+  disabled(staffMember: university_dept_StaffMember__gqlv_input): String
+  hidden: Boolean
+  validity: String
+}
+
 type university_dept_Department__staffMembers__gqlv_collection {
   disabled: String
   get: [university_dept_StaffMember]
@@ -1789,10 +1960,36 @@ type 
university_dept_Department__staffMembers__gqlv_collection {
 }
 
 type university_dept_Departments {
+  createDepartment: university_dept_Departments__createDepartment__gqlv_action
   findAllDepartments: 
university_dept_Departments__findAllDepartments__gqlv_action
   findDepartmentByName: 
university_dept_Departments__findDepartmentByName__gqlv_action
 }
 
+type 
university_dept_Departments__createDepartment__deptHead__gqlv_action_parameter {
+  autoComplete(name: String, search: String!): [university_dept_DeptHead]
+  disabled(deptHead: university_dept_DeptHead__gqlv_input, name: String): 
String
+  hidden(name: String): Boolean
+  validity: String
+}
+
+type university_dept_Departments__createDepartment__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Departments__createDepartment__gqlv_action_params
+  validate(deptHead: university_dept_DeptHead__gqlv_input, name: String): 
String
+}
+
+type university_dept_Departments__createDepartment__gqlv_action_params {
+  deptHead: 
university_dept_Departments__createDepartment__deptHead__gqlv_action_parameter
+  name: 
university_dept_Departments__createDepartment__name__gqlv_action_parameter
+}
+
+type 
university_dept_Departments__createDepartment__name__gqlv_action_parameter {
+  disabled(name: String): String
+  hidden: Boolean
+  validity: String
+}
+
 type university_dept_Departments__findAllDepartments__gqlv_action {
   disabled: String
   hidden: Boolean
@@ -1820,10 +2017,48 @@ type 
university_dept_Departments__findDepartmentByName__name__gqlv_action_parame
 
 type university_dept_DeptHead {
   _gqlv_meta: university_dept_DeptHead__gqlv_meta
+  changeDepartment: university_dept_DeptHead__changeDepartment__gqlv_action
+  changeName: university_dept_DeptHead__changeName__gqlv_action
   department: university_dept_DeptHead__department__gqlv_property
   name: university_dept_DeptHead__name__gqlv_property
 }
 
+type 
university_dept_DeptHead__changeDepartment__department__gqlv_action_parameter {
+  choices: [university_dept_Department]
+  disabled(department: university_dept_Department__gqlv_input): String
+  hidden: Boolean
+  validity: String
+}
+
+type university_dept_DeptHead__changeDepartment__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_DeptHead__changeDepartment__gqlv_action_params
+  validate(department: university_dept_Department__gqlv_input): String
+}
+
+type university_dept_DeptHead__changeDepartment__gqlv_action_params {
+  department: 
university_dept_DeptHead__changeDepartment__department__gqlv_action_parameter
+}
+
+type university_dept_DeptHead__changeName__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_DeptHead__changeName__gqlv_action_params
+  validate(newName: String): String
+}
+
+type university_dept_DeptHead__changeName__gqlv_action_params {
+  newName: university_dept_DeptHead__changeName__newName__gqlv_action_parameter
+}
+
+type university_dept_DeptHead__changeName__newName__gqlv_action_parameter {
+  default: String
+  disabled(newName: String): String
+  hidden: Boolean
+  validity: String
+}
+
 type university_dept_DeptHead__department__gqlv_property {
   choices(department: university_dept_Department__gqlv_input): 
[university_dept_Department]
   disabled: String
@@ -1876,6 +2111,7 @@ type 
university_dept_DeptHeads__findHeadByName__name__gqlv_action_parameter {
 }
 
 type university_dept_Staff {
+  createStaffMember: university_dept_Staff__createStaffMember__gqlv_action
   findAllStaffMembers: university_dept_Staff__findAllStaffMembers__gqlv_action
   findStaffMemberByName: 
university_dept_Staff__findStaffMemberByName__gqlv_action
 }
@@ -1924,6 +2160,31 @@ type university_dept_StaffMember__photo__gqlv_property {
   validate(photo: String): String
 }
 
+type 
university_dept_Staff__createStaffMember__department__gqlv_action_parameter {
+  choices(name: String): [university_dept_Department]
+  disabled(department: university_dept_Department__gqlv_input, name: String): 
String
+  hidden(name: String): Boolean
+  validity: String
+}
+
+type university_dept_Staff__createStaffMember__gqlv_action {
+  disabled: String
+  hidden: Boolean
+  params: university_dept_Staff__createStaffMember__gqlv_action_params
+  validate(department: university_dept_Department__gqlv_input, name: String): 
String
+}
+
+type university_dept_Staff__createStaffMember__gqlv_action_params {
+  department: 
university_dept_Staff__createStaffMember__department__gqlv_action_parameter
+  name: university_dept_Staff__createStaffMember__name__gqlv_action_parameter
+}
+
+type university_dept_Staff__createStaffMember__name__gqlv_action_parameter {
+  disabled(name: String): String
+  hidden: Boolean
+  validity: String
+}
+
 type university_dept_Staff__findAllStaffMembers__gqlv_action {
   disabled: String
   hidden: Boolean
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
index 852ec0c70a..493dd1defd 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
@@ -108,7 +108,7 @@ public class GraphQlSourceForCauseway implements 
GraphQlSource {
         val context = new Context(codeRegistryBuilder, bookmarkService, 
specificationLoader, typeMapper, serviceRegistry, causewayConfiguration, 
causewaySystemEnvironment);
 
         // add to the top-level query type and (dependent on configuration) 
the top-level mutation type also
-        val topLevelQuery = new GqlvTopLevelQuery(serviceRegistry, 
codeRegistryBuilder);
+        val topLevelQuery = new GqlvTopLevelQuery();
         val topLevelMutation =
                 causewayConfiguration.getViewer().getGraphql().getApiVariant() 
== CausewayConfiguration.Viewer.Graphql.ApiVariant.QUERY_AND_MUTATIONS ?
                     new GqlvTopLevelMutation(context)
@@ -127,7 +127,10 @@ public class GraphQlSourceForCauseway implements 
GraphQlSource {
             switch (objectSpec.getBeanSort()) {
                 case MANAGED_BEAN_CONTRIBUTING: // @DomainService
                     
serviceRegistry.lookupBeanById(objectSpec.getLogicalTypeName())
-                        .ifPresent(servicePojo -> 
topLevelQuery.addDomainServiceTo(objectSpec, servicePojo, context));
+                        .ifPresent(servicePojo -> {
+                            topLevelQuery.addDomainService(objectSpec, 
servicePojo, context);
+                            topLevelQuery.addDataFetchers();
+                        });
                     break;
             }
         });
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelQuery.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelQuery.java
index cb7b8db159..3ebf14055a 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelQuery.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelQuery.java
@@ -1,27 +1,25 @@
 package org.apache.causeway.viewer.graphql.viewer.toplevel;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import graphql.schema.FieldCoordinates;
+import graphql.schema.GraphQLFieldDefinition;
+import graphql.schema.GraphQLObjectType;
+
 import static graphql.schema.GraphQLObjectType.newObject;
 
-import org.apache.causeway.applib.services.registry.ServiceRegistry;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.viewer.graphql.model.context.Context;
 import org.apache.causeway.viewer.graphql.model.domain.GqlvDomainService;
 
-import graphql.schema.DataFetcher;
-import graphql.schema.FieldCoordinates;
-import graphql.schema.GraphQLCodeRegistry;
-import graphql.schema.GraphQLFieldDefinition;
-import graphql.schema.GraphQLObjectType;
 import lombok.Getter;
-import lombok.val;
-
-public class GqlvTopLevelQuery {
-
-    private final ServiceRegistry serviceRegistry;
-    private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
 
+public class GqlvTopLevelQuery implements GqlvDomainService.Holder {
     @Getter final GraphQLObjectType.Builder queryBuilder;
 
+    private final List<GqlvDomainService> domainServices = new ArrayList<>();
+
 
     /**
      * Built using {@link #buildQueryType()}
@@ -29,13 +27,8 @@ public class GqlvTopLevelQuery {
     private GraphQLObjectType queryType;
 
 
-    public GqlvTopLevelQuery(
-            final ServiceRegistry serviceRegistry,
-            final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
-        this.serviceRegistry = serviceRegistry;
-        this.codeRegistryBuilder = codeRegistryBuilder;
+    public GqlvTopLevelQuery() {
         queryBuilder = newObject().name("Query");
-
     }
 
 
@@ -58,27 +51,30 @@ public class GqlvTopLevelQuery {
         return queryType;
     }
 
-    public void addFieldFor(
-            final GqlvDomainService domainService,
-            final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
-
-        GraphQLFieldDefinition topLevelQueryField = 
domainService.createTopLevelQueryField();
-        queryBuilder.field(topLevelQueryField);
+    public void addDomainService(ObjectSpecification objectSpec, Object 
servicePojo, Context context) {
+        domainServices.add(new GqlvDomainService(this, objectSpec, 
servicePojo, context));
+    }
 
-        codeRegistryBuilder.dataFetcher(
-                // TODO: it would be nice to make these typesafe...
-                FieldCoordinates.coordinates("Query", 
topLevelQueryField.getName()),
-                (DataFetcher<Object>) environment -> 
domainService.getServicePojo());
 
+    @Override
+    public FieldCoordinates coordinatesFor(GraphQLFieldDefinition 
fieldDefinition) {
+        return FieldCoordinates.coordinates("Query", 
fieldDefinition.getName());
     }
 
-    public void addDomainServiceTo(final ObjectSpecification objectSpec, final 
Object servicePojo, final Context context) {
-        val domainService = new GqlvDomainService(objectSpec, servicePojo, 
context);
+    @Override
+    public GraphQLFieldDefinition addField(GraphQLFieldDefinition field) {
+        queryBuilder.field(field);
+        return field;
+    }
 
-        boolean actionsAdded = domainService.hasActions();
-        if (actionsAdded) {
-            addFieldFor(domainService, context.codeRegistryBuilder);
-        }
+    public void addDataFetchers() {
+        domainServices.forEach(domainService -> {
+            boolean actionsAdded = domainService.hasActions();
+            if (actionsAdded) {
+                domainService.addDataFetchers();
+            }
+        });
     }
 
+
 }

Reply via email to