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 1f5dfa52e2 CAUSEWAY-3676: adds example of specifying a reference to an 
entity as an input type
1f5dfa52e2 is described below

commit 1f5dfa52e2a5279892c6f80ef964be2391c64fec
Author: danhaywood <[email protected]>
AuthorDate: Wed Jan 24 23:19:01 2024 +0000

    CAUSEWAY-3676: adds example of specifying a reference to an entity as an 
input type
---
 .../viewer/graphql/model/domain/GqlvAction.java    |  2 +-
 .../graphql/model/domain/GqlvActionInvoke.java     | 44 ++++++++++++++++++++--
 ...ayViewerGraphqlTestModuleIntegTestAbstract.java | 33 +++++++++++++---
 ...gTest.create_staff_member_with_department._.gql | 18 +++++++++
 ...eate_staff_member_with_department.approved.json | 20 ++++++++++
 .../graphql/viewer/test/e2e/Domain_IntegTest.java  | 21 +++++++++++
 6 files changed, 128 insertions(+), 10 deletions(-)

diff --git 
a/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvAction.java
 
b/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvAction.java
index f51077c69d..2125886224 100644
--- 
a/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvAction.java
+++ 
b/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvAction.java
@@ -60,7 +60,7 @@ public class GqlvAction
         this.hidden = new GqlvMemberHidden(this, codeRegistryBuilder);
         this.disabled = new GqlvMemberDisabled(this, codeRegistryBuilder);
         this.validate = new GqlvActionValidate(this, codeRegistryBuilder);
-        this.invoke = new GqlvActionInvoke(this, codeRegistryBuilder);
+        this.invoke = new GqlvActionInvoke(this, codeRegistryBuilder, 
bookmarkService);
 
         this.gqlObjectType = gqlObjectTypeBuilder.build();
 
diff --git 
a/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvActionInvoke.java
 
b/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvActionInvoke.java
index 925e825fae..79ac4ef813 100644
--- 
a/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvActionInvoke.java
+++ 
b/incubator/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/GqlvActionInvoke.java
@@ -19,9 +19,11 @@
 package org.apache.causeway.viewer.graphql.model.domain;
 
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
-import org.apache.causeway.core.metamodel.consent.Consent;
+import org.apache.causeway.applib.services.bookmark.Bookmark;
+import org.apache.causeway.applib.services.bookmark.BookmarkService;
 import org.apache.causeway.core.metamodel.spec.feature.OneToOneActionParameter;
 
 import org.springframework.lang.Nullable;
@@ -54,14 +56,16 @@ public class GqlvActionInvoke {
     private final GqlvActionInvokeHolder holder;
     private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
     private final GraphQLFieldDefinition field;
+    private final BookmarkService bookmarkService;
 
     public GqlvActionInvoke(
             final GqlvActionInvokeHolder holder,
-            final GraphQLCodeRegistry.Builder codeRegistryBuilder
-    ) {
+            final GraphQLCodeRegistry.Builder codeRegistryBuilder,
+            final BookmarkService bookmarkService) {
         this.holder = holder;
         this.codeRegistryBuilder = codeRegistryBuilder;
         this.field = fieldDefinition(holder);
+        this.bookmarkService = bookmarkService;
     }
 
     private static GraphQLFieldDefinition fieldDefinition(final 
GqlvActionInvokeHolder holder) {
@@ -178,8 +182,40 @@ public class GqlvActionInvoke {
         Can<ObjectActionParameter> parameters = objectAction.getParameters();
         Can<ManagedObject> argumentManagedObjects = parameters
                 .map(oap -> {
+                    final ObjectSpecification elementType = 
oap.getElementType();
                     Object argumentValue = argumentPojos.get(oap.getId());
-                    return ManagedObject.adaptParameter(oap, argumentValue);
+                    switch (elementType.getBeanSort()) {
+
+                        case VALUE:
+                            return ManagedObject.adaptParameter(oap, 
argumentValue);
+
+                        case ENTITY:
+                        case VIEW_MODEL:
+                            //noinspection unchecked
+                            if (argumentValue == null) {
+                                return ManagedObject.empty(elementType);
+                            }
+                            String idValue = ((Map<String, String>) 
argumentValue).get("id");
+                            Class<?> paramClass = 
elementType.getCorrespondingClass();
+                            Optional<Bookmark> bookmarkIfAny = 
bookmarkService.bookmarkFor(paramClass, idValue);
+                            return bookmarkIfAny
+                                    .map(bookmarkService::lookup)
+                                    .filter(Optional::isPresent)
+                                    .map(Optional::get)
+                                    .map(pojo -> 
ManagedObject.adaptParameter(oap, pojo))
+                                    .orElse(ManagedObject.empty(elementType));
+
+                        case ABSTRACT:
+                        case COLLECTION:
+                        case MANAGED_BEAN_CONTRIBUTING:
+                        case VETOED:
+                        case MANAGED_BEAN_NOT_CONTRIBUTING:
+                        case MIXIN:
+                        case UNKNOWN:
+                        default:
+                            throw new IllegalArgumentException(String.format(
+                                    "Cannot handle an input type for %s; 
beanSort is %s", elementType.getFullIdentifier(), elementType.getBeanSort()));
+                    }
                 });
 
         val consent = objectAction.isArgumentSetValid(actionInteractionHead, 
argumentManagedObjects, InteractionInitiatedBy.USER);
diff --git 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/CausewayViewerGraphqlTestModuleIntegTestAbstract.java
 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/CausewayViewerGraphqlTestModuleIntegTestAbstract.java
index f07abad316..1496364764 100644
--- 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/CausewayViewerGraphqlTestModuleIntegTestAbstract.java
+++ 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/CausewayViewerGraphqlTestModuleIntegTestAbstract.java
@@ -28,6 +28,8 @@ import java.net.http.HttpClient;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
 
 import javax.inject.Inject;
 
@@ -36,7 +38,6 @@ import 
org.apache.causeway.commons.internal.resources._Resources;
 
 import org.apache.causeway.core.config.environment.CausewaySystemEnvironment;
 import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
-import 
org.apache.causeway.testing.fixtures.applib.CausewayIntegrationTestAbstractWithFixtures;
 import 
org.apache.causeway.viewer.graphql.viewer.integration.ExecutionGraphQlServiceForCauseway;
 import 
org.apache.causeway.viewer.graphql.viewer.integration.GraphQlSourceForCauseway;
 
@@ -156,7 +157,11 @@ public abstract class 
CausewayViewerGraphqlTestModuleIntegTestAbstract {
      * @throws Exception if an error occurs during the submission
      */
     protected String submit() throws Exception{
-        val httpRequest = buildRequest(testInfo, "._.gql");
+        return submit(Collections.emptyMap());
+    }
+
+    protected String submit(Map<String,String> replacements) throws Exception{
+        val httpRequest = buildRequest(testInfo, "._.gql", replacements);
         return submitRequest(httpRequest);
     }
 
@@ -167,15 +172,17 @@ public abstract class 
CausewayViewerGraphqlTestModuleIntegTestAbstract {
 
     protected HttpRequest buildRequest(
             final TestInfo testInfo,
-            final String resourceSuffix) throws IOException {
+            final String resourceSuffix,
+            final Map<String, String> replacements) throws IOException {
 
         val testMethodName = 
testInfo.getTestMethod().map(Method::getName).get();
         val resourceName = getClass().getSimpleName() + "." + testMethodName + 
resourceSuffix;
-        val resourceContents = readResource(resourceName);
+        String resourceContents = readResource(resourceName);
+        String resourceContent = replace(resourceContents, replacements);
 
         val uri = URI.create(String.format("http://0.0.0.0:%d/graphql";, port));
 
-        val gqlBody = new GqlBody(resourceContents);
+        val gqlBody = new GqlBody(resourceContent);
         val gqlBodyStr = objectMapper.writeValueAsString(gqlBody);
         val bodyPublisher = HttpRequest.BodyPublishers.ofString(gqlBodyStr);
 
@@ -186,6 +193,22 @@ public abstract class 
CausewayViewerGraphqlTestModuleIntegTestAbstract {
                 build();
     }
 
+    private static String replace(String str, Map<String, String> 
replacements) {
+        val builder = new StringBuilder(str);
+        replacements.forEach((key, value) -> {
+            int index;
+            int numMatches = 0;
+            while ((index = builder.indexOf(key)) != -1) {
+                builder.replace(index, index + key.length(), value);
+                numMatches++;
+            }
+            if (numMatches == 0) {
+                throw new IllegalArgumentException("Could not find '" + key + 
"' to replace");
+            }
+        });
+        return builder.toString();
+    }
+
     private String submitRequest(final HttpRequest request) throws 
IOException, InterruptedException {
         val responseBodyHandler = HttpResponse.BodyHandlers.ofString();
         val httpClient = HttpClient.newBuilder().build();
diff --git 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department._.gql
 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department._.gql
new file mode 100644
index 0000000000..fc14f7ac4a
--- /dev/null
+++ 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department._.gql
@@ -0,0 +1,18 @@
+{
+  university_dept_Staff {
+    createStaffMember {
+      invokeNonIdempotent(name: "Dr. Georgina McGovern", department: { id: 
"$departmentId"}) {
+        name {
+          get
+        }
+        department {
+          get {
+            name {
+              get
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department.approved.json
 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department.approved.json
new file mode 100644
index 0000000000..1b1ab53dad
--- /dev/null
+++ 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.create_staff_member_with_department.approved.json
@@ -0,0 +1,20 @@
+{
+  "data" : {
+    "university_dept_Staff" : {
+      "createStaffMember" : {
+        "invokeNonIdempotent" : {
+          "name" : {
+            "get" : "Dr. Georgina McGovern"
+          },
+          "department" : {
+            "get" : {
+              "name" : {
+                "get" : "Classics"
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.java
 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.java
index d454b5b375..1bf7d53fa1 100644
--- 
a/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.java
+++ 
b/incubator/viewers/graphql/test/src/test/java/org/apache/causeway/viewer/graphql/viewer/test/e2e/Domain_IntegTest.java
@@ -27,6 +27,7 @@ import javax.inject.Inject;
 
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.bookmark.BookmarkService;
+import org.apache.causeway.commons.internal.collections._Maps;
 import org.apache.causeway.viewer.graphql.viewer.test.domain.StaffMember;
 import 
org.apache.causeway.viewer.graphql.viewer.test.domain.StaffMemberRepository;
 
@@ -184,6 +185,26 @@ public class Domain_IntegTest extends 
CausewayViewerGraphqlTestModuleIntegTestAb
         Approvals.verify(submit(), jsonOptions());
     }
 
+    @Test
+    @UseReporter(DiffReporter.class)
+    void create_staff_member_with_department() throws Exception {
+
+        final Bookmark bookmark =
+                transactionService.callTransactional(
+                        Propagation.REQUIRED,
+                        () -> {
+                            Department department = 
departmentRepository.findByName("Classics");
+                            return 
bookmarkService.bookmarkFor(department).orElseThrow();
+                        }
+                ).valueAsNonNullElseFail();
+
+        val response = submit(_Maps.unmodifiable("$departmentId", 
bookmark.getIdentifier()));
+
+        // then payload
+        Approvals.verify(response, jsonOptions());
+
+    }
+
     @Test
     @UseReporter(DiffReporter.class)
     void create_department() throws Exception {

Reply via email to