From e450f3f6d64e585ba641039f3aba82b287e0da34 Mon Sep 17 00:00:00 2001
From: Saba-Zedginidze-EPAM
<148070844+Saba-Zedginidze-EPAM@users.noreply.github.com>
Date: Thu, 29 Aug 2024 18:41:29 +0400
Subject: [PATCH 1/7] [MODINV-1070] Modify TenantItems response schema (#759)
* [MODINV-1070] Modify TenantItems response schema
* [MODINV-1070] Fix failing test
* [MODINV-1070] Remove unused import
* [MODINV-1070] Remove unused import
---
pom.xml | 1 +
ramls/tenantItemResponse.json | 20 ++++++++++++
.../inventory/resources/TenantItems.java | 32 +++++++++----------
.../java/api/items/TenantItemApiTests.java | 10 +++---
4 files changed, 42 insertions(+), 21 deletions(-)
create mode 100644 ramls/tenantItemResponse.json
diff --git a/pom.xml b/pom.xml
index 49b91ca8a..705f4f467 100644
--- a/pom.xml
+++ b/pom.xml
@@ -451,6 +451,7 @@
${basedir}/ramls/instance-ingress-event.json
${basedir}/ramls/tenantItemPair.json
${basedir}/ramls/tenantItemPairCollection.json
+ ${basedir}/ramls/tenantItemResponse.json
org.folio
true
diff --git a/ramls/tenantItemResponse.json b/ramls/tenantItemResponse.json
new file mode 100644
index 000000000..8bdf521e3
--- /dev/null
+++ b/ramls/tenantItemResponse.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "Collection of pairs of item and tenant IDs",
+ "type": "object",
+ "properties": {
+ "tenantItems": {
+ "type": "array",
+ "description": "Items with corresponding tenantIds",
+ "items": {
+ "type": "object",
+ "additionalProperties": true
+ }
+ },
+ "totalRecords": {
+ "type": "integer"
+ }
+ },
+ "additionalProperties": false,
+ "required": ["item", "totalRecords"]
+}
diff --git a/src/main/java/org/folio/inventory/resources/TenantItems.java b/src/main/java/org/folio/inventory/resources/TenantItems.java
index c6079b6f4..c02ac570d 100644
--- a/src/main/java/org/folio/inventory/resources/TenantItems.java
+++ b/src/main/java/org/folio/inventory/resources/TenantItems.java
@@ -17,8 +17,10 @@
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.folio.TenantItem;
import org.folio.TenantItemPair;
import org.folio.TenantItemPairCollection;
+import org.folio.TenantItemResponse;
import org.folio.inventory.common.WebContext;
import org.folio.inventory.storage.external.CollectionResourceClient;
import org.folio.inventory.support.JsonArrayHelper;
@@ -28,7 +30,6 @@
import org.folio.inventory.support.http.server.ServerErrorResponse;
import io.vertx.core.http.HttpClient;
-import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
@@ -45,6 +46,7 @@ public class TenantItems {
private static final String TENANT_ITEMS_PATH = "/inventory/tenant-items";
public static final String ITEMS_FIELD = "items";
+ public static final String ITEM_FIELD = "item";
public static final String TOTAL_RECORDS_FIELD = "totalRecords";
public static final String TENANT_ID_FIELD = "tenantId";
@@ -77,11 +79,11 @@ private void getItemsFromTenants(RoutingContext routingContext) {
.map(CompletableFuture::join)
.flatMap(List::stream)
.toList())
- .thenApply(this::constructResponse)
- .thenAccept(jsonObject -> JsonResponse.success(routingContext.response(), jsonObject));
+ .thenApply(items -> new TenantItemResponse().withTenantItems(items).withTotalRecords(items.size()))
+ .thenAccept(response -> JsonResponse.success(routingContext.response(), JsonObject.mapFrom(response)));
}
- private CompletableFuture> getItemsWithTenantId(String tenantId, List itemIds, RoutingContext routingContext) {
+ private CompletableFuture> getItemsWithTenantId(String tenantId, List itemIds, RoutingContext routingContext) {
LOG.info("getItemsWithTenantId:: Fetching items - {} from tenant - {}", itemIds, tenantId);
var context = new WebContext(routingContext);
CollectionResourceClient itemsStorageClient;
@@ -98,24 +100,20 @@ private CompletableFuture> getItemsWithTenantId(String tenantId
var itemsFetched = new CompletableFuture();
itemsStorageClient.getAll(getByIdsQuery, itemsFetched::complete);
- return itemsFetched.thenApplyAsync(response ->
- getItemsWithTenantId(tenantId, response));
+ return itemsFetched
+ .thenApply(this::getItems)
+ .thenApply(items -> items.stream()
+ .map(item -> new TenantItem()
+ .withAdditionalProperty(ITEM_FIELD, item)
+ .withAdditionalProperty(TENANT_ID_FIELD, tenantId))
+ .toList());
}
- private List getItemsWithTenantId(String tenantId, Response response) {
+ private List getItems(Response response) {
if (response.getStatusCode() != HttpStatus.SC_OK || !response.hasBody()) {
return List.of();
}
- return JsonArrayHelper.toList(response.getJson(), ITEMS_FIELD).stream()
- .map(item -> item.put(TENANT_ID_FIELD, tenantId))
- .toList();
- }
-
- private JsonObject constructResponse(List items) {
- return JsonObject.of(
- ITEMS_FIELD, JsonArray.of(items.toArray()),
- TOTAL_RECORDS_FIELD, items.size()
- );
+ return JsonArrayHelper.toList(response.getJson(), ITEMS_FIELD);
}
private CollectionResourceClient createItemsStorageClient(OkapiHttpClient client, WebContext context) throws MalformedURLException {
diff --git a/src/test/java/api/items/TenantItemApiTests.java b/src/test/java/api/items/TenantItemApiTests.java
index 4b0095bcd..5471bda7a 100644
--- a/src/test/java/api/items/TenantItemApiTests.java
+++ b/src/test/java/api/items/TenantItemApiTests.java
@@ -6,7 +6,7 @@
import static api.ApiTestSuite.getCanCirculateLoanType;
import static api.support.InstanceSamples.smallAngryPlanet;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.folio.inventory.resources.TenantItems.ITEMS_FIELD;
+import static org.folio.inventory.resources.TenantItems.ITEM_FIELD;
import static org.folio.inventory.resources.TenantItems.TENANT_ID_FIELD;
import static org.folio.inventory.resources.TenantItems.TOTAL_RECORDS_FIELD;
import static org.folio.inventory.support.ItemUtil.ID;
@@ -38,6 +38,8 @@
@RunWith(JUnitParamsRunner.class)
public class TenantItemApiTests extends ApiTests {
+ private static final String TENANT_ITEMS_FIELD = "tenantItems";
+
@Test
public void testTenantItemsGetFromDifferentTenants() throws MalformedURLException,
ExecutionException, InterruptedException, TimeoutException {
@@ -59,8 +61,8 @@ public void testTenantItemsGetFromDifferentTenants() throws MalformedURLExceptio
.toCompletableFuture().get(5, TimeUnit.SECONDS);
assertThat(response.getStatusCode()).isEqualTo(200);
- consortiumItem.put(TENANT_ID_FIELD, CONSORTIA_TENANT_ID);
- collegeItem.put(TENANT_ID_FIELD, COLLEGE_TENANT_ID);
+ consortiumItem = JsonObject.of(ITEM_FIELD, consortiumItem, TENANT_ID_FIELD, CONSORTIA_TENANT_ID);
+ collegeItem = JsonObject.of(ITEM_FIELD, collegeItem, TENANT_ID_FIELD, COLLEGE_TENANT_ID);
var items = extractItems(response, 2);
assertThat(items).contains(consortiumItem, collegeItem);
}
@@ -91,7 +93,7 @@ private UUID createInstanceHoldingItem(ResourceClient itemsStorageClient, Resour
private List extractItems(Response itemsResponse, int expected) {
var itemsCollection = itemsResponse.getJson();
- var items = JsonArrayHelper.toList(itemsCollection.getJsonArray(ITEMS_FIELD));
+ var items = JsonArrayHelper.toList(itemsCollection.getJsonArray(TENANT_ITEMS_FIELD));
assertThat(items).hasSize(expected);
assertThat(itemsCollection.getInteger(TOTAL_RECORDS_FIELD)).isEqualTo(expected);
return items;
From 8e019f94811b1af87d2e5475d12b9a050d105d0b Mon Sep 17 00:00:00 2001
From: SvitlanaKovalova1
Date: Fri, 30 Aug 2024 13:43:39 +0300
Subject: [PATCH 2/7] feat(instance-date-type-fields): add new date type fields
to Instance schema (#758)
---
NEWS.md | 1 +
descriptors/ModuleDescriptor-template.json | 4 +-
ramls/instance.json | 21 ++++++
.../config/InventoryConfigurationImpl.java | 3 +-
.../inventory/domain/instances/Dates.java | 42 +++++++++++
.../inventory/domain/instances/Instance.java | 20 ++++-
src/test/java/api/InstancesApiExamples.java | 24 +++++-
.../inventory/domain/instances/DatesTest.java | 74 +++++++++++++++++++
8 files changed, 182 insertions(+), 7 deletions(-)
create mode 100644 src/main/java/org/folio/inventory/domain/instances/Dates.java
create mode 100644 src/test/java/org/folio/inventory/domain/instances/DatesTest.java
diff --git a/NEWS.md b/NEWS.md
index 27a7f4fb7..bf365f805 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -20,6 +20,7 @@
* Disallow updating holdings ownership with related boundwith [MODINV-1051](https://folio-org.atlassian.net/browse/MODINV-1051)
* Disallow updating ownership of boundwith item [MODINV-1052](https://folio-org.atlassian.net/browse/MODINV-1052)
* InstanceIngress update events consumption [MODINV-1008](https://folio-org.atlassian.net/browse/MODINV-1008)
+* Apply new date type fields to instance schema [MODINV-1067](https://folio-org.atlassian.net/browse/MODINV-1067)
## 20.2.0 2023-03-20
* Inventory cannot process Holdings with virtual fields ([MODINV-941](https://issues.folio.org/browse/MODINV-941))
diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json
index 5bc3ee80b..cea866adc 100644
--- a/descriptors/ModuleDescriptor-template.json
+++ b/descriptors/ModuleDescriptor-template.json
@@ -4,7 +4,7 @@
"provides": [
{
"id": "inventory",
- "version": "13.1",
+ "version": "13.2",
"handlers": [
{
"methods": ["GET"],
@@ -602,7 +602,7 @@
},
{
"id": "instance-storage",
- "version": "10.0"
+ "version": "10.2"
},
{
"id": "instance-storage-batch",
diff --git a/ramls/instance.json b/ramls/instance.json
index d27ab0f00..ee7703fee 100644
--- a/ramls/instance.json
+++ b/ramls/instance.json
@@ -335,6 +335,27 @@
]
}
},
+ "dates": {
+ "type": "object",
+ "description": "Instance Dates",
+ "properties": {
+ "dateTypeId": {
+ "type": "string",
+ "description": "Date type ID",
+ "$ref": "uuid.json"
+ },
+ "date1": {
+ "type": "string",
+ "description": "Date 1",
+ "maxLength": 4
+ },
+ "date2": {
+ "type": "string",
+ "description": "Date 2",
+ "maxLength": 4
+ }
+ }
+ },
"instanceTypeId": {
"type": "string",
"description": "The unique term for the resource type whether it's from the RDA content term list of locally defined"
diff --git a/src/main/java/org/folio/inventory/config/InventoryConfigurationImpl.java b/src/main/java/org/folio/inventory/config/InventoryConfigurationImpl.java
index 6fbd93eb0..b750fb5ff 100644
--- a/src/main/java/org/folio/inventory/config/InventoryConfigurationImpl.java
+++ b/src/main/java/org/folio/inventory/config/InventoryConfigurationImpl.java
@@ -32,7 +32,8 @@ public class InventoryConfigurationImpl implements InventoryConfiguration {
Instance.INSTANCE_TYPE_ID_KEY,
Instance.MODE_OF_ISSUANCE_ID_KEY,
Instance.PRECEDING_TITLES_KEY,
- Instance.SUCCEEDING_TITLES_KEY
+ Instance.SUCCEEDING_TITLES_KEY,
+ Instance.DATES_KEY
);
private static final Set HOLDINGS_BLOCKED_FIELDS = Sets.newHashSet(
diff --git a/src/main/java/org/folio/inventory/domain/instances/Dates.java b/src/main/java/org/folio/inventory/domain/instances/Dates.java
new file mode 100644
index 000000000..58ee18458
--- /dev/null
+++ b/src/main/java/org/folio/inventory/domain/instances/Dates.java
@@ -0,0 +1,42 @@
+package org.folio.inventory.domain.instances;
+
+import io.vertx.core.json.JsonObject;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import static org.apache.commons.lang3.ObjectUtils.anyNotNull;
+import static org.folio.inventory.support.JsonHelper.includeIfPresent;
+
+@Getter
+@AllArgsConstructor
+public class Dates {
+ // JSON property names
+ public static final String DATE_TYPE_ID_KEY = "dateTypeId";
+ public static final String DATE1_KEY = "date1";
+ public static final String DATE2_KEY = "date2";
+
+ public final String dateTypeId;
+ public final String date1;
+ public final String date2;
+
+ public static JsonObject datesToJson(Dates dates) {
+ if (dates == null || (dates.getDate1() == null && dates.getDate2() == null && dates.getDateTypeId() == null)) {
+ return null;
+ }
+ var json = new JsonObject();
+ includeIfPresent(json, DATE_TYPE_ID_KEY, dates.getDateTypeId());
+ includeIfPresent(json, DATE1_KEY, dates.getDate1());
+ includeIfPresent(json, DATE2_KEY, dates.getDate2());
+ return json;
+ }
+
+ public static Dates datesFromJson(JsonObject datesJson) {
+ if (datesJson == null) {
+ return null;
+ }
+ var dateTypeId = datesJson.getString(DATE_TYPE_ID_KEY);
+ var date1 = datesJson.getString(DATE1_KEY);
+ var date2 = datesJson.getString(DATE2_KEY);
+ return anyNotNull(dateTypeId, date1, date2) ? new Dates(dateTypeId, date1, date2) : null;
+ }
+}
diff --git a/src/main/java/org/folio/inventory/domain/instances/Instance.java b/src/main/java/org/folio/inventory/domain/instances/Instance.java
index bd92b3508..3efeba9df 100644
--- a/src/main/java/org/folio/inventory/domain/instances/Instance.java
+++ b/src/main/java/org/folio/inventory/domain/instances/Instance.java
@@ -1,5 +1,7 @@
package org.folio.inventory.domain.instances;
+import static org.folio.inventory.domain.instances.Dates.datesFromJson;
+import static org.folio.inventory.domain.instances.Dates.datesToJson;
import static org.folio.inventory.domain.instances.PublicationPeriod.publicationPeriodFromJson;
import static org.folio.inventory.domain.instances.PublicationPeriod.publicationPeriodToJson;
import static org.folio.inventory.support.JsonArrayHelper.toListOfStrings;
@@ -73,6 +75,7 @@ public class Instance {
public static final String TAG_LIST_KEY = "tagList";
public static final String NATURE_OF_CONTENT_TERM_IDS_KEY = "natureOfContentTermIds";
public static final String PUBLICATION_PERIOD_KEY = "publicationPeriod";
+ public static final String DATES_KEY = "dates";
private final String id;
@JsonProperty("_version")
@@ -117,6 +120,7 @@ public class Instance {
private List tags;
private List natureOfContentTermIds = new ArrayList<>();
private PublicationPeriod publicationPeriod;
+ private Dates dates;
protected static final String INVENTORY_PATH = "/inventory";
protected static final String INSTANCES_PATH = INVENTORY_PATH + "/instances";
@@ -188,7 +192,8 @@ public static Instance fromJson(JsonObject instanceJson) {
.setStatusUpdatedDate(instanceJson.getString(STATUS_UPDATED_DATE_KEY))
.setTags(getTags(instanceJson))
.setNatureOfContentTermIds(toListOfStrings(instanceJson.getJsonArray(NATURE_OF_CONTENT_TERM_IDS_KEY)))
- .setPublicationPeriod(publicationPeriodFromJson(instanceJson.getJsonObject(PUBLICATION_PERIOD_KEY)));
+ .setPublicationPeriod(publicationPeriodFromJson(instanceJson.getJsonObject(PUBLICATION_PERIOD_KEY)))
+ .setDates(datesFromJson(instanceJson.getJsonObject(DATES_KEY)));
}
/**
@@ -237,6 +242,7 @@ public JsonObject getJsonForStorage() {
json.put(TAGS_KEY, new JsonObject().put(TAG_LIST_KEY, new JsonArray(getTags() == null ? Collections.emptyList() : getTags())));
json.put(NATURE_OF_CONTENT_TERM_IDS_KEY, natureOfContentTermIds);
putIfNotNull(json, PUBLICATION_PERIOD_KEY, publicationPeriodToJson(publicationPeriod));
+ putIfNotNull(json, DATES_KEY, datesToJson(dates));
return json;
}
@@ -290,6 +296,7 @@ public JsonObject getJsonForResponse(WebContext context) {
putIfNotNull(json, TAGS_KEY, new JsonObject().put(TAG_LIST_KEY, new JsonArray(getTags())));
putIfNotNull(json, NATURE_OF_CONTENT_TERM_IDS_KEY, getNatureOfContentTermIds());
putIfNotNull(json, PUBLICATION_PERIOD_KEY, publicationPeriodToJson(publicationPeriod));
+ putIfNotNull(json, DATES_KEY, datesToJson(dates));
if (precedingTitles != null) {
JsonArray precedingTitlesJsonArray = new JsonArray();
@@ -461,6 +468,11 @@ public Instance setElectronicAccess (JsonArray array) {
return this;
}
+ public Instance setDates(Dates dates) {
+ this.dates = dates;
+ return this;
+ }
+
public Instance setInstanceFormatIds(List instanceFormatIds) {
this.instanceFormatIds = instanceFormatIds;
return this;
@@ -747,7 +759,8 @@ public Instance copyWithNewId(String newId) {
.setMetadata(metadata)
.setTags(tags)
.setNatureOfContentTermIds(natureOfContentTermIds)
- .setPublicationPeriod(publicationPeriod);
+ .setPublicationPeriod(publicationPeriod)
+ .setDates(dates);
}
public Instance copyInstance() {
@@ -781,7 +794,8 @@ public Instance copyInstance() {
.setMetadata(metadata)
.setTags(tags)
.setNatureOfContentTermIds(natureOfContentTermIds)
- .setPublicationPeriod(publicationPeriod);
+ .setPublicationPeriod(publicationPeriod)
+ .setDates(dates);
}
public Instance addIdentifier(Identifier identifier) {
diff --git a/src/test/java/api/InstancesApiExamples.java b/src/test/java/api/InstancesApiExamples.java
index c33a7bb76..a9c25c8de 100644
--- a/src/test/java/api/InstancesApiExamples.java
+++ b/src/test/java/api/InstancesApiExamples.java
@@ -12,6 +12,11 @@
import static io.vertx.core.http.HttpMethod.PUT;
import static java.util.Arrays.asList;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.folio.inventory.domain.instances.Dates.DATE_TYPE_ID_KEY;
+import static org.folio.inventory.domain.instances.Dates.DATE1_KEY;
+import static org.folio.inventory.domain.instances.Dates.DATE2_KEY;
+import static org.folio.inventory.domain.instances.Dates.datesToJson;
+import static org.folio.inventory.domain.instances.Instance.DATES_KEY;
import static org.folio.inventory.domain.instances.Instance.PRECEDING_TITLES_KEY;
import static org.folio.inventory.domain.instances.Instance.PUBLICATION_PERIOD_KEY;
import static org.folio.inventory.domain.instances.Instance.TAGS_KEY;
@@ -40,6 +45,7 @@
import org.folio.HttpStatus;
import org.folio.inventory.config.InventoryConfiguration;
import org.folio.inventory.config.InventoryConfigurationImpl;
+import org.folio.inventory.domain.instances.Dates;
import org.folio.inventory.domain.instances.PublicationPeriod;
import org.folio.inventory.domain.instances.titles.PrecedingSucceedingTitle;
import org.folio.inventory.support.JsonArrayHelper;
@@ -63,6 +69,9 @@ public class InstancesApiExamples extends ApiTests {
private static final InventoryConfiguration config = new InventoryConfigurationImpl();
private final String tagNameOne = "important";
private final String tagNameTwo = "very important";
+ private final String dateTypeId = "0750f52b-3bfc-458d-9307-e9afc8bcdffa";
+ private final String date1 = "2014";
+ private final String date2 = "2016";
@After
public void disableFailureEmulation() throws Exception {
@@ -93,6 +102,7 @@ public void canCreateInstanceWithoutAnIDAndHRID()
.put("instanceTypeId", ApiTestSuite.getTextInstanceType())
.put(TAGS_KEY, new JsonObject().put(TAG_LIST_KEY, new JsonArray().add(tagNameOne)))
.put(PUBLICATION_PERIOD_KEY, publicationPeriodToJson(new PublicationPeriod(1000, 2000)))
+ .put(DATES_KEY, datesToJson(new Dates(dateTypeId, date1, date2)))
.put("natureOfContentTermIds",
new JsonArray(asList(
ApiTestSuite.getAudiobookNatureOfContentTermId(),
@@ -161,6 +171,11 @@ public void canCreateInstanceWithoutAnIDAndHRID()
var publicationPeriod = createdInstance.getJsonObject(PUBLICATION_PERIOD_KEY);
assertThat(publicationPeriod.getInteger("start"), is(1000));
assertThat(publicationPeriod.getInteger("end"), is(2000));
+
+ var dates = createdInstance.getJsonObject(DATES_KEY);
+ assertThat(dates.getString(DATE_TYPE_ID_KEY), is(dateTypeId));
+ assertThat(dates.getString(DATE1_KEY), is(date1));
+ assertThat(dates.getString(DATE2_KEY), is(date2));
}
@Test
@@ -392,6 +407,7 @@ public void canUpdateAnExistingInstance()
smallAngryPlanet.put("natureOfContentTermIds",
new JsonArray().add(ApiTestSuite.getBibliographyNatureOfContentTermId()));
smallAngryPlanet.put(PUBLICATION_PERIOD_KEY, publicationPeriodToJson(new PublicationPeriod(1000, 2000)));
+ smallAngryPlanet.put(DATES_KEY, datesToJson(new Dates(null, date1, date2)));
JsonObject newInstance = createInstance(smallAngryPlanet);
@@ -399,6 +415,7 @@ public void canUpdateAnExistingInstance()
.put("title", "The Long Way to a Small, Angry Planet")
.put(TAGS_KEY, new JsonObject().put(TAG_LIST_KEY, new JsonArray().add(tagNameTwo)))
.put(PUBLICATION_PERIOD_KEY, publicationPeriodToJson(new PublicationPeriod(2000, 2012)))
+ .put(DATES_KEY, datesToJson(new Dates(dateTypeId, date1, date2)))
.put("natureOfContentTermIds",
new JsonArray().add(ApiTestSuite.getAudiobookNatureOfContentTermId()));
@@ -434,6 +451,11 @@ public void canUpdateAnExistingInstance()
var publicationPeriod = updatedInstance.getJsonObject(PUBLICATION_PERIOD_KEY);
assertThat(publicationPeriod.getInteger("start"), is(2000));
assertThat(publicationPeriod.getInteger("end"), is(2012));
+
+ var dates = updatedInstance.getJsonObject(DATES_KEY);
+ assertThat(dates.getString(DATE_TYPE_ID_KEY), is(dateTypeId));
+ assertThat(dates.getString(DATE1_KEY), is(date1));
+ assertThat(dates.getString(DATE2_KEY), is(date2));
}
@Test
@@ -612,7 +634,7 @@ public void canNotUpdateAnExistingMARCInstanceIfBlockedFieldsAreChangedToNulls()
assertThat(errors.size(), is(1));
assertThat(errors.getJsonObject(0).getString("message"), is(
"Instance is controlled by MARC record, these fields are blocked and can not be updated: " +
- "physicalDescriptions,notes,languages,precedingTitles,identifiers,instanceTypeId,modeOfIssuanceId,subjects," +
+ "physicalDescriptions,notes,languages,precedingTitles,identifiers,instanceTypeId,modeOfIssuanceId,subjects,dates," +
"source,title,indexTitle,publicationFrequency,electronicAccess,publicationRange," +
"classifications,succeedingTitles,editions,hrid,series,instanceFormatIds,publication,contributors," +
"alternativeTitles"));
diff --git a/src/test/java/org/folio/inventory/domain/instances/DatesTest.java b/src/test/java/org/folio/inventory/domain/instances/DatesTest.java
new file mode 100644
index 000000000..770ea1b40
--- /dev/null
+++ b/src/test/java/org/folio/inventory/domain/instances/DatesTest.java
@@ -0,0 +1,74 @@
+package org.folio.inventory.domain.instances;
+
+import io.vertx.core.json.JsonObject;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import junitparams.converters.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.folio.inventory.domain.instances.Dates.datesFromJson;
+import static org.folio.inventory.domain.instances.Dates.datesToJson;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+
+@RunWith(JUnitParamsRunner.class)
+public class DatesTest {
+
+ @Parameters({
+ "1, 1990, 2002",
+ "1, 1990, null",
+ "1, null, 2022",
+ "null, 1990, 2002",
+ "null, 1990, null",
+ })
+ @Test
+ public void shouldCreateDatesFromJson(@Nullable String dateTypeId, @Nullable String date1, @Nullable String date2) {
+ var dates = datesFromJson(datesJson(dateTypeId, date1, date2));
+
+ assertThat(dates.getDateTypeId(), is(dateTypeId));
+ assertThat(dates.getDate1(), is(date1));
+ assertThat(dates.getDate2(), is(date2));
+ }
+
+ @Test
+ public void shouldNotCreateDatesFromJsonWhenJsonIsNull() {
+ assertThat(datesFromJson(null), nullValue());
+ }
+
+ @Test
+ public void shouldNotCreateDatesFromJsonWhenAllFieldsAreNull() {
+ assertThat(datesFromJson(datesJson(null, null, null)), nullValue());
+ }
+
+ @Parameters({
+ "1, 1990, 2002",
+ "1, 1990, null",
+ "1, null, 2022",
+ "null, 1990, 2002",
+ "null, 1990, null",
+ })
+ @Test
+ public void shouldConvertDatesToJson(@Nullable String dateTypeId, @Nullable String date1, @Nullable String date2) {
+ var json = datesToJson(new Dates(dateTypeId, date1, date2));
+
+ assertThat(json.getString("dateTypeId"), is(dateTypeId));
+ assertThat(json.getString("date1"), is(date1));
+ assertThat(json.getString("date2"), is(date2));
+ }
+
+ @Test
+ public void shouldNotConvertDatesToJsonWhenItIsNull() {
+ assertThat(datesToJson(null), nullValue());
+ }
+
+ @Test
+ public void shouldNotConvertDatesToJsonWhenAllFieldsAreNull() {
+ assertThat(datesToJson(new Dates(null, null, null)), nullValue());
+ }
+
+ private JsonObject datesJson(String dateTypeId, String date1, String date2) {
+ return new JsonObject().put("dateTypeId", dateTypeId).put("date1", date1).put("date2", date2);
+ }
+}
From 6a37749c98d060e09f5489fefab243f7f4286c19 Mon Sep 17 00:00:00 2001
From: Javokhir Abdullaev
<101543142+JavokhirAbdullayev@users.noreply.github.com>
Date: Tue, 3 Sep 2024 16:42:45 +0500
Subject: [PATCH 3/7] MODINV-1069 Fix DataImportConsumerVerticleTest in
mod-inventory and Fix NPE in HoldingsItemMatcher (#757)
* Fix DataImportConsumerVerticleTest in mod-inventory and Fix NPE in HoldingsItemMatcher
* Fix DataImportConsumerVerticleTest in mod-inventory and Fix NPE in HoldingsItemMatcher
* small fix
* small fix
---
.../handlers/matching/loaders/HoldingLoader.java | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/matching/loaders/HoldingLoader.java b/src/main/java/org/folio/inventory/dataimport/handlers/matching/loaders/HoldingLoader.java
index d3acb0e5f..44a8364bb 100644
--- a/src/main/java/org/folio/inventory/dataimport/handlers/matching/loaders/HoldingLoader.java
+++ b/src/main/java/org/folio/inventory/dataimport/handlers/matching/loaders/HoldingLoader.java
@@ -4,13 +4,11 @@
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+import io.vertx.core.json.Json;
+import io.vertx.core.json.JsonObject;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
-
-import io.vertx.core.json.Json;
-import io.vertx.core.json.JsonObject;
-
import org.folio.DataImportEventPayload;
import org.folio.HoldingsRecord;
import org.folio.inventory.common.Context;
@@ -26,6 +24,7 @@ public class HoldingLoader extends AbstractLoader {
private static final String HOLDINGS_FIELD = "holdings";
private static final String INSTANCE_ID_FIELD = "instanceId";
private static final String INSTANCES_IDS_KEY = "INSTANCES_IDS";
+ private static final String EMPTY_ARRAY = "[]";
private Storage storage;
private AbstractPreloader preloader;
@@ -59,7 +58,7 @@ protected String addCqlSubMatchCondition(DataImportEventPayload eventPayload) {
cqlSubMatch = getConditionByMultiMatchResult(eventPayload);
} else if (isNotEmpty(eventPayload.getContext().get(INSTANCES_IDS_KEY))) {
cqlSubMatch = getConditionByMultipleMarcBibMatchResult(eventPayload);
- } else if (isNotEmpty(eventPayload.getContext().get(EntityType.HOLDINGS.value()))) {
+ } else if (isNotNullOrEmpty(eventPayload.getContext().get(EntityType.HOLDINGS.value()))) {
JsonObject holdingAsJson = new JsonObject(eventPayload.getContext().get(EntityType.HOLDINGS.value()));
if (holdingAsJson.getJsonObject(HOLDINGS_FIELD) != null) {
holdingAsJson = holdingAsJson.getJsonObject(HOLDINGS_FIELD);
@@ -73,6 +72,12 @@ protected String addCqlSubMatchCondition(DataImportEventPayload eventPayload) {
return cqlSubMatch;
}
+ private static boolean isNotNullOrEmpty(String value) {
+ if (value == null || value.equals(EMPTY_ARRAY))
+ return false;
+ return isNotEmpty(value);
+ }
+
private String getConditionByMultipleMarcBibMatchResult(DataImportEventPayload eventPayload) {
return getConditionByMultipleValues(INSTANCE_ID_FIELD, eventPayload, INSTANCES_IDS_KEY);
}
From 890d389941d3158f0d45b178e755bdb4ad4baa16 Mon Sep 17 00:00:00 2001
From: Pavel Bobylev <131748689+PBobylev@users.noreply.github.com>
Date: Thu, 5 Sep 2024 12:31:23 +0500
Subject: [PATCH 4/7] MODINV-1066: Update mapping for "sourceRecordIdentifier"
property in "instance_ingress" event (#754)
---
.../handler/InstanceIngressEventHandler.java | 9 +++++++--
...reateInstanceIngressEventHandlerUnitTest.java | 16 ++++++++--------
...pdateInstanceIngressEventHandlerUnitTest.java | 15 ++++++++-------
3 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/src/main/java/org/folio/inventory/instanceingress/handler/InstanceIngressEventHandler.java b/src/main/java/org/folio/inventory/instanceingress/handler/InstanceIngressEventHandler.java
index 74bdfc146..18320b5bf 100644
--- a/src/main/java/org/folio/inventory/instanceingress/handler/InstanceIngressEventHandler.java
+++ b/src/main/java/org/folio/inventory/instanceingress/handler/InstanceIngressEventHandler.java
@@ -46,6 +46,7 @@
public interface InstanceIngressEventHandler {
String LINKED_DATA_ID = "linkedDataId";
+ String INSTANCE_ID = "instanceId";
String FAILURE = "Failed to process InstanceIngressEvent with id {}";
CompletableFuture handle(InstanceIngressEvent instanceIngressEvent);
@@ -57,11 +58,15 @@ default boolean eventContainsNoData(InstanceIngressEvent event) {
}
default Optional getInstanceId(InstanceIngressEvent event) {
- return ofNullable(event.getEventPayload().getSourceRecordIdentifier());
+ return ofNullable(event.getEventPayload())
+ .map(InstanceIngressPayload::getAdditionalProperties)
+ .map(ap -> ap.get(INSTANCE_ID))
+ .map(o -> (String) o);
}
default Record constructMarcBibRecord(InstanceIngressPayload eventPayload) {
- var recordId = UUID.randomUUID().toString();
+ var recordId = ofNullable(eventPayload.getSourceRecordIdentifier())
+ .orElseGet(() -> UUID.randomUUID().toString());
var marcBibRecord = new org.folio.rest.jaxrs.model.Record()
.withId(recordId)
.withRecordType(MARC_BIB)
diff --git a/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java b/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java
index 01dbce3ea..701f1350e 100644
--- a/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java
+++ b/src/test/java/org/folio/inventory/instanceingress/handler/CreateInstanceIngressEventHandlerUnitTest.java
@@ -330,14 +330,16 @@ public void shouldReturnFailedFuture_ifItsFailedToCreateMarcRecordInSrs() throws
@Test
public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOException, ExecutionException, InterruptedException {
// given
- var linkedDataIdId = "someLinkedDataIdId";
+ var linkedDataId = "someLinkedDataId";
+ var instanceId = "someInstanceId";
var event = new InstanceIngressEvent()
.withId(UUID.randomUUID().toString())
.withEventPayload(new InstanceIngressPayload()
.withSourceRecordObject(TestUtil.readFileFromPath(BIB_RECORD_PATH))
.withSourceType(LINKED_DATA)
.withSourceRecordIdentifier(UUID.randomUUID().toString())
- .withAdditionalProperty("linkedDataId", linkedDataIdId)
+ .withAdditionalProperty("linkedDataId", linkedDataId)
+ .withAdditionalProperty("instanceId", instanceId)
);
doReturn(succeededFuture(null)).when(idStorageService).store(anyString(), anyString(), anyString());
var mappingRules = new JsonObject(TestUtil.readFileFromPath(MAPPING_RULES_PATH));
@@ -365,18 +367,16 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx
assertThat(future.isDone()).isTrue();
var instance = future.get();
- assertThat(instance.getId()).isEqualTo(event.getEventPayload().getSourceRecordIdentifier());
+ assertThat(instance.getId()).isEqualTo(instanceId);
assertThat(instance.getSource()).isEqualTo("LINKED_DATA");
- assertThat(instance.getIdentifiers().stream().anyMatch(i -> i.value.equals("(ld) " + linkedDataIdId))).isTrue();
+ assertThat(instance.getIdentifiers().stream().anyMatch(i -> i.value.equals("(ld) " + linkedDataId))).isTrue();
var recordCaptor = ArgumentCaptor.forClass(Record.class);
verify(sourceStorageClient).postSourceStorageRecords(recordCaptor.capture());
var recordSentToSRS = recordCaptor.getValue();
- assertThat(recordSentToSRS.getId()).isNotNull();
- assertThat(recordSentToSRS.getId()).isNotEqualTo(event.getEventPayload().getSourceRecordIdentifier());
- assertThat(recordSentToSRS.getId()).doesNotContain(linkedDataIdId);
+ assertThat(recordSentToSRS.getId()).isEqualTo(event.getEventPayload().getSourceRecordIdentifier());
assertThat(recordSentToSRS.getRecordType()).isEqualTo(Record.RecordType.MARC_BIB);
assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_I)).hasValue(instance.getId());
- assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_L)).hasValue(linkedDataIdId);
+ assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_L)).hasValue(linkedDataId);
}
}
diff --git a/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java b/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java
index 51a4c80c7..0c9afb4be 100644
--- a/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java
+++ b/src/test/java/org/folio/inventory/instanceingress/handler/UpdateInstanceIngressEventHandlerUnitTest.java
@@ -490,14 +490,16 @@ public void shouldReturnFailedFuture_ifCreatePrecedingSucceedingTitlesFailed() t
@Test
public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOException, ExecutionException, InterruptedException {
// given
- var linkedDataIdId = "someLinkedDataIdId";
+ var linkedDataId = "someLinkedDataId";
+ var instanceId = "instanceId";
var event = new InstanceIngressEvent()
.withId(UUID.randomUUID().toString())
.withEventPayload(new InstanceIngressPayload()
.withSourceRecordObject(TestUtil.readFileFromPath(BIB_RECORD_PATH))
.withSourceType(LINKED_DATA)
.withSourceRecordIdentifier(UUID.randomUUID().toString())
- .withAdditionalProperty("linkedDataId", linkedDataIdId)
+ .withAdditionalProperty("linkedDataId", linkedDataId)
+ .withAdditionalProperty("instanceId", instanceId)
);
var mappingRules = new JsonObject(TestUtil.readFileFromPath(MAPPING_RULES_PATH));
doReturn(succeededFuture(Optional.of(new MappingMetadataDto()
@@ -537,10 +539,10 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx
assertThat(future.isDone()).isTrue();
var instance = future.get();
- assertThat(instance.getId()).isEqualTo(event.getEventPayload().getSourceRecordIdentifier());
+ assertThat(instance.getId()).isEqualTo(instanceId);
assertThat(instance.getHrid()).isEqualTo(existedInstance.getHrid());
assertThat(instance.getSource()).isEqualTo("LINKED_DATA");
- assertThat(instance.getIdentifiers().stream().anyMatch(i -> i.value.equals("(ld) " + linkedDataIdId))).isTrue();
+ assertThat(instance.getIdentifiers().stream().anyMatch(i -> i.value.equals("(ld) " + linkedDataId))).isTrue();
var recordCaptor = ArgumentCaptor.forClass(Record.class);
verify(sourceStorageClient).putSourceStorageRecordsGenerationById(eq(previousSrsId), recordCaptor.capture());
@@ -548,11 +550,10 @@ public void shouldReturnSucceededFuture_ifProcessFinishedCorrectly() throws IOEx
assertThat(recordSentToSRS.getId()).isNotNull();
assertThat(recordSentToSRS.getId()).isNotEqualTo(previousSrsId);
assertThat(recordSentToSRS.getMatchedId()).isEqualTo(previousSrsId);
- assertThat(recordSentToSRS.getId()).isNotEqualTo(event.getEventPayload().getSourceRecordIdentifier());
- assertThat(recordSentToSRS.getId()).doesNotContain(linkedDataIdId);
+ assertThat(recordSentToSRS.getId()).isEqualTo(event.getEventPayload().getSourceRecordIdentifier());
assertThat(recordSentToSRS.getRecordType()).isEqualTo(Record.RecordType.MARC_BIB);
assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_I)).hasValue(instance.getId());
- assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_L)).hasValue(linkedDataIdId);
+ assertThat(AdditionalFieldsUtil.getValue(recordSentToSRS, TAG_999, SUBFIELD_L)).hasValue(linkedDataId);
}
}
From 271d4e88dc96b4ce80de2469166c2ee0d87a120f Mon Sep 17 00:00:00 2001
From: RomanChernetskyi <111740564+RomanChernetskyi@users.noreply.github.com>
Date: Mon, 9 Sep 2024 14:06:06 +0300
Subject: [PATCH 5/7] [MODINVSTOR-1253] Add user-tenants.collection.get to all
ECS APIs (#763)
---
descriptors/ModuleDescriptor-template.json | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json
index cea866adc..a062e86ac 100644
--- a/descriptors/ModuleDescriptor-template.json
+++ b/descriptors/ModuleDescriptor-template.json
@@ -559,7 +559,8 @@
"inventory-storage.holdings.item.get",
"inventory-storage.holdings.collection.get",
"inventory-storage.instances.item.get",
- "inventory-storage.bound-with-parts.collection.get"
+ "inventory-storage.bound-with-parts.collection.get",
+ "user-tenants.collection.get"
]
},
{
@@ -574,7 +575,8 @@
"inventory-storage.items.item.delete",
"inventory-storage.items.collection.get",
"inventory-storage.instances.item.get",
- "inventory-storage.bound-with-parts.collection.get"
+ "inventory-storage.bound-with-parts.collection.get",
+ "user-tenants.collection.get"
]
}
]
From 41a10ffb4e6c4930d3c1e9f65e1c48914196acfc Mon Sep 17 00:00:00 2001
From: Dmytro Krutii
Date: Mon, 9 Sep 2024 14:37:27 +0300
Subject: [PATCH 6/7] MODINVSTOR-1205 Add subjectTypeId and subjectSourceId to
instance
---
descriptors/ModuleDescriptor-template.json | 4 +--
.../inventory/domain/instances/Subject.java | 27 ++++++++++++++++---
src/test/java/api/InstancesApiExamples.java | 14 +++++++++-
3 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json
index a062e86ac..8ca1eef80 100644
--- a/descriptors/ModuleDescriptor-template.json
+++ b/descriptors/ModuleDescriptor-template.json
@@ -4,7 +4,7 @@
"provides": [
{
"id": "inventory",
- "version": "13.2",
+ "version": "13.3",
"handlers": [
{
"methods": ["GET"],
@@ -604,7 +604,7 @@
},
{
"id": "instance-storage",
- "version": "10.2"
+ "version": "10.3"
},
{
"id": "instance-storage-batch",
diff --git a/src/main/java/org/folio/inventory/domain/instances/Subject.java b/src/main/java/org/folio/inventory/domain/instances/Subject.java
index 27950f639..051c3ca11 100644
--- a/src/main/java/org/folio/inventory/domain/instances/Subject.java
+++ b/src/main/java/org/folio/inventory/domain/instances/Subject.java
@@ -4,17 +4,30 @@
public class Subject extends Authorized {
// JSON property names
- public static final String VALUE_KEY = "value";
+ private static final String VALUE_KEY = "value";
+ private static final String SOURCE_KEY = "sourceId";
+ private static final String TYPE_KEY = "typeId";
private final String value;
- public Subject(String value, String authorityId) {
+ private final String sourceId;
+
+ private final String typeId;
+
+ public Subject(String value, String authorityId, String sourceId, String typeId) {
super(authorityId);
this.value = value;
+ this.sourceId = sourceId;
+ this.typeId = typeId;
}
public Subject(JsonObject json) {
- this(json.getString(VALUE_KEY), json.getString(AUTHORITY_ID_KEY));
+ this(
+ json.getString(VALUE_KEY),
+ json.getString(AUTHORITY_ID_KEY),
+ json.getString(SOURCE_KEY),
+ json.getString(TYPE_KEY)
+ );
}
public String getAuthorityId() {
@@ -24,4 +37,12 @@ public String getAuthorityId() {
public String getValue() {
return value;
}
+
+ public String getSourceId() {
+ return sourceId;
+ }
+
+ public String getTypeId() {
+ return typeId;
+ }
}
diff --git a/src/test/java/api/InstancesApiExamples.java b/src/test/java/api/InstancesApiExamples.java
index a9c25c8de..fd41b36ea 100644
--- a/src/test/java/api/InstancesApiExamples.java
+++ b/src/test/java/api/InstancesApiExamples.java
@@ -47,6 +47,7 @@
import org.folio.inventory.config.InventoryConfigurationImpl;
import org.folio.inventory.domain.instances.Dates;
import org.folio.inventory.domain.instances.PublicationPeriod;
+import org.folio.inventory.domain.instances.Subject;
import org.folio.inventory.domain.instances.titles.PrecedingSucceedingTitle;
import org.folio.inventory.support.JsonArrayHelper;
import org.folio.inventory.support.http.ContentType;
@@ -402,6 +403,8 @@ public void canUpdateAnExistingInstance()
ExecutionException {
UUID id = UUID.randomUUID();
+ final var sourceId = "sourceId";
+ final var typeId = "typeId";
JsonObject smallAngryPlanet = smallAngryPlanet(id);
smallAngryPlanet.put("natureOfContentTermIds",
@@ -417,7 +420,10 @@ public void canUpdateAnExistingInstance()
.put(PUBLICATION_PERIOD_KEY, publicationPeriodToJson(new PublicationPeriod(2000, 2012)))
.put(DATES_KEY, datesToJson(new Dates(dateTypeId, date1, date2)))
.put("natureOfContentTermIds",
- new JsonArray().add(ApiTestSuite.getAudiobookNatureOfContentTermId()));
+ new JsonArray().add(ApiTestSuite.getAudiobookNatureOfContentTermId()))
+ .put("subjects", new JsonArray().add(
+ new Subject(null, null, sourceId, typeId)
+ ));
URL instanceLocation = new URL(String.format("%s/%s", ApiRoot.instances(),
newInstance.getString("id")));
@@ -456,6 +462,12 @@ public void canUpdateAnExistingInstance()
assertThat(dates.getString(DATE_TYPE_ID_KEY), is(dateTypeId));
assertThat(dates.getString(DATE1_KEY), is(date1));
assertThat(dates.getString(DATE2_KEY), is(date2));
+
+ var subjects = updatedInstance.getJsonArray("subjects");
+ var subject = subjects.getJsonObject(0);
+ assertThat(subjects.size(), is(1));
+ assertThat(subject.getString(sourceId), is(sourceId));
+ assertThat(subject.getString(typeId), is(typeId));
}
@Test
From 39ad7d188213a78bce5ab2f2db5bb0d7f0529d8e Mon Sep 17 00:00:00 2001
From: elena-shmygaliova
Date: Thu, 12 Sep 2024 12:22:40 +0300
Subject: [PATCH 7/7] MODDINV-1071: Extended Authority Mapping (#762)
* MODDINV-1071: Extended Authority Mapping
* MODDINV-1071: Extended Authority Mapping
* MODDINV-1071: Extended Authority Mapping
* MODDINV-1071: Extended Authority Mapping
* MODDINV-1071: Extended Authority Mapping
---------
Co-authored-by: ElenaShm
---
NEWS.md | 1 +
README.MD | 12 ++++++++++
.../AbstractAuthorityEventHandler.java | 22 +++++++++++++++++-
.../UpdateAuthorityEventHandlerTest.java | 23 +++++++++++++++++++
4 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/NEWS.md b/NEWS.md
index bf365f805..ebb154b4a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -21,6 +21,7 @@
* Disallow updating ownership of boundwith item [MODINV-1052](https://folio-org.atlassian.net/browse/MODINV-1052)
* InstanceIngress update events consumption [MODINV-1008](https://folio-org.atlassian.net/browse/MODINV-1008)
* Apply new date type fields to instance schema [MODINV-1067](https://folio-org.atlassian.net/browse/MODINV-1067)
+* Extend Authority with Additional fields [MODINV-1071](https://folio-org.atlassian.net/browse/MODINV-1071)
## 20.2.0 2023-03-20
* Inventory cannot process Holdings with virtual fields ([MODINV-941](https://issues.folio.org/browse/MODINV-941))
diff --git a/README.MD b/README.MD
index 71fa0e31b..ca9d74c41 100644
--- a/README.MD
+++ b/README.MD
@@ -129,6 +129,18 @@ After setup, it is good to check logs in all related modules for errors.
* DI_SRS_MARC_BIB_RECORD_MODIFIED_PARTITIONS
Default value for all partitions is 1
+## Properties
+
+`AUTHORITY_EXTENDED` environment variable enables extended mapping for Authority to support advanced references classification in 5xx fields:
+* broader terms (`$wg` tag)
+* narrower terms (`$wh` tag)
+* earlier headings (`$wa` tag)
+* later headings (`$wb` tag)
+
+Default value for `AUTHORITY_EXTENDED` is `false`.
+The mapping itself is implemented in [data-import-processing-core](https://github.com/folio-org/data-import-processing-core).
+
+
# Making Requests
These modules provide HTTP based APIs rather than any UI themselves.
diff --git a/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractAuthorityEventHandler.java b/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractAuthorityEventHandler.java
index 12be75fd7..2f052bf36 100644
--- a/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractAuthorityEventHandler.java
+++ b/src/main/java/org/folio/inventory/dataimport/handlers/actions/AbstractAuthorityEventHandler.java
@@ -21,6 +21,7 @@
import org.apache.logging.log4j.Logger;
import org.folio.ActionProfile;
+import org.folio.ActionProfile.FolioRecord;
import org.folio.Authority;
import org.folio.DataImportEventPayload;
import org.folio.MappingMetadataDto;
@@ -54,10 +55,13 @@ public abstract class AbstractAuthorityEventHandler implements EventHandler {
private static final String RECORD_ID_HEADER = "recordId";
private static final String CHUNK_ID_HEADER = "chunkId";
+ public static final String AUTHORITY_EXTENDED = "AUTHORITY_EXTENDED";
private final Storage storage;
private final MappingMetadataCache mappingMetadataCache;
+ private static boolean isAuthorityExtended = isAuthorityExtendedMode();
+
protected AbstractAuthorityEventHandler(Storage storage, MappingMetadataCache mappingMetadataCache) {
this.storage = storage;
this.mappingMetadataCache = mappingMetadataCache;
@@ -161,7 +165,9 @@ private Future mapAuthority(DataImportEventPayload payload, MappingMe
var mappingParameters = Json.decodeValue(mappingMetadata.getMappingParams(), MappingParameters.class);
var parsedRecord = new JsonObject((String) new JsonObject(payload.getContext().get(sourceRecordType().value()))
.mapTo(Record.class).getParsedRecord().getContent());
- RecordMapper recordMapper = RecordMapperBuilder.buildMapper(sourceRecordType().value());
+ RecordMapper recordMapper = isAuthorityExtended
+ ? RecordMapperBuilder.buildMapper(FolioRecord.MARC_AUTHORITY_EXTENDED.value())
+ : RecordMapperBuilder.buildMapper(sourceRecordType().value());
var authority = recordMapper.mapRecord(parsedRecord, mappingParameters, mappingRules);
authority.setSource(Authority.Source.MARC);
return Future.succeededFuture(authority);
@@ -215,4 +221,18 @@ private String constructMetaInfoMsg(DataImportEventPayload payload) {
getChunkIdHeader(payload)
);
}
+
+ private static boolean isAuthorityExtendedMode() {
+ return Boolean.parseBoolean(
+ System.getenv().getOrDefault(AUTHORITY_EXTENDED, "false"));
+ }
+
+ /**
+ * For test usage only.
+ *
+ * @param newIsAuthoritiesExtended New value for the env to set.
+ */
+ public static void setAuthorityExtendedMode(boolean newIsAuthoritiesExtended) {
+ isAuthorityExtended = newIsAuthoritiesExtended;
+ }
}
diff --git a/src/test/java/org/folio/inventory/dataimport/handlers/actions/UpdateAuthorityEventHandlerTest.java b/src/test/java/org/folio/inventory/dataimport/handlers/actions/UpdateAuthorityEventHandlerTest.java
index 5cea2d3c4..b4961c753 100644
--- a/src/test/java/org/folio/inventory/dataimport/handlers/actions/UpdateAuthorityEventHandlerTest.java
+++ b/src/test/java/org/folio/inventory/dataimport/handlers/actions/UpdateAuthorityEventHandlerTest.java
@@ -9,6 +9,8 @@
import io.vertx.core.Vertx;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
+import java.util.Arrays;
+import java.util.Collection;
import org.folio.ActionProfile;
import org.folio.Authority;
import org.folio.DataImportEventPayload;
@@ -28,9 +30,12 @@
import org.folio.rest.jaxrs.model.ParsedRecord;
import org.folio.rest.jaxrs.model.ProfileSnapshotWrapper;
import org.folio.rest.jaxrs.model.Record;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -70,11 +75,13 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+@RunWith(Parameterized.class)
public class UpdateAuthorityEventHandlerTest {
private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/marc-authority-rules.json";
private static final String PARSED_AUTHORITY_RECORD = "src/test/resources/marc/authority/parsed-authority-record.json";
private static final String MAPPING_METADATA_URL = "/mapping-metadata";
+ private final boolean isAuthorityExtended;
private final Vertx vertx = Vertx.vertx();
@Rule
@@ -112,6 +119,15 @@ public class UpdateAuthorityEventHandlerTest {
private UpdateAuthorityEventHandler eventHandler;
+ public UpdateAuthorityEventHandlerTest(boolean isAuthorityExtended) {
+ this.isAuthorityExtended = isAuthorityExtended;
+ }
+
+ @Parameterized.Parameters
+ public static Collection