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 7c4cf784887ed368c94015446f992e23952bb0a7
Author: danhaywood <[email protected]>
AuthorDate: Tue Jan 30 15:26:28 2024 +0000

    CAUSEWAY-3676: mutation support for actions now works
---
 .../viewer/graphql/model/domain/GqlvMutation.java  | 125 +++++++++++++++------
 viewers/graphql/test/src/test/resources/schema.gql |  22 ++--
 .../viewer/toplevel/GqlvTopLevelMutation.java      | 125 +--------------------
 3 files changed, 104 insertions(+), 168 deletions(-)

diff --git 
a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvMutation.java
 
b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvMutation.java
index d6f5298cef..d07693e89b 100644
--- 
a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvMutation.java
+++ 
b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvMutation.java
@@ -18,62 +18,74 @@
  */
 package org.apache.causeway.viewer.graphql.model.domain;
 
-import graphql.schema.*;
+import java.util.ArrayList;
 
-import lombok.extern.log4j.Log4j2;
-import lombok.val;
+import graphql.schema.DataFetchingEnvironment;
+import graphql.schema.GraphQLArgument;
+import graphql.schema.GraphQLFieldDefinition;
+import graphql.schema.GraphQLList;
+import graphql.schema.GraphQLOutputType;
+import graphql.schema.GraphQLType;
+
+import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
+
+import org.springframework.lang.Nullable;
 
 import org.apache.causeway.applib.annotation.Where;
-import org.apache.causeway.applib.services.bookmark.BookmarkService;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.causeway.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
+import 
org.apache.causeway.core.metamodel.spec.feature.OneToManyActionParameter;
+import org.apache.causeway.core.metamodel.spec.feature.OneToOneActionParameter;
 import org.apache.causeway.viewer.graphql.applib.types.TypeMapper;
 import org.apache.causeway.viewer.graphql.model.context.Context;
 import org.apache.causeway.viewer.graphql.model.exceptions.DisabledException;
 import org.apache.causeway.viewer.graphql.model.exceptions.HiddenException;
-import 
org.apache.causeway.viewer.graphql.model.mmproviders.ObjectActionProvider;
-import 
org.apache.causeway.viewer.graphql.model.mmproviders.ObjectSpecificationProvider;
-
-import org.springframework.lang.Nullable;
 
-import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 public class GqlvMutation {
 
     private final Holder holder;
+    private final ObjectSpecification objectSpec;
+    private final ObjectAction objectAction;
     private final Context context;
     private final GraphQLFieldDefinition field;
     private String argumentName;
 
     public GqlvMutation(
             final Holder holder,
-            final Context context) {
+            final ObjectSpecification objectSpec,
+            final ObjectAction objectAction,
+        final Context context) {
         this.holder = holder;
+        this.objectSpec = objectSpec;
+        this.objectAction = objectAction;
         this.context = context;
 
         this.argumentName = 
context.causewayConfiguration.getViewer().getGraphql().getMutation().getTargetArgName();
 
-        val objectSpec = holder.getObjectSpecification();
-        val objectAction = holder.getObjectAction();
-
         GraphQLOutputType type = typeFor(objectAction);
         if (type != null) {
             val fieldBuilder = newFieldDefinition()
                     .name(fieldName(objectSpec, objectAction))
                     .type(type);
-            holder.addGqlArguments(fieldBuilder, 
TypeMapper.InputContext.INVOKE);
+            addGqlArguments(fieldBuilder);
             this.field = holder.addField(fieldBuilder.build());
         } else {
             this.field = null;
         }
     }
 
-    private static String fieldName(ObjectSpecification objectSpecification, 
ObjectAction objectAction) {
+    private static String fieldName(
+            final ObjectSpecification objectSpecification,
+            final ObjectAction objectAction) {
         return TypeNames.objectTypeNameFor(objectSpecification) + "__" + 
objectAction.getId();
     }
 
@@ -117,21 +129,18 @@ public class GqlvMutation {
 
     private Object invoke(final DataFetchingEnvironment 
dataFetchingEnvironment) {
 
-        val objectSpecification = holder.getObjectSpecification();
-        val objectAction = holder.getObjectAction();
-
-        val isService = 
objectSpecification.getBeanSort().isManagedBeanContributing();
+        val isService = objectSpec.getBeanSort().isManagedBeanContributing();
 
         Object sourcePojo;
         if (isService) {
-            sourcePojo = 
context.serviceRegistry.lookupServiceElseFail(objectSpecification.getCorrespondingClass());
+            sourcePojo = 
context.serviceRegistry.lookupServiceElseFail(objectSpec.getCorrespondingClass());
         } else {
             Object target = dataFetchingEnvironment.getArgument(argumentName);
-            sourcePojo = GqlvAction.asPojo(objectSpecification, target, 
context.bookmarkService)
+            sourcePojo = GqlvAction.asPojo(objectSpec, target, 
context.bookmarkService)
                     .orElseThrow(); // TODO: better error handling if no such 
object found.
         }
 
-        ManagedObject managedObject = 
ManagedObject.adaptSingular(objectSpecification, sourcePojo);
+        ManagedObject managedObject = ManagedObject.adaptSingular(objectSpec, 
sourcePojo);
 
         val visibleConsent = objectAction.isVisible(managedObject, 
InteractionInitiatedBy.USER, Where.ANYWHERE);
         if (visibleConsent.isVetoed()) {
@@ -144,7 +153,7 @@ public class GqlvMutation {
         }
 
         val head = objectAction.interactionHead(managedObject);
-        val argumentManagedObjects = 
holder.argumentManagedObjectsFor(dataFetchingEnvironment, objectAction, 
context.bookmarkService);
+        val argumentManagedObjects = 
argumentManagedObjectsFor(dataFetchingEnvironment, objectAction);
 
         val validityConsent = objectAction.isArgumentSetValid(head, 
argumentManagedObjects, InteractionInitiatedBy.USER);
         if (validityConsent.isVetoed()) {
@@ -155,18 +164,64 @@ public class GqlvMutation {
         return resultManagedObject.getPojo();
     }
 
+
+    // TODO: adapted from GqlvAction - rationalize?
+    private void addGqlArguments(final GraphQLFieldDefinition.Builder 
fieldBuilder) {
+
+        val arguments = new ArrayList<GraphQLArgument>();
+        val argName = 
context.causewayConfiguration.getViewer().getGraphql().getMutation().getTargetArgName();
+
+        // add target (if not a service)
+        if (! objectSpec.getBeanSort().isManagedBeanContributing()) {
+            arguments.add(
+                    GraphQLArgument.newArgument()
+                            .name(argName)
+                            .type(context.typeMapper.inputTypeFor(objectSpec))
+                            .build()
+            );
+        }
+
+        val parameters = objectAction.getParameters();
+        parameters.stream()
+                .map(this::gqlArgumentFor)
+                .forEach(arguments::add);
+
+        if (!arguments.isEmpty()) {
+            fieldBuilder.arguments(arguments);
+        }
+    }
+
+    // adapted from GqlvAction
+    GraphQLArgument gqlArgumentFor(final ObjectActionParameter 
objectActionParameter) {
+        return objectActionParameter.isPlural()
+                ? gqlArgumentFor((OneToManyActionParameter) 
objectActionParameter)
+                : gqlArgumentFor((OneToOneActionParameter) 
objectActionParameter);
+    }
+
+    // adapted from GqlvAction
+    GraphQLArgument gqlArgumentFor(final OneToOneActionParameter 
oneToOneActionParameter) {
+        return GraphQLArgument.newArgument()
+                .name(oneToOneActionParameter.getId())
+                .type(context.typeMapper.inputTypeFor(oneToOneActionParameter, 
TypeMapper.InputContext.INVOKE))
+                .build();
+    }
+
+    // adapted from GqlvAction
+    GraphQLArgument gqlArgumentFor(final OneToManyActionParameter 
oneToManyActionParameter) {
+        return GraphQLArgument.newArgument()
+                .name(oneToManyActionParameter.getId())
+                
.type(context.typeMapper.inputTypeFor(oneToManyActionParameter))
+                .build();
+    }
+
+    private Can<ManagedObject> argumentManagedObjectsFor(
+            final DataFetchingEnvironment dataFetchingEnvironment,
+            final ObjectAction objectAction) {
+        return GqlvAction.argumentManagedObjectsFor(dataFetchingEnvironment, 
objectAction, context);
+    }
+
     public interface Holder
-            extends GqlvHolder,
-                    ObjectSpecificationProvider,
-                    ObjectActionProvider {
-
-        void addGqlArguments(
-                final GraphQLFieldDefinition.Builder fieldBuilder,
-                final TypeMapper.InputContext inputContext);
-
-        Can<ManagedObject> argumentManagedObjectsFor(
-                final DataFetchingEnvironment dataFetchingEnvironment,
-                final ObjectAction objectAction,
-                final BookmarkService bookmarkService);
+            extends GqlvHolder {
     }
+
 }
diff --git a/viewers/graphql/test/src/test/resources/schema.gql 
b/viewers/graphql/test/src/test/resources/schema.gql
index 94ac2ae9d2..5f6c0fe828 100644
--- a/viewers/graphql/test/src/test/resources/schema.gql
+++ b/viewers/graphql/test/src/test/resources/schema.gql
@@ -23,22 +23,22 @@ directive @specifiedBy(
   ) on SCALAR
 
 type Mutation {
-  causeway_applib_PropertyNode__streamChildNodes(target: 
causeway_applib_PropertyNode__gqlv_input): java_util_stream_Stream
-  causeway_applib_node_ActionNode__streamChildNodes(target: 
causeway_applib_node_ActionNode__gqlv_input): java_util_stream_Stream
-  causeway_applib_node_CollectionNode__streamChildNodes(target: 
causeway_applib_node_CollectionNode__gqlv_input): java_util_stream_Stream
-  
org_apache_causeway_core_metamodel_inspect_model_MemberNode__streamChildNodes(target:
 org_apache_causeway_core_metamodel_inspect_model_MemberNode__gqlv_input): 
java_util_stream_Stream
+  causeway_applib_PropertyNode__streamChildNodes(_gqlv_target: 
causeway_applib_PropertyNode__gqlv_input): java_util_stream_Stream
+  causeway_applib_node_ActionNode__streamChildNodes(_gqlv_target: 
causeway_applib_node_ActionNode__gqlv_input): java_util_stream_Stream
+  causeway_applib_node_CollectionNode__streamChildNodes(_gqlv_target: 
causeway_applib_node_CollectionNode__gqlv_input): java_util_stream_Stream
+  
org_apache_causeway_core_metamodel_inspect_model_MemberNode__streamChildNodes(_gqlv_target:
 org_apache_causeway_core_metamodel_inspect_model_MemberNode__gqlv_input): 
java_util_stream_Stream
   university_admin_AdminMenu__actionWithDisabledParam(firstParam: String!, 
secondParam: String!, thirdParameter: String!): String
   university_admin_AdminMenu__actionWithHiddenParam(firstParam: String!, 
secondParam: String!): String
   university_admin_AdminMenu__adminAction: String
   university_admin_AdminMenu__otherAdminAction: String
-  university_dept_Department__addStaffMember(staffMember: 
university_dept_StaffMember__gqlv_input!, target: 
university_dept_Department__gqlv_input): university_dept_Department
-  university_dept_Department__addStaffMembers(staffMembers: 
[university_dept_StaffMember__gqlv_input], target: 
university_dept_Department__gqlv_input): university_dept_Department
-  university_dept_Department__changeDeptHead(newDeptHead: 
university_dept_DeptHead__gqlv_input!, target: 
university_dept_Department__gqlv_input): university_dept_Department
-  university_dept_Department__changeName(newName: String!, target: 
university_dept_Department__gqlv_input): university_dept_Department
-  university_dept_Department__removeStaffMember(staffMember: 
university_dept_StaffMember__gqlv_input!, target: 
university_dept_Department__gqlv_input): university_dept_Department
+  university_dept_Department__addStaffMember(_gqlv_target: 
university_dept_Department__gqlv_input, staffMember: 
university_dept_StaffMember__gqlv_input!): university_dept_Department
+  university_dept_Department__addStaffMembers(_gqlv_target: 
university_dept_Department__gqlv_input, staffMembers: 
[university_dept_StaffMember__gqlv_input]): university_dept_Department
+  university_dept_Department__changeDeptHead(_gqlv_target: 
university_dept_Department__gqlv_input, newDeptHead: 
university_dept_DeptHead__gqlv_input!): university_dept_Department
+  university_dept_Department__changeName(_gqlv_target: 
university_dept_Department__gqlv_input, newName: String!): 
university_dept_Department
+  university_dept_Department__removeStaffMember(_gqlv_target: 
university_dept_Department__gqlv_input, staffMember: 
university_dept_StaffMember__gqlv_input!): university_dept_Department
   university_dept_Departments__createDepartment(deptHead: 
university_dept_DeptHead__gqlv_input, name: String!): university_dept_Department
-  university_dept_DeptHead__changeDepartment(department: 
university_dept_Department__gqlv_input!, target: 
university_dept_DeptHead__gqlv_input): university_dept_DeptHead
-  university_dept_DeptHead__changeName(newName: String!, target: 
university_dept_DeptHead__gqlv_input): university_dept_DeptHead
+  university_dept_DeptHead__changeDepartment(_gqlv_target: 
university_dept_DeptHead__gqlv_input, department: 
university_dept_Department__gqlv_input!): university_dept_DeptHead
+  university_dept_DeptHead__changeName(_gqlv_target: 
university_dept_DeptHead__gqlv_input, newName: String!): 
university_dept_DeptHead
   university_dept_Staff__createStaffMember(department: 
university_dept_Department__gqlv_input!, name: String!): 
university_dept_StaffMember
 }
 
diff --git 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelMutation.java
 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelMutation.java
index 00db413aee..3d4a792f53 100644
--- 
a/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelMutation.java
+++ 
b/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/toplevel/GqlvTopLevelMutation.java
@@ -3,32 +3,20 @@ package org.apache.causeway.viewer.graphql.viewer.toplevel;
 import java.util.ArrayList;
 import java.util.List;
 
-import graphql.schema.DataFetchingEnvironment;
 import graphql.schema.FieldCoordinates;
-import graphql.schema.GraphQLArgument;
 import graphql.schema.GraphQLFieldDefinition;
 import graphql.schema.GraphQLObjectType;
 
 import static graphql.schema.GraphQLObjectType.newObject;
 
-import org.apache.causeway.applib.services.bookmark.BookmarkService;
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
-import 
org.apache.causeway.core.metamodel.spec.feature.OneToManyActionParameter;
-import org.apache.causeway.core.metamodel.spec.feature.OneToOneActionParameter;
-import org.apache.causeway.viewer.graphql.applib.types.TypeMapper;
 import org.apache.causeway.viewer.graphql.model.context.Context;
-import org.apache.causeway.viewer.graphql.model.domain.GqlvAction;
 import org.apache.causeway.viewer.graphql.model.domain.GqlvMutation;
-import org.apache.causeway.viewer.graphql.model.domain.GqlvHolder;
 
 import lombok.Getter;
-import lombok.val;
 
-public class GqlvTopLevelMutation implements GqlvHolder {
+public class GqlvTopLevelMutation implements GqlvMutation.Holder {
 
     private final Context context;
 
@@ -68,25 +56,9 @@ public class GqlvTopLevelMutation implements GqlvHolder {
         return gqlObjectType;
     }
 
-//    public void addFieldFor(
-//            final GqlvDomainService domainService,
-//            final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
-//
-//        GraphQLFieldDefinition topLevelQueryField = 
domainService.createTopLevelQueryField();
-//        gqlObjectBuilder.field(topLevelQueryField);
-//
-//        codeRegistryBuilder.dataFetcher(
-//                // TODO: it would be nice to make these typesafe...
-//                FieldCoordinates.coordinates("Mutation", 
topLevelQueryField.getName()),
-//                (DataFetcher<Object>) environment -> 
domainService.getServicePojo());
-//
-//    }
-
 
     public void addAction(ObjectSpecification objectSpec, final ObjectAction 
objectAction) {
-        // TODO: kinda ugly the responsibilities here
-        val holder = new GqlvMutationHolder(this, objectSpec, objectAction, 
context);
-        actions.add(new GqlvMutation(holder, context));
+        actions.add(new GqlvMutation(this, objectSpec, objectAction, context));
     }
 
     @Override
@@ -103,98 +75,7 @@ public class GqlvTopLevelMutation implements GqlvHolder {
     public void addDataFetchers() {
         actions.forEach(GqlvMutation::addDataFetcher);
     }
-}
-
-class GqlvMutationHolder implements GqlvMutation.Holder {
-
-    private final GqlvTopLevelMutation gqlvTopLevelMutation;
-    private final ObjectSpecification objectSpec;
-    private final ObjectAction objectAction;
-    private final Context context;
-
-    public GqlvMutationHolder(
-            final GqlvTopLevelMutation gqlvTopLevelMutation,
-            final ObjectSpecification objectSpec,
-            final ObjectAction objectAction,
-            final Context context) {
-        this.objectSpec = objectSpec;
-        this.objectAction = objectAction;
-        this.gqlvTopLevelMutation = gqlvTopLevelMutation;
-        this.context = context;
-    }
-
-    @Override public ObjectAction getObjectAction() {return objectAction;}
-    @Override public ObjectAction getObjectMember() {return objectAction;}
-    @Override public ObjectSpecification getObjectSpecification() {return 
objectSpec;}
-
-    // TODO: adapted from GqlvAction
-    @Override
-    public void addGqlArguments(
-            final GraphQLFieldDefinition.Builder fieldBuilder,
-            final TypeMapper.InputContext inputContext) {
-
-        val arguments = new ArrayList<GraphQLArgument>();
-        val argName = 
context.causewayConfiguration.getViewer().getGraphql().getMutation().getTargetArgName();
-
-        // add target (if not a service)
-        if (! objectSpec.getBeanSort().isManagedBeanContributing()) {
-            arguments.add(
-                GraphQLArgument.newArgument()
-                        .name(argName)
-                        .type(context.typeMapper.inputTypeFor(objectSpec))
-                        .build()
-            );
-        }
-
-        val parameters = objectAction.getParameters();
-        parameters.stream()
-                .map(this::gqlArgumentFor)
-                .forEach(arguments::add);
-
-        if (!arguments.isEmpty()) {
-            fieldBuilder.arguments(arguments);
-        }
-    }
 
-    // adapted from GqlvAction
-    GraphQLArgument gqlArgumentFor(final ObjectActionParameter 
objectActionParameter) {
-        return objectActionParameter.isPlural()
-                ? gqlArgumentFor((OneToManyActionParameter) 
objectActionParameter)
-                : gqlArgumentFor((OneToOneActionParameter) 
objectActionParameter);
-    }
-
-    // adapted from GqlvAction
-    GraphQLArgument gqlArgumentFor(final OneToOneActionParameter 
oneToOneActionParameter) {
-        return GraphQLArgument.newArgument()
-                .name(oneToOneActionParameter.getId())
-                .type(context.typeMapper.inputTypeFor(oneToOneActionParameter, 
TypeMapper.InputContext.INVOKE))
-                .build();
-    }
-
-    // TODO: copied from GqlvAction
-    GraphQLArgument gqlArgumentFor(final OneToManyActionParameter 
oneToManyActionParameter) {
-        return GraphQLArgument.newArgument()
-                .name(oneToManyActionParameter.getId())
-                
.type(context.typeMapper.inputTypeFor(oneToManyActionParameter))
-                .build();
-    }
-
-    @Override
-    public Can<ManagedObject> argumentManagedObjectsFor(
-            final DataFetchingEnvironment dataFetchingEnvironment,
-            final ObjectAction objectAction,
-            final BookmarkService bookmarkService) {
-        return GqlvAction.argumentManagedObjectsFor(dataFetchingEnvironment, 
objectAction, context);
-    }
-
-    @Override
-    public GraphQLFieldDefinition addField(GraphQLFieldDefinition 
fieldDefinition) {
-        return gqlvTopLevelMutation.addField(fieldDefinition);
-    }
-
-    @Override
-    public FieldCoordinates coordinatesFor(GraphQLFieldDefinition 
fieldDefinition) {
-        return gqlvTopLevelMutation.coordinatesFor(fieldDefinition);
-    }
 
 }
+

Reply via email to