From a411d5da81721794cdf478ac06584e23ac8eeba9 Mon Sep 17 00:00:00 2001
From: PK Jacob <pkjacob@ebsco.com>
Date: Fri, 22 Nov 2024 13:01:10 -0500
Subject: [PATCH] MODLD-602: Updated TitleFieldRequest to avoid oneOf at the
 top level

---
 .../json/ObjectMapperConfig.java              |  4 +-
 .../title/TitleFieldRequestDeserializer.java  | 12 +--
 .../dto/monograph/TopResourceMapperUnit.java  |  4 +-
 .../dto/PrimaryTitleDtoValidator.java         |  7 +-
 .../resource/request/InstanceRequest.json     | 15 +---
 .../schema/resource/request/WorkRequest.json  | 15 +---
 .../request/title/TitleFieldRequest.json      | 86 +++++++++++--------
 .../dto/PrimaryTitleDtoValidatorTest.java     | 10 +--
 8 files changed, 78 insertions(+), 75 deletions(-)

diff --git a/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java b/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java
index f5a75c5f..42203507 100644
--- a/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java
+++ b/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java
@@ -14,7 +14,7 @@
 import org.folio.linked.data.domain.dto.MarcRecord;
 import org.folio.linked.data.domain.dto.ResourceRequestField;
 import org.folio.linked.data.domain.dto.SourceRecordDomainEvent;
-import org.folio.linked.data.domain.dto.TitleFieldRequest;
+import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner;
 import org.folio.linked.data.exception.RequestProcessingExceptionBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -38,7 +38,7 @@ public ObjectMapper objectMapper(RequestProcessingExceptionBuilder exceptionBuil
   private Module monographModule(ObjectMapper objectMapper, RequestProcessingExceptionBuilder exceptionBuilder) {
     return new SimpleModule()
       .addDeserializer(ResourceRequestField.class, new ResourceRequestFieldDeserializer(exceptionBuilder))
-      .addDeserializer(TitleFieldRequest.class, new TitleFieldRequestDeserializer(exceptionBuilder))
+      .addDeserializer(TitleFieldRequestTitleInner.class, new TitleFieldRequestDeserializer(exceptionBuilder))
       .addDeserializer(InstanceRequestAllOfMap.class, new InstanceRequestAllOfMapDeserializer(exceptionBuilder))
       .addDeserializer(SourceRecordDomainEvent.class, new SourceRecordDomainEventDeserializer(objectMapper));
   }
diff --git a/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java b/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java
index d1ccd735..f6e94126 100644
--- a/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java
+++ b/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java
@@ -11,26 +11,26 @@
 import java.util.Map;
 import org.folio.linked.data.domain.dto.ParallelTitleField;
 import org.folio.linked.data.domain.dto.PrimaryTitleField;
-import org.folio.linked.data.domain.dto.TitleFieldRequest;
+import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner;
 import org.folio.linked.data.domain.dto.VariantTitleField;
 import org.folio.linked.data.exception.RequestProcessingExceptionBuilder;
 import org.folio.linked.data.util.DtoDeserializer;
 
-public class TitleFieldRequestDeserializer extends JsonDeserializer<TitleFieldRequest> {
+public class TitleFieldRequestDeserializer extends JsonDeserializer<TitleFieldRequestTitleInner> {
 
-  private static final Map<String, Class<? extends TitleFieldRequest>> IDENDTITY_MAP = Map.of(
+  private static final Map<String, Class<? extends TitleFieldRequestTitleInner>> IDENDTITY_MAP = Map.of(
     TITLE.getUri(), PrimaryTitleField.class,
     PARALLEL_TITLE.getUri(), ParallelTitleField.class,
     VARIANT_TITLE.getUri(), VariantTitleField.class
   );
-  private final DtoDeserializer<TitleFieldRequest> dtoDeserializer;
+  private final DtoDeserializer<TitleFieldRequestTitleInner> dtoDeserializer;
 
   public TitleFieldRequestDeserializer(RequestProcessingExceptionBuilder exceptionBuilder) {
-    dtoDeserializer = new DtoDeserializer<>(TitleFieldRequest.class, IDENDTITY_MAP, exceptionBuilder);
+    dtoDeserializer = new DtoDeserializer<>(TitleFieldRequestTitleInner.class, IDENDTITY_MAP, exceptionBuilder);
   }
 
   @Override
-  public TitleFieldRequest deserialize(JsonParser jp, DeserializationContext dc) throws IOException {
+  public TitleFieldRequestTitleInner deserialize(JsonParser jp, DeserializationContext dc) throws IOException {
     return dtoDeserializer.deserialize(jp);
   }
 
diff --git a/src/main/java/org/folio/linked/data/mapper/dto/monograph/TopResourceMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/monograph/TopResourceMapperUnit.java
index 578fdd11..67d63d82 100644
--- a/src/main/java/org/folio/linked/data/mapper/dto/monograph/TopResourceMapperUnit.java
+++ b/src/main/java/org/folio/linked/data/mapper/dto/monograph/TopResourceMapperUnit.java
@@ -8,7 +8,7 @@
 import org.folio.linked.data.domain.dto.PrimaryTitleField;
 import org.folio.linked.data.domain.dto.ResourceRequestDto;
 import org.folio.linked.data.domain.dto.ResourceResponseDto;
-import org.folio.linked.data.domain.dto.TitleFieldRequest;
+import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner;
 import org.folio.linked.data.mapper.dto.common.SingleResourceMapperUnit;
 
 public abstract class TopResourceMapperUnit implements SingleResourceMapperUnit {
@@ -23,7 +23,7 @@ public Set<Class<?>> supportedParents() {
     return SUPPORTED_PARENTS;
   }
 
-  protected List<String> getPrimaryMainTitles(List<TitleFieldRequest> titles) {
+  protected List<String> getPrimaryMainTitles(List<TitleFieldRequestTitleInner> titles) {
     if (isNull(titles)) {
       return new ArrayList<>();
     }
diff --git a/src/main/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidator.java b/src/main/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidator.java
index ba83e830..bae3e6ab 100644
--- a/src/main/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidator.java
+++ b/src/main/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidator.java
@@ -8,13 +8,14 @@
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.folio.linked.data.domain.dto.PrimaryTitleField;
-import org.folio.linked.data.domain.dto.TitleFieldRequest;
+import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner;
 import org.folio.linked.data.validation.PrimaryTitleConstraint;
 
-public class PrimaryTitleDtoValidator implements ConstraintValidator<PrimaryTitleConstraint, List<TitleFieldRequest>> {
+public class PrimaryTitleDtoValidator implements
+  ConstraintValidator<PrimaryTitleConstraint, List<TitleFieldRequestTitleInner>> {
 
   @Override
-  public boolean isValid(List<TitleFieldRequest> titleFields, ConstraintValidatorContext context) {
+  public boolean isValid(List<TitleFieldRequestTitleInner> titleFields, ConstraintValidatorContext context) {
     if (isNull(titleFields)) {
       return true;
     }
diff --git a/src/main/resources/swagger.api/schema/resource/request/InstanceRequest.json b/src/main/resources/swagger.api/schema/resource/request/InstanceRequest.json
index 4c699ae0..befc9bae 100644
--- a/src/main/resources/swagger.api/schema/resource/request/InstanceRequest.json
+++ b/src/main/resources/swagger.api/schema/resource/request/InstanceRequest.json
@@ -2,18 +2,12 @@
   "$schema": "http://json-schema.org/draft-04/schema#",
   "description": "Instance request DTO",
   "allOf": [
+    {
+      "$ref": "title/TitleFieldRequest.json"
+    },
     {
       "type": "object",
       "properties": {
-        "title": {
-          "type": "array",
-          "items": {
-            "type": "object",
-            "$ref": "title/TitleFieldRequest.json"
-          },
-          "x-json-property": "http://bibfra.me/vocab/marc/title",
-          "x-field-extra-annotation": "@org.folio.linked.data.validation.PrimaryTitleConstraint"
-        },
         "production": {
           "type": "array",
           "items": {
@@ -208,8 +202,7 @@
             "$ref": "../common/IdField.json"
           }
         }
-      },
-      "required": ["title"]
+      }
     }
   ]
 }
diff --git a/src/main/resources/swagger.api/schema/resource/request/WorkRequest.json b/src/main/resources/swagger.api/schema/resource/request/WorkRequest.json
index c5842bb6..09abfb15 100644
--- a/src/main/resources/swagger.api/schema/resource/request/WorkRequest.json
+++ b/src/main/resources/swagger.api/schema/resource/request/WorkRequest.json
@@ -2,18 +2,12 @@
   "$schema": "http://json-schema.org/draft-04/schema#",
   "description": "Work request DTO",
   "allOf": [
+    {
+      "$ref": "title/TitleFieldRequest.json"
+    },
     {
       "type": "object",
       "properties": {
-        "title": {
-          "type": "array",
-          "items": {
-            "type": "object",
-            "$ref": "title/TitleFieldRequest.json"
-          },
-          "x-json-property": "http://bibfra.me/vocab/marc/title",
-          "x-field-extra-annotation": "@org.folio.linked.data.validation.PrimaryTitleConstraint"
-        },
         "targetAudience": {
           "type": "array",
           "items": {
@@ -149,8 +143,7 @@
           },
           "x-json-property": "http://bibfra.me/vocab/scholar/dissertation"
         }
-      },
-      "required": ["title"]
+      }
     }
   ]
 }
diff --git a/src/main/resources/swagger.api/schema/resource/request/title/TitleFieldRequest.json b/src/main/resources/swagger.api/schema/resource/request/title/TitleFieldRequest.json
index 3a8c29ab..5b44ddd7 100644
--- a/src/main/resources/swagger.api/schema/resource/request/title/TitleFieldRequest.json
+++ b/src/main/resources/swagger.api/schema/resource/request/title/TitleFieldRequest.json
@@ -1,38 +1,54 @@
 {
-  "description": "A title of a resource.",
-  "oneOf": [
-    {
-      "type": "object",
-      "title": "PrimaryTitleField",
-      "properties": {
-        "PrimaryTitle": {
-          "type": "object",
-          "$ref": "schema/resource/common/title/PrimaryTitle.json",
-          "x-json-property": "http://bibfra.me/vocab/marc/Title"
-        }
-      }
-    },
-    {
-      "type": "object",
-      "title": "VariantTitleField",
-      "properties": {
-        "VariantTitle": {
-          "type": "object",
-          "$ref": "schema/resource/common/title/VariantTitle.json",
-          "x-json-property": "http://bibfra.me/vocab/marc/VariantTitle"
-        }
-      }
-    },
-    {
-      "type": "object",
-      "title": "ParallelTitleField",
-      "properties": {
-        "ParallelTitle": {
-          "type": "object",
-          "$ref": "schema/resource/common/title/ParallelTitle.json",
-          "x-json-property": "http://bibfra.me/vocab/marc/ParallelTitle"
-        }
-      }
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "description": "Title of the Work or Instance resource",
+  "properties": {
+    "title": {
+      "type": "array",
+      "description": "The title of the work or instance",
+      "items": {
+        "type": "object",
+        "oneOf": [
+          {
+            "type": "object",
+            "title": "PrimaryTitleField",
+            "properties": {
+              "PrimaryTitle": {
+                "type": "object",
+                "$ref": "../../common/title/PrimaryTitle.json",
+                "x-json-property": "http://bibfra.me/vocab/marc/Title",
+                "description": "The primary title of the work or instance"
+              }
+            }
+          },
+          {
+            "type": "object",
+            "title": "VariantTitleField",
+            "properties": {
+              "VariantTitle": {
+                "type": "object",
+                "$ref": "../../common/title/VariantTitle.json",
+                "x-json-property": "http://bibfra.me/vocab/marc/VariantTitle",
+                "description": "The variant title of the work or instance"
+              }
+            }
+          },
+          {
+            "type": "object",
+            "title": "ParallelTitleField",
+            "properties": {
+              "ParallelTitle": {
+                "type": "object",
+                "$ref": "../../common/title/ParallelTitle.json",
+                "x-json-property": "http://bibfra.me/vocab/marc/ParallelTitle",
+                "description": "The parallel title of the work or instance"
+              }
+            }
+          }
+        ]
+      },
+      "x-json-property": "http://bibfra.me/vocab/marc/title",
+      "x-field-extra-annotation": "@org.folio.linked.data.validation.PrimaryTitleConstraint"
     }
-  ]
+  },
+  "required": ["title"]
 }
diff --git a/src/test/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidatorTest.java b/src/test/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidatorTest.java
index f629da1a..7d1eb7f3 100644
--- a/src/test/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidatorTest.java
+++ b/src/test/java/org/folio/linked/data/validation/dto/PrimaryTitleDtoValidatorTest.java
@@ -8,7 +8,7 @@
 import org.folio.linked.data.domain.dto.ParallelTitleField;
 import org.folio.linked.data.domain.dto.PrimaryTitle;
 import org.folio.linked.data.domain.dto.PrimaryTitleField;
-import org.folio.linked.data.domain.dto.TitleFieldRequest;
+import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner;
 import org.folio.spring.testing.type.UnitTest;
 import org.junit.jupiter.api.Test;
 
@@ -29,7 +29,7 @@ void shouldReturnTrue_ifGivenTitleFieldRequestListIsNull() {
   @Test
   void shouldReturnFalse_ifGivenTitleFieldRequestListIsEmpty() {
     // given
-    var titleFields = new ArrayList<TitleFieldRequest>();
+    var titleFields = new ArrayList<TitleFieldRequestTitleInner>();
 
     // when
     boolean result = validator.isValid(titleFields, null);
@@ -41,7 +41,7 @@ void shouldReturnFalse_ifGivenTitleFieldRequestListIsEmpty() {
   @Test
   void shouldReturnFalse_ifGivenTitleFieldRequestListContainsNoPrimaryTitle() {
     // given
-    var titleFields = new ArrayList<TitleFieldRequest>();
+    var titleFields = new ArrayList<TitleFieldRequestTitleInner>();
     titleFields.add(new ParallelTitleField().parallelTitle(
       new ParallelTitle().mainTitle(List.of("parallel main title"))
     ));
@@ -56,7 +56,7 @@ void shouldReturnFalse_ifGivenTitleFieldRequestListContainsNoPrimaryTitle() {
   @Test
   void shouldReturnFalse_ifGivenTitleFieldRequestListContainsPrimaryTitleWithNoMainTitle() {
     // given
-    var titleFields = new ArrayList<TitleFieldRequest>();
+    var titleFields = new ArrayList<TitleFieldRequestTitleInner>();
     titleFields.add(new ParallelTitleField().parallelTitle(
       new ParallelTitle().mainTitle(List.of("parallel main title"))
     ));
@@ -74,7 +74,7 @@ void shouldReturnFalse_ifGivenTitleFieldRequestListContainsPrimaryTitleWithNoMai
   @Test
   void shouldReturnTrue_ifGivenTitleFieldListContainsPrimaryTitleWithMainTitle() {
     // given
-    var titleFields = new ArrayList<TitleFieldRequest>();
+    var titleFields = new ArrayList<TitleFieldRequestTitleInner>();
     titleFields.add(new ParallelTitleField().parallelTitle(
       new ParallelTitle().mainTitle(List.of("parallel main title"))
     ));