From 6b23d3a4ea772e9a2839101a92eb083ed957cf4f Mon Sep 17 00:00:00 2001 From: Viachaslau Khandramai Date: Sun, 15 Dec 2024 22:00:12 +0100 Subject: [PATCH 1/2] MODEXPW-545 - TD: Improve caching (#605) * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching * MODEXPW-545 - Improve caching --- pom.xml | 29 ++-- .../BulkEditProcessingErrorsService.java | 4 +- .../dew/service/ElectronicAccessService.java | 58 +------- .../service/ElectronicAccessServiceCache.java | 25 ++++ .../dew/service/HoldingsReferenceService.java | 89 ++++-------- .../HoldingsReferenceServiceCache.java | 131 ++++++++++++++++++ .../dew/service/InstanceReferenceService.java | 57 ++------ .../InstanceReferenceServiceCache.java | 79 +++++++++++ .../dew/service/ItemReferenceService.java | 114 ++------------- .../service/ItemReferenceServiceCache.java | 68 +++++++++ .../dew/service/UserReferenceService.java | 62 +-------- .../service/UserReferenceServiceCache.java | 57 ++++++++ .../java/org/folio/dew/BaseBatchTest.java | 12 +- src/test/java/org/folio/dew/BulkEditTest.java | 16 +-- .../service/ElectronicAccessServiceTest.java | 63 +-------- .../service/HoldingsReferenceServiceTest.java | 29 ++-- .../service/InstanceReferenceServiceTest.java | 33 ++--- .../dew/service/UserReferenceServiceTest.java | 39 +----- .../service/mapper/InstanceMapperTest.java | 15 +- 19 files changed, 490 insertions(+), 490 deletions(-) create mode 100644 src/main/java/org/folio/dew/service/ElectronicAccessServiceCache.java create mode 100644 src/main/java/org/folio/dew/service/HoldingsReferenceServiceCache.java create mode 100644 src/main/java/org/folio/dew/service/InstanceReferenceServiceCache.java create mode 100644 src/main/java/org/folio/dew/service/ItemReferenceServiceCache.java create mode 100644 src/main/java/org/folio/dew/service/UserReferenceServiceCache.java diff --git a/pom.xml b/pom.xml index 11d0fe7f2..a7f88be74 100644 --- a/pom.xml +++ b/pom.xml @@ -292,21 +292,22 @@ ${spring-cloud-starter-bootstrap.version} test - + + org.springframework.boot + spring-boot-starter-test + 3.4.0 + test + + + org.junit.vintage + junit-vintage-engine + + org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - org.springframework.boot - spring-boot-starter-logging - - - + spring-boot-starter-logging + + + org.hamcrest hamcrest-all diff --git a/src/main/java/org/folio/dew/service/BulkEditProcessingErrorsService.java b/src/main/java/org/folio/dew/service/BulkEditProcessingErrorsService.java index 5a7b18854..8f0229be5 100644 --- a/src/main/java/org/folio/dew/service/BulkEditProcessingErrorsService.java +++ b/src/main/java/org/folio/dew/service/BulkEditProcessingErrorsService.java @@ -157,11 +157,11 @@ private String getPathToStorage(String jobId) { return format(STORAGE_TEMPLATE, jobId); } - private String getPathToCsvFile(String jobId, String csvFileName) { + public String getPathToCsvFile(String jobId, String csvFileName) { return format(CSV_FILE_TEMPLATE, jobId, csvFileName); } - private String getCsvFileName(String jobId, String fileName) { + public String getCsvFileName(String jobId, String fileName) { var pathToStorage = getPathToStorage(jobId); List names = new ArrayList<>(); diff --git a/src/main/java/org/folio/dew/service/ElectronicAccessService.java b/src/main/java/org/folio/dew/service/ElectronicAccessService.java index 95dfbf0a8..437e3f564 100644 --- a/src/main/java/org/folio/dew/service/ElectronicAccessService.java +++ b/src/main/java/org/folio/dew/service/ElectronicAccessService.java @@ -2,28 +2,18 @@ import static org.apache.commons.lang3.ObjectUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.EMPTY; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; -import static org.folio.dew.utils.Constants.ARRAY_DELIMITER; import static org.folio.dew.utils.Constants.ENTITY_TYPE_TO_ELECTRONIC_ACCESS_DATA_DELIMITER; import static org.folio.dew.utils.Constants.ENTITY_TYPE_TO_ELECTRONIC_ACCESS_DELIMITER; -import static org.folio.dew.utils.Constants.ITEM_DELIMITER_PATTERN; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.apache.commons.lang3.StringUtils; -import org.folio.dew.client.ElectronicAccessRelationshipClient; import org.folio.dew.domain.dto.ElectronicAccess; import org.folio.dew.domain.dto.EntityType; import org.folio.dew.domain.dto.ErrorServiceArgs; import org.folio.dew.error.BulkEditException; import org.folio.dew.error.NotFoundException; -import org.folio.spring.FolioExecutionContext; -import org.folio.spring.scope.FolioExecutionContextSetter; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -32,16 +22,8 @@ @RequiredArgsConstructor @Log4j2 public class ElectronicAccessService extends FolioExecutionContextManager { - private final ElectronicAccessRelationshipClient relationshipClient; private final BulkEditProcessingErrorsService errorsService; - private final FolioExecutionContext folioExecutionContext; - - private static final int NUMBER_OF_ELECTRONIC_ACCESS_COMPONENTS = 6; - private static final int ELECTRONIC_ACCESS_URI_INDEX = 0; - private static final int ELECTRONIC_ACCESS_LINK_TEXT_INDEX = 1; - private static final int ELECTRONIC_ACCESS_MATERIAL_SPECIFICATION_INDEX = 2; - private static final int ELECTRONIC_ACCESS_PUBLIC_NOTE_INDEX = 3; - + private final ElectronicAccessServiceCache electronicAccessServiceCache; public String getElectronicAccessesToString(List electronicAccesses, ErrorServiceArgs errorServiceArgs, EntityType entityType, String tenantId) { return isEmpty(electronicAccesses) ? @@ -63,12 +45,9 @@ private String electronicAccessToString(ElectronicAccess access, ErrorServiceArg isEmpty(access.getPublicNote()) ? EMPTY : access.getPublicNote()); } - @Cacheable(cacheNames = "relationships") public String getRelationshipNameById(String id, ErrorServiceArgs errorServiceArgs, String tenantId) { try { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return relationshipClient.getById(id).getName(); - } + return electronicAccessServiceCache.getRelationshipNameById(id, tenantId); } catch (NotFoundException e) { var errorMessage = String.format("Electronic access relationship not found by id=%s", id); log.error(errorMessage); @@ -76,37 +55,4 @@ public String getRelationshipNameById(String id, ErrorServiceArgs errorServiceAr return id; } } - - @Cacheable(cacheNames = "relationships") - public String getElectronicAccessRelationshipIdByName(String name) { - var relationships = relationshipClient.getByQuery(String.format("name==\"%s\"", name)); - if (relationships.getElectronicAccessRelationships().isEmpty()) { - return EMPTY; - } - return relationships.getElectronicAccessRelationships().get(0).getId(); - } - - public List restoreElectronicAccess(String s) { - return StringUtils.isEmpty(s) ? Collections.emptyList() : - Arrays.stream(s.split(ITEM_DELIMITER_PATTERN)) - .map(this::restoreElectronicAccessItem) - .filter(Objects::nonNull) - .toList(); - } - - private ElectronicAccess restoreElectronicAccessItem(String s) { - if (isNotEmpty(s)) { - var tokens = s.split(ARRAY_DELIMITER, -1); - if (NUMBER_OF_ELECTRONIC_ACCESS_COMPONENTS == tokens.length) { - return new ElectronicAccess() - .uri(tokens[ELECTRONIC_ACCESS_URI_INDEX]) - .linkText(tokens[ELECTRONIC_ACCESS_LINK_TEXT_INDEX]) - .materialsSpecification(tokens[ELECTRONIC_ACCESS_MATERIAL_SPECIFICATION_INDEX]) - .publicNote(tokens[ELECTRONIC_ACCESS_PUBLIC_NOTE_INDEX]) - .relationshipId(tokens[tokens.length - 1]); - } - throw new BulkEditException(String.format("Illegal number of electronic access elements: %d, expected: %d", tokens.length, NUMBER_OF_ELECTRONIC_ACCESS_COMPONENTS)); - } - return null; - } } diff --git a/src/main/java/org/folio/dew/service/ElectronicAccessServiceCache.java b/src/main/java/org/folio/dew/service/ElectronicAccessServiceCache.java new file mode 100644 index 000000000..c649c1ca3 --- /dev/null +++ b/src/main/java/org/folio/dew/service/ElectronicAccessServiceCache.java @@ -0,0 +1,25 @@ +package org.folio.dew.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.folio.dew.client.ElectronicAccessRelationshipClient; +import org.folio.spring.FolioExecutionContext; +import org.folio.spring.scope.FolioExecutionContextSetter; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@Log4j2 +public class ElectronicAccessServiceCache extends FolioExecutionContextManager { + + private final ElectronicAccessRelationshipClient relationshipClient; + private final FolioExecutionContext folioExecutionContext; + + @Cacheable(cacheNames = "relationships") + public String getRelationshipNameById(String id, String tenantId) { + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return relationshipClient.getById(id).getName(); + } + } +} diff --git a/src/main/java/org/folio/dew/service/HoldingsReferenceService.java b/src/main/java/org/folio/dew/service/HoldingsReferenceService.java index 2f0e39189..c2db510c1 100644 --- a/src/main/java/org/folio/dew/service/HoldingsReferenceService.java +++ b/src/main/java/org/folio/dew/service/HoldingsReferenceService.java @@ -6,27 +6,17 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.apache.commons.lang3.ObjectUtils; -import org.folio.dew.client.CallNumberTypeClient; import org.folio.dew.client.HoldingClient; -import org.folio.dew.client.HoldingsNoteTypeClient; -import org.folio.dew.client.HoldingsSourceClient; -import org.folio.dew.client.HoldingsTypeClient; -import org.folio.dew.client.IllPolicyClient; import org.folio.dew.client.InstanceClient; import org.folio.dew.client.InventoryClient; -import org.folio.dew.client.LocationClient; -import org.folio.dew.client.StatisticalCodeClient; import org.folio.dew.domain.dto.ErrorServiceArgs; import org.folio.dew.domain.dto.HoldingsRecord; import org.folio.dew.error.BulkEditException; import org.folio.dew.error.NotFoundException; import org.folio.spring.FolioExecutionContext; import org.folio.spring.scope.FolioExecutionContextSetter; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -34,22 +24,15 @@ @RequiredArgsConstructor @Log4j2 public class HoldingsReferenceService extends FolioExecutionContextManager { - private static final String QUERY_PATTERN_NAME = "name==\"%s\""; private static final String QUERY_PATTERN_HRID = "hrid==\"%s\""; private static final String QUERY_PATTERN_BARCODE = "barcode==\"%s\""; private final InstanceClient instanceClient; private final InventoryClient inventoryClient; - private final HoldingsTypeClient holdingsTypeClient; - private final LocationClient locationClient; - private final CallNumberTypeClient callNumberTypeClient; - private final HoldingsNoteTypeClient holdingsNoteTypeClient; - private final IllPolicyClient illPolicyClient; - private final HoldingsSourceClient sourceClient; - private final StatisticalCodeClient statisticalCodeClient; private final BulkEditProcessingErrorsService errorsService; private final HoldingClient holdingClient; private final FolioExecutionContext folioExecutionContext; + private final HoldingsReferenceServiceCache holdingsReferenceServiceCache; public HoldingsRecord getHoldingById(String id, String tenantId) { try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { @@ -110,13 +93,9 @@ public String getHoldingsIdByItemBarcode(String itemBarcode) { return items.getItems().get(0).getHoldingsRecordId(); } - @Cacheable(cacheNames = "holdingsTypesNames") public String getHoldingsTypeNameById(String id, ErrorServiceArgs args, String tenantId) { - if (isEmpty(id)) { - return EMPTY; - } - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : holdingsTypeClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getHoldingsTypeNameById(id, tenantId); } catch (NotFoundException e) { var msg = "Holdings type not found by id=" + id; log.error(msg); @@ -125,21 +104,9 @@ public String getHoldingsTypeNameById(String id, ErrorServiceArgs args, String t } } - @Cacheable(cacheNames = "holdingsLocationsNames") - public String getLocationNameById(String id, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : locationClient.getLocationById(id).getName(); - } catch (NotFoundException e) { - var msg = "Location not found by id=" + id; - log.error(msg); - throw new BulkEditException(msg); - } - } - - @Cacheable(cacheNames = "holdingsCallNumberTypesNames") public String getCallNumberTypeNameById(String id, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : callNumberTypeClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getCallNumberTypeNameById(id, tenantId); } catch (NotFoundException e) { var msg = "Call number type not found by id=" + id; log.error(msg); @@ -148,10 +115,9 @@ public String getCallNumberTypeNameById(String id, ErrorServiceArgs args, String } } - @Cacheable(cacheNames = "holdingsNoteTypesNames") public String getNoteTypeNameById(String id, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : holdingsNoteTypeClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getNoteTypeNameById(id, tenantId); } catch (NotFoundException e) { var msg = "Note type not found by id=" + id; log.error(msg); @@ -160,22 +126,21 @@ public String getNoteTypeNameById(String id, ErrorServiceArgs args, String tenan } } - @Cacheable(cacheNames = "illPolicyNames") public String getIllPolicyNameById(String id, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : illPolicyClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getIllPolicyNameById(id, tenantId); } catch (NotFoundException e) { - var msg = "Ill policy not found by id=" + id; - log.error(msg); - errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(msg), args.getFileName()); - return id; + var msg = "Ill policy not found by id=" + id; + log.error(msg); + errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(msg), args.getFileName()); + return id; } } - @Cacheable(cacheNames = "holdingsSourceNames") + public String getSourceNameById(String id, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : sourceClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getSourceNameById(id, tenantId); } catch (NotFoundException e) { var msg = "Holdings record source not found by id=" + id; log.error(msg); @@ -184,10 +149,9 @@ public String getSourceNameById(String id, ErrorServiceArgs args, String tenantI } } - @Cacheable(cacheNames = "holdingsStatisticalCodeNames") public String getStatisticalCodeNameById(String id, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(id) ? EMPTY : statisticalCodeClient.getById(id).getName(); + try { + return holdingsReferenceServiceCache.getStatisticalCodeNameById(id, tenantId); } catch (NotFoundException e) { var msg = "Statistical code not found by id=" + id; log.error(msg); @@ -196,20 +160,15 @@ public String getStatisticalCodeNameById(String id, ErrorServiceArgs args, Strin } } - @Cacheable(cacheNames = "holdings") public JsonNode getHoldingsJsonById(String holdingsId, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return holdingClient.getHoldingById(holdingsId); - } + return holdingsReferenceServiceCache.getHoldingsJsonById(holdingsId, tenantId); } - @Cacheable(cacheNames = "holdingsLocations") public JsonNode getHoldingsLocationById(String locationId, String tenantId) { - if (ObjectUtils.isEmpty(locationId)) { - return new ObjectMapper().createObjectNode(); - } - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return locationClient.getLocation(locationId); - } + return holdingsReferenceServiceCache.getHoldingsLocationById(locationId, tenantId); + } + + public String getLocationNameById(String id, String tenantId) { + return holdingsReferenceServiceCache.getLocationNameById(id, tenantId); } } diff --git a/src/main/java/org/folio/dew/service/HoldingsReferenceServiceCache.java b/src/main/java/org/folio/dew/service/HoldingsReferenceServiceCache.java new file mode 100644 index 000000000..80502eba6 --- /dev/null +++ b/src/main/java/org/folio/dew/service/HoldingsReferenceServiceCache.java @@ -0,0 +1,131 @@ +package org.folio.dew.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.ObjectUtils; +import org.folio.dew.client.CallNumberTypeClient; +import org.folio.dew.client.HoldingClient; +import org.folio.dew.client.HoldingsNoteTypeClient; +import org.folio.dew.client.HoldingsSourceClient; +import org.folio.dew.client.HoldingsTypeClient; +import org.folio.dew.client.IllPolicyClient; +import org.folio.dew.client.LocationClient; +import org.folio.dew.client.StatisticalCodeClient; +import org.folio.dew.error.BulkEditException; +import org.folio.dew.error.NotFoundException; +import org.folio.spring.FolioExecutionContext; +import org.folio.spring.scope.FolioExecutionContextSetter; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.apache.commons.lang3.StringUtils.isEmpty; + + +@Service +@RequiredArgsConstructor +@Log4j2 +public class HoldingsReferenceServiceCache extends FolioExecutionContextManager { + + private final HoldingsTypeClient holdingsTypeClient; + private final LocationClient locationClient; + private final CallNumberTypeClient callNumberTypeClient; + private final HoldingsNoteTypeClient holdingsNoteTypeClient; + private final IllPolicyClient illPolicyClient; + private final HoldingsSourceClient sourceClient; + private final StatisticalCodeClient statisticalCodeClient; + private final HoldingClient holdingClient; + private final FolioExecutionContext folioExecutionContext; + + + @Cacheable(cacheNames = "holdingsTypesNames") + public String getHoldingsTypeNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return holdingsTypeClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "holdingsLocationsNames") + public String getLocationNameById(String id, String tenantId) { + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return isEmpty(id) ? EMPTY : locationClient.getLocationById(id).getName(); + } catch (NotFoundException e) { + var msg = "Location not found by id=" + id; + log.error(msg); + throw new BulkEditException(msg); + } + } + + @Cacheable(cacheNames = "holdingsCallNumberTypesNames") + public String getCallNumberTypeNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return callNumberTypeClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "holdingsNoteTypesNames") + public String getNoteTypeNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return holdingsNoteTypeClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "illPolicyNames") + public String getIllPolicyNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return illPolicyClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "holdingsSourceNames") + public String getSourceNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return sourceClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "holdingsStatisticalCodeNames") + public String getStatisticalCodeNameById(String id, String tenantId) { + if (isEmpty(id)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return statisticalCodeClient.getById(id).getName(); + } + } + + @Cacheable(cacheNames = "holdings") + public JsonNode getHoldingsJsonById(String holdingsId, String tenantId) { + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return holdingClient.getHoldingById(holdingsId); + } + } + + @Cacheable(cacheNames = "holdingsLocations") + public JsonNode getHoldingsLocationById(String locationId, String tenantId) { + if (ObjectUtils.isEmpty(locationId)) { + return new ObjectMapper().createObjectNode(); + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return locationClient.getLocation(locationId); + } + } + +} diff --git a/src/main/java/org/folio/dew/service/InstanceReferenceService.java b/src/main/java/org/folio/dew/service/InstanceReferenceService.java index 57a57ff8e..b1c80adca 100644 --- a/src/main/java/org/folio/dew/service/InstanceReferenceService.java +++ b/src/main/java/org/folio/dew/service/InstanceReferenceService.java @@ -3,108 +3,75 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.apache.commons.lang3.StringUtils; -import org.folio.dew.client.InstanceNoteTypesClient; -import org.folio.dew.client.InstanceStatusesClient; -import org.folio.dew.client.InstanceModeOfIssuanceClient; -import org.folio.dew.client.InstanceTypesClient; -import org.folio.dew.client.NatureOfContentTermsClient; -import org.folio.dew.client.InstanceFormatsClient; -import org.folio.dew.client.IdentifierTypeClient; import org.folio.dew.domain.dto.ErrorServiceArgs; -import org.folio.dew.domain.dto.IdentifierTypeReferenceCollection; import org.folio.dew.error.BulkEditException; import org.folio.dew.error.NotFoundException; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import static org.apache.commons.lang3.ObjectUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.EMPTY; @Service @Log4j2 @RequiredArgsConstructor public class InstanceReferenceService { - private static final String QUERY_PATTERN_NAME = "name==\"%s\""; - private final BulkEditProcessingErrorsService errorsService; - private final InstanceStatusesClient instanceStatusesClient; - private final InstanceModeOfIssuanceClient instanceModeOfIssuanceClient; - private final InstanceTypesClient instanceTypesClient; - private final NatureOfContentTermsClient natureOfContentTermsClient; - private final InstanceFormatsClient instanceFormatsClient; - private final IdentifierTypeClient identifierTypeClient; - private final InstanceNoteTypesClient instanceNoteTypesClient; - + private final InstanceReferenceServiceCache instanceReferenceServiceCache; - @Cacheable(cacheNames = "instanceStatusNames") public String getInstanceStatusNameById(String instanceStatusId, ErrorServiceArgs args) { try { - return isEmpty(instanceStatusId) ? EMPTY : instanceStatusesClient.getById(instanceStatusId).getName(); + return instanceReferenceServiceCache.getInstanceStatusNameById(instanceStatusId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Instance status was not found by id: [%s]", instanceStatusId)), args.getFileName()); return instanceStatusId; } } - @Cacheable(cacheNames = "issuanceModeNames") + public String getModeOfIssuanceNameById(String issuanceModeId, ErrorServiceArgs args) { try { - return isEmpty(issuanceModeId) ? EMPTY : instanceModeOfIssuanceClient.getById(issuanceModeId).getName(); + return instanceReferenceServiceCache.getModeOfIssuanceNameById(issuanceModeId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Issuance mode was not found by id: [%s]", issuanceModeId)), args.getFileName()); return issuanceModeId; } } - @Cacheable(cacheNames = "instanceTypes") + public String getInstanceTypeNameById(String instanceTypeId, ErrorServiceArgs args) { try { - return isEmpty(instanceTypeId) ? EMPTY : instanceTypesClient.getById(instanceTypeId).getName(); + return instanceReferenceServiceCache.getInstanceTypeNameById(instanceTypeId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Instance type was not found by id: [%s]", instanceTypeId)), args.getFileName()); return instanceTypeId; } } - @Cacheable(cacheNames = "natureOfContentTermIds") + public String getNatureOfContentTermNameById(String natureOfContentTermId, ErrorServiceArgs args) { try { - return isEmpty(natureOfContentTermId) ? EMPTY : natureOfContentTermsClient.getById(natureOfContentTermId).getName(); + return instanceReferenceServiceCache.getNatureOfContentTermNameById(natureOfContentTermId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Nature of content term was not found by id: [%s]", natureOfContentTermId)), args.getFileName()); return natureOfContentTermId; } } - @Cacheable(cacheNames = "instanceFormatIds") + public String getFormatOfInstanceNameById(String instanceFormatId, ErrorServiceArgs args) { try { - return isEmpty(instanceFormatId) ? EMPTY : instanceFormatsClient.getById(instanceFormatId).getName(); + return instanceReferenceServiceCache.getFormatOfInstanceNameById(instanceFormatId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Instance format was not found by id: [%s]", instanceFormatId)), args.getFileName()); return instanceFormatId; } } - @Cacheable(cacheNames = "typeOfIdentifiersIds") public String getTypeOfIdentifiersIdByName(String identifierName) { - if (StringUtils.isEmpty(identifierName)) { - return null; - } - IdentifierTypeReferenceCollection typeOfIdentifiers = identifierTypeClient.getByQuery(String.format(QUERY_PATTERN_NAME, identifierName)); - if (typeOfIdentifiers.getIdentifierTypes().isEmpty()) { - log.error("Identifier type not found by identifierName={}", identifierName); - return identifierName; - } - return typeOfIdentifiers.getIdentifierTypes().get(0).getId(); + return instanceReferenceServiceCache.getTypeOfIdentifiersIdByName(identifierName); } - @Cacheable(cacheNames = "instanceNoteTypes") public String getInstanceNoteTypeNameById(String noteTypeId, ErrorServiceArgs args) { try { - return isEmpty(noteTypeId) ? EMPTY : instanceNoteTypesClient.getNoteTypeById(noteTypeId).getName(); + return instanceReferenceServiceCache.getInstanceNoteTypeNameById(noteTypeId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Instance note type was not found by id: [%s]", noteTypeId)), args.getFileName()); return noteTypeId; } } - } diff --git a/src/main/java/org/folio/dew/service/InstanceReferenceServiceCache.java b/src/main/java/org/folio/dew/service/InstanceReferenceServiceCache.java new file mode 100644 index 000000000..6d330898b --- /dev/null +++ b/src/main/java/org/folio/dew/service/InstanceReferenceServiceCache.java @@ -0,0 +1,79 @@ +package org.folio.dew.service; + + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.folio.dew.client.IdentifierTypeClient; +import org.folio.dew.client.InstanceFormatsClient; +import org.folio.dew.client.InstanceModeOfIssuanceClient; +import org.folio.dew.client.InstanceNoteTypesClient; +import org.folio.dew.client.InstanceStatusesClient; +import org.folio.dew.client.InstanceTypesClient; +import org.folio.dew.client.NatureOfContentTermsClient; +import org.folio.dew.domain.dto.IdentifierTypeReferenceCollection; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import static org.apache.commons.lang3.ObjectUtils.isEmpty; +import static org.apache.commons.lang3.StringUtils.EMPTY; + +@Service +@Log4j2 +@RequiredArgsConstructor +public class InstanceReferenceServiceCache { + + private static final String QUERY_PATTERN_NAME = "name==\"%s\""; + + private final InstanceStatusesClient instanceStatusesClient; + private final InstanceModeOfIssuanceClient instanceModeOfIssuanceClient; + private final InstanceTypesClient instanceTypesClient; + private final NatureOfContentTermsClient natureOfContentTermsClient; + private final InstanceFormatsClient instanceFormatsClient; + private final IdentifierTypeClient identifierTypeClient; + private final InstanceNoteTypesClient instanceNoteTypesClient; + + + @Cacheable(cacheNames = "instanceStatusNames") + public String getInstanceStatusNameById(String instanceStatusId) { + return isEmpty(instanceStatusId) ? EMPTY : instanceStatusesClient.getById(instanceStatusId).getName(); + } + + @Cacheable(cacheNames = "issuanceModeNames") + public String getModeOfIssuanceNameById(String issuanceModeId) { + return isEmpty(issuanceModeId) ? EMPTY : instanceModeOfIssuanceClient.getById(issuanceModeId).getName(); + } + + @Cacheable(cacheNames = "instanceTypes") + public String getInstanceTypeNameById(String instanceTypeId) { + return isEmpty(instanceTypeId) ? EMPTY : instanceTypesClient.getById(instanceTypeId).getName(); + } + + @Cacheable(cacheNames = "natureOfContentTermIds") + public String getNatureOfContentTermNameById(String natureOfContentTermId) { + return isEmpty(natureOfContentTermId) ? EMPTY : natureOfContentTermsClient.getById(natureOfContentTermId).getName(); + } + + @Cacheable(cacheNames = "instanceFormatIds") + public String getFormatOfInstanceNameById(String instanceFormatId) { + return isEmpty(instanceFormatId) ? EMPTY : instanceFormatsClient.getById(instanceFormatId).getName(); + } + + @Cacheable(cacheNames = "typeOfIdentifiersIds") + public String getTypeOfIdentifiersIdByName(String identifierName) { + if (StringUtils.isEmpty(identifierName)) { + return null; + } + IdentifierTypeReferenceCollection typeOfIdentifiers = identifierTypeClient.getByQuery(String.format(QUERY_PATTERN_NAME, identifierName)); + if (typeOfIdentifiers.getIdentifierTypes().isEmpty()) { + log.error("Identifier type not found by identifierName={}", identifierName); + return identifierName; + } + return typeOfIdentifiers.getIdentifierTypes().get(0).getId(); + } + + @Cacheable(cacheNames = "instanceNoteTypes") + public String getInstanceNoteTypeNameById(String noteTypeId) { + return isEmpty(noteTypeId) ? EMPTY : instanceNoteTypesClient.getNoteTypeById(noteTypeId).getName(); + } +} diff --git a/src/main/java/org/folio/dew/service/ItemReferenceService.java b/src/main/java/org/folio/dew/service/ItemReferenceService.java index c930243bc..ccb9fb798 100644 --- a/src/main/java/org/folio/dew/service/ItemReferenceService.java +++ b/src/main/java/org/folio/dew/service/ItemReferenceService.java @@ -1,149 +1,55 @@ package org.folio.dew.service; -import static java.util.Objects.nonNull; -import static org.apache.commons.lang3.ObjectUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.EMPTY; -import static org.folio.dew.utils.Constants.BULK_EDIT_CONFIGURATIONS_QUERY_TEMPLATE; -import static org.folio.dew.utils.Constants.MODULE_NAME; -import static org.folio.dew.utils.Constants.STATUSES_CONFIG_NAME; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.folio.dew.client.CallNumberTypeClient; -import org.folio.dew.client.ConfigurationClient; -import org.folio.dew.client.DamagedStatusClient; -import org.folio.dew.client.HoldingClient; -import org.folio.dew.client.ItemNoteTypeClient; -import org.folio.dew.client.LoanTypeClient; -import org.folio.dew.client.LocationClient; -import org.folio.dew.client.MaterialTypeClient; -import org.folio.dew.client.ServicePointClient; -import org.folio.dew.client.StatisticalCodeClient; -import org.folio.dew.client.UserClient; import org.folio.dew.domain.dto.ErrorServiceArgs; -import org.folio.dew.domain.dto.ItemLocationCollection; -import org.folio.dew.domain.dto.LoanTypeCollection; -import org.folio.dew.domain.dto.MaterialTypeCollection; import org.folio.dew.error.BulkEditException; -import org.folio.dew.error.ConfigurationException; import org.folio.dew.error.NotFoundException; -import org.folio.spring.FolioExecutionContext; -import org.folio.spring.scope.FolioExecutionContextSetter; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; @Service @Log4j2 @RequiredArgsConstructor public class ItemReferenceService extends FolioExecutionContextManager { - private static final String QUERY_PATTERN_NAME = "name==\"%s\""; - public static final String EFFECTIVE_LOCATION_ID = "effectiveLocationId"; - private final CallNumberTypeClient callNumberTypeClient; - private final DamagedStatusClient damagedStatusClient; - private final ItemNoteTypeClient itemNoteTypeClient; - private final StatisticalCodeClient statisticalCodeClient; - private final LocationClient locationClient; - private final MaterialTypeClient materialTypeClient; - private final HoldingClient holdingClient; - private final LoanTypeClient loanTypeClient; - private final ConfigurationClient configurationClient; - private final ObjectMapper objectMapper; private final BulkEditProcessingErrorsService errorsService; - private final FolioExecutionContext folioExecutionContext; + private final ItemReferenceServiceCache itemReferenceServiceCache; + - @Cacheable(cacheNames = "callNumberTypeNames") public String getCallNumberTypeNameById(String callNumberTypeId, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(callNumberTypeId) ? EMPTY : callNumberTypeClient.getById(callNumberTypeId).getName(); + try { + return itemReferenceServiceCache.getCallNumberTypeNameById(callNumberTypeId, tenantId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Call number type was not found by id: [%s]", callNumberTypeId)), args.getFileName()); return callNumberTypeId; } } - @Cacheable(cacheNames = "damagedStatusNames") public String getDamagedStatusNameById(String damagedStatusId, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(damagedStatusId) ? EMPTY : damagedStatusClient.getById(damagedStatusId).getName(); + try { + return itemReferenceServiceCache.getDamagedStatusNameById(damagedStatusId, tenantId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Damaged status was not found by id: [%s]", damagedStatusId)), args.getFileName()); return damagedStatusId; } } - @Cacheable(cacheNames = "noteTypeNames") public String getNoteTypeNameById(String noteTypeId, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(noteTypeId) ? EMPTY : itemNoteTypeClient.getById(noteTypeId).getName(); + try { + return itemReferenceServiceCache.getNoteTypeNameById(noteTypeId, tenantId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Note type was not found by id: [%s]", noteTypeId)), args.getFileName()); return noteTypeId; } } - @Cacheable(cacheNames = "statisticalCodeNames") public String getStatisticalCodeById(String statisticalCodeId, ErrorServiceArgs args, String tenantId) { - try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { - return isEmpty(statisticalCodeId) ? EMPTY : statisticalCodeClient.getById(statisticalCodeId).getCode(); + try { + return itemReferenceServiceCache.getStatisticalCodeById(statisticalCodeId, tenantId); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Statistical code was not found by id: [%s]", statisticalCodeId)), args.getFileName()); return statisticalCodeId; } } - - @Cacheable(cacheNames = "locations") - public ItemLocationCollection getItemLocationsByName(String name) { - return locationClient.getLocationByQuery(String.format(QUERY_PATTERN_NAME, name)); - } - - @Cacheable(cacheNames = "materialTypes") - public MaterialTypeCollection getMaterialTypesByName(String name) { - return materialTypeClient.getByQuery(String.format(QUERY_PATTERN_NAME, name)); - } - - @Cacheable(cacheNames = "loanTypes") - public LoanTypeCollection getLoanTypesByName(String name) { - return loanTypeClient.getByQuery(String.format(QUERY_PATTERN_NAME, name)); - } - - @Cacheable(cacheNames = "holdings") - public String getHoldingEffectiveLocationCodeById(String id) { - var holdingJson = holdingClient.getHoldingById(id); - var effectiveLocationId = isEmpty(holdingJson.get(EFFECTIVE_LOCATION_ID)) ? getHoldingsEffectiveLocation(holdingJson) : holdingJson.get(EFFECTIVE_LOCATION_ID); - if (nonNull(effectiveLocationId)) { - var locationJson = locationClient.getLocation(effectiveLocationId.asText()); - return isEmpty(locationJson.get("name")) ? EMPTY : locationJson.get("name").asText(); - } - return EMPTY; - } - - @Cacheable(cacheNames = "allowedStatuses") - public List getAllowedStatuses(String statusName) { - var configurations = configurationClient.getConfigurations(String.format(BULK_EDIT_CONFIGURATIONS_QUERY_TEMPLATE, MODULE_NAME, STATUSES_CONFIG_NAME)); - if (configurations.getConfigs().isEmpty()) { - throw new NotFoundException("Statuses configuration was not found"); - } - try { - var statuses = objectMapper - .readValue(configurations.getConfigs().get(0).getValue(), new TypeReference>>() {}); - return statuses.getOrDefault(statusName, Collections.emptyList()); - } catch (JsonProcessingException e) { - var msg = String.format("Error reading configuration, reason: %s", e.getMessage()); - log.error(msg); - throw new ConfigurationException(msg); - } - } - - private JsonNode getHoldingsEffectiveLocation(JsonNode holdingsJson) { - return isEmpty(holdingsJson.get("temporaryLocationId")) ? holdingsJson.get("permanentLocationId") : holdingsJson.get("temporaryLocationId"); - } } diff --git a/src/main/java/org/folio/dew/service/ItemReferenceServiceCache.java b/src/main/java/org/folio/dew/service/ItemReferenceServiceCache.java new file mode 100644 index 000000000..e8d58e1bc --- /dev/null +++ b/src/main/java/org/folio/dew/service/ItemReferenceServiceCache.java @@ -0,0 +1,68 @@ +package org.folio.dew.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.folio.dew.client.CallNumberTypeClient; +import org.folio.dew.client.DamagedStatusClient; +import org.folio.dew.client.ItemNoteTypeClient; +import org.folio.dew.client.StatisticalCodeClient; +import org.folio.spring.FolioExecutionContext; +import org.folio.spring.scope.FolioExecutionContextSetter; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import static org.apache.commons.lang3.ObjectUtils.isEmpty; +import static org.apache.commons.lang3.StringUtils.EMPTY; + + +@Service +@Log4j2 +@RequiredArgsConstructor +public class ItemReferenceServiceCache extends FolioExecutionContextManager { + + private final CallNumberTypeClient callNumberTypeClient; + private final DamagedStatusClient damagedStatusClient; + private final ItemNoteTypeClient itemNoteTypeClient; + private final StatisticalCodeClient statisticalCodeClient; + private final FolioExecutionContext folioExecutionContext; + + @Cacheable(cacheNames = "callNumberTypeNames") + public String getCallNumberTypeNameById(String callNumberTypeId, String tenantId) { + if (isEmpty(callNumberTypeId)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return callNumberTypeClient.getById(callNumberTypeId).getName(); + } + } + + @Cacheable(cacheNames = "damagedStatusNames") + public String getDamagedStatusNameById(String damagedStatusId, String tenantId) { + if (isEmpty(damagedStatusId)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return damagedStatusClient.getById(damagedStatusId).getName(); + } + } + + @Cacheable(cacheNames = "noteTypeNames") + public String getNoteTypeNameById(String noteTypeId, String tenantId) { + if (isEmpty(noteTypeId)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return itemNoteTypeClient.getById(noteTypeId).getName(); + } + } + + @Cacheable(cacheNames = "statisticalCodeNames") + public String getStatisticalCodeById(String statisticalCodeId, String tenantId) { + if (isEmpty(statisticalCodeId)) { + return EMPTY; + } + try (var context = new FolioExecutionContextSetter(refreshAndGetFolioExecutionContext(tenantId, folioExecutionContext))) { + return statisticalCodeClient.getById(statisticalCodeId).getCode(); + } + } +} diff --git a/src/main/java/org/folio/dew/service/UserReferenceService.java b/src/main/java/org/folio/dew/service/UserReferenceService.java index f591c06b7..a87cacdb9 100644 --- a/src/main/java/org/folio/dew/service/UserReferenceService.java +++ b/src/main/java/org/folio/dew/service/UserReferenceService.java @@ -1,23 +1,10 @@ package org.folio.dew.service; -import static org.apache.commons.lang3.StringUtils.EMPTY; -import static java.lang.String.format; -import static java.util.Objects.isNull; -import static org.apache.commons.lang3.ObjectUtils.isEmpty; -import static org.folio.dew.batch.bulkedit.jobs.processidentifiers.Utils.encode; -import static org.folio.dew.utils.Constants.QUERY_PATTERN_REF_ID; - import lombok.extern.log4j.Log4j2; -import org.folio.dew.client.AddressTypeClient; -import org.folio.dew.client.CustomFieldsClient; -import org.folio.dew.client.DepartmentClient; -import org.folio.dew.client.GroupClient; import org.folio.dew.domain.dto.CustomField; import org.folio.dew.domain.dto.ErrorServiceArgs; import org.folio.dew.error.BulkEditException; import org.folio.dew.error.NotFoundException; -import org.folio.spring.FolioExecutionContext; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; @@ -27,76 +14,37 @@ @Log4j2 public class UserReferenceService { - private final AddressTypeClient addressTypeClient; - private final DepartmentClient departmentClient; - private final GroupClient groupClient; - private final CustomFieldsClient customFieldsClient; private final BulkEditProcessingErrorsService errorsService; - private final ModuleTenantService moduleTenantService; - private final FolioExecutionContext folioExecutionContext; + private final UserReferenceServiceCache userReferenceServiceCache; - @Cacheable(cacheNames = "addressTypeNames") public String getAddressTypeDescById(String id, ErrorServiceArgs args) { try { - return isNull(id) ? EMPTY : addressTypeClient.getAddressTypeById(id).getAddressType(); + return userReferenceServiceCache.getAddressTypeDescById(id); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Address type was not found by id: [%s]", id)), args.getFileName()); return id; } } - @Cacheable(cacheNames = "addressTypeIds") - public String getAddressTypeIdByDesc(String desc) { - if (isEmpty(desc)) { - return null; - } else { - var response = addressTypeClient.getAddressTypeByQuery(String.format("desc==\"%s\"", desc)); - if (response.getAddressTypes().isEmpty()) { - return desc; - } - return response.getAddressTypes().get(0).getId(); - } - } - - @Cacheable(cacheNames = "departmentNames") public String getDepartmentNameById(String id, ErrorServiceArgs args) { try { - return isNull(id) ? EMPTY : departmentClient.getDepartmentById(id).getName(); + return userReferenceServiceCache.getDepartmentNameById(id); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Department was not found by id: [%s]", id)), args.getFileName()); return id; } } - @Cacheable(cacheNames = "departmentIds") - public String getDepartmentIdByName(String name) { - if (isEmpty(name)) { - return null; - } else { - var response = departmentClient.getDepartmentByQuery(String.format("name==\"%s\"", name)); - if (response.getDepartments().isEmpty()) { - return name; - } - return response.getDepartments().get(0).getId(); - } - } - - @Cacheable(cacheNames = "patronGroupNames") public String getPatronGroupNameById(String id, ErrorServiceArgs args) { try { - return isNull(id) ? EMPTY : groupClient.getGroupById(id).getGroup(); + return userReferenceServiceCache.getPatronGroupNameById(id); } catch (NotFoundException e) { errorsService.saveErrorInCSV(args.getJobId(), args.getIdentifier(), new BulkEditException(String.format("Patron group was not found by id: [%s]", id)), args.getFileName()); return id; } } - @Cacheable(cacheNames = "customFields") public CustomField getCustomFieldByRefId(String refId) { - var moduleId = moduleTenantService.getModUsersModuleId(); - return customFieldsClient.getCustomFieldsByQuery(moduleId, format(QUERY_PATTERN_REF_ID, encode(refId))).getCustomFields() - .stream().filter(customField -> customField.getRefId().equals(refId)) - .findFirst() - .orElseThrow(() -> new BulkEditException(format("Custom field with refId=%s not found", refId))); + return userReferenceServiceCache.getCustomFieldByRefId(refId); } } diff --git a/src/main/java/org/folio/dew/service/UserReferenceServiceCache.java b/src/main/java/org/folio/dew/service/UserReferenceServiceCache.java new file mode 100644 index 000000000..87f8b8dde --- /dev/null +++ b/src/main/java/org/folio/dew/service/UserReferenceServiceCache.java @@ -0,0 +1,57 @@ +package org.folio.dew.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.folio.dew.client.AddressTypeClient; +import org.folio.dew.client.CustomFieldsClient; +import org.folio.dew.client.DepartmentClient; +import org.folio.dew.client.GroupClient; +import org.folio.dew.domain.dto.CustomField; +import org.folio.dew.error.BulkEditException; +import org.folio.spring.FolioExecutionContext; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import static java.lang.String.format; +import static java.util.Objects.isNull; +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.folio.dew.batch.bulkedit.jobs.processidentifiers.Utils.encode; +import static org.folio.dew.utils.Constants.QUERY_PATTERN_REF_ID; + +@Service +@RequiredArgsConstructor +@Log4j2 +public class UserReferenceServiceCache { + + private final AddressTypeClient addressTypeClient; + private final DepartmentClient departmentClient; + private final GroupClient groupClient; + private final CustomFieldsClient customFieldsClient; + private final BulkEditProcessingErrorsService errorsService; + private final ModuleTenantService moduleTenantService; + private final FolioExecutionContext folioExecutionContext; + + @Cacheable(cacheNames = "addressTypeNames") + public String getAddressTypeDescById(String id) { + return isNull(id) ? EMPTY : addressTypeClient.getAddressTypeById(id).getAddressType(); + } + + @Cacheable(cacheNames = "departmentNames") + public String getDepartmentNameById(String id) { + return isNull(id) ? EMPTY : departmentClient.getDepartmentById(id).getName(); + } + + @Cacheable(cacheNames = "patronGroupNames") + public String getPatronGroupNameById(String id) { + return isNull(id) ? EMPTY : groupClient.getGroupById(id).getGroup(); + } + + @Cacheable(cacheNames = "customFields") + public CustomField getCustomFieldByRefId(String refId) { + var moduleId = moduleTenantService.getModUsersModuleId(); + return customFieldsClient.getCustomFieldsByQuery(moduleId, format(QUERY_PATTERN_REF_ID, encode(refId))).getCustomFields() + .stream().filter(customField -> customField.getRefId().equals(refId)) + .findFirst() + .orElseThrow(() -> new BulkEditException(format("Custom field with refId=%s not found", refId))); + } +} diff --git a/src/test/java/org/folio/dew/BaseBatchTest.java b/src/test/java/org/folio/dew/BaseBatchTest.java index 4c4e9016e..6efc6f870 100644 --- a/src/test/java/org/folio/dew/BaseBatchTest.java +++ b/src/test/java/org/folio/dew/BaseBatchTest.java @@ -27,6 +27,9 @@ import org.folio.dew.batch.ExportJobManager; import org.folio.dew.batch.ExportJobManagerSync; import org.folio.dew.client.ConsortiaClient; +import org.folio.dew.client.ElectronicAccessRelationshipClient; +import org.folio.dew.client.InstanceClient; +import org.folio.dew.client.InstanceNoteTypesClient; import org.folio.dew.client.SearchClient; import org.folio.dew.client.OkapiUserPermissionsClient; import org.folio.dew.domain.dto.BatchIdsDto; @@ -91,7 +94,7 @@ public abstract class BaseBatchTest { public static PostgreSQLContainer postgreDBContainer = new PostgreSQLContainer<>("postgres:13"); @Autowired - protected MockMvc mockMvc; + public MockMvc mockMvc; @Autowired private FolioModuleMetadata folioModuleMetadata; @Autowired @@ -118,6 +121,12 @@ public abstract class BaseBatchTest { private ConsortiaClient consortiaClient; @MockBean protected OkapiUserPermissionsClient okapiUserPermissionsClient; + @MockBean + public InstanceClient instanceClient; + @MockBean + public InstanceNoteTypesClient instanceNoteTypesClient; + @MockBean + public ElectronicAccessRelationshipClient relationshipClient; static { postgreDBContainer.start(); @@ -207,6 +216,7 @@ protected void setUp() { when(consortiaClient.getUserTenantCollection()) .thenReturn(new UserTenantCollection().userTenants(List.of(new UserTenant().tenantId("member").centralTenantId("central")))); + } @AfterEach diff --git a/src/test/java/org/folio/dew/BulkEditTest.java b/src/test/java/org/folio/dew/BulkEditTest.java index 17e88fcb9..c262b113f 100644 --- a/src/test/java/org/folio/dew/BulkEditTest.java +++ b/src/test/java/org/folio/dew/BulkEditTest.java @@ -7,27 +7,23 @@ import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.folio.dew.client.InstanceClient; import org.folio.dew.config.kafka.KafkaService; import org.folio.dew.domain.dto.BriefInstance; import org.folio.dew.domain.dto.BriefInstanceCollection; +import org.folio.dew.domain.dto.ElectronicAccessRelationship; import org.folio.dew.domain.dto.EntityType; import org.folio.dew.domain.dto.ExportType; import org.folio.dew.domain.dto.IdentifierType; import org.folio.dew.domain.dto.JobParameterNames; import org.folio.dew.repository.LocalFilesStorage; import org.folio.dew.service.UserPermissionsService; -import org.folio.spring.FolioExecutionContext; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.EnumSource; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; @@ -99,7 +95,6 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; -@ExtendWith(MockitoExtension.class) class BulkEditTest extends BaseBatchTest { private static final String HOLDINGS_IDENTIFIERS_CSV = "src/test/resources/upload/holdings_identifiers.csv"; @@ -183,13 +178,9 @@ class BulkEditTest extends BaseBatchTest { @Autowired private LocalFilesStorage localFilesStorage; @MockBean - private InstanceClient instanceClient; - @MockBean private KafkaService kafkaService; @MockBean private UserPermissionsService userPermissionsService; - @Mock - private FolioExecutionContext folioExecutionContext; @ParameterizedTest @CsvSource({"BARCODE," + BARCODES_CSV, "USER_NAME," + USERNAMES_CSV}) @@ -241,6 +232,7 @@ void shouldUpdateProgressUponItemIdentifiersJob() throws Exception { mockInstanceClient(); when(userPermissionsService.getPermissions()).thenReturn(List.of(BULK_EDIT_INVENTORY_VIEW_PERMISSION.getValue(), INVENTORY_ITEMS_ITEM_GET_PERMISSION.getValue())); + when(relationshipClient.getById(any())).thenReturn(new ElectronicAccessRelationship().name("Version of resource")); JobLauncherTestUtils testLauncher = createTestLauncher(bulkEditProcessItemIdentifiersJob); final JobParameters jobParameters = prepareJobParameters(BULK_EDIT_IDENTIFIERS, ITEM, BARCODE, BARCODES_FOR_PROGRESS_CSV); @@ -583,7 +575,7 @@ void shouldSkipDuplicatedHoldingsOnItemBarcodes() throws Exception { mockInstanceClient(); when(userPermissionsService.getPermissions()).thenReturn(List.of(BULK_EDIT_INVENTORY_VIEW_PERMISSION.getValue(), INVENTORY_STORAGE_HOLDINGS_ITEM_GET_PERMISSION.getValue())); JobLauncherTestUtils testLauncher = createTestLauncher(bulkEditProcessHoldingsIdentifiersJob); -// when(folioExecutionContext.getAllHeaders()).thenReturn(Map.of(X_OKAPI_TENANT, List.of("original"))); + when(relationshipClient.getById(any())).thenReturn(new ElectronicAccessRelationship().name("Version of resource")); final JobParameters jobParameters = prepareJobParameters(BULK_EDIT_IDENTIFIERS, HOLDINGS_RECORD, ITEM_BARCODE, HOLDINGS_IDENTIFIERS_ITEM_BARCODE_CSV); JobExecution jobExecution = testLauncher.launchJob(jobParameters); @@ -628,6 +620,7 @@ void bulkEditUserJobTestWithErrors() throws Exception { void bulkEditItemJobTestWithErrors() throws Exception { mockInstanceClient(); when(userPermissionsService.getPermissions()).thenReturn(List.of(BULK_EDIT_INVENTORY_VIEW_PERMISSION.getValue(), INVENTORY_ITEMS_ITEM_GET_PERMISSION.getValue())); + when(relationshipClient.getById(any())).thenReturn(new ElectronicAccessRelationship().name("Version of resource")); JobLauncherTestUtils testLauncher = createTestLauncher(bulkEditProcessItemIdentifiersJob); final JobParameters jobParameters = prepareJobParameters(BULK_EDIT_IDENTIFIERS, ITEM, BARCODE, ITEM_BARCODES_SOME_NOT_FOUND); @@ -672,6 +665,7 @@ void shouldProcessUsersWithoutPatronGroupIdSuccessfully() throws Exception { void shouldEscapeDoubleQuotes() { mockInstanceClient(); when(userPermissionsService.getPermissions()).thenReturn(List.of(BULK_EDIT_INVENTORY_VIEW_PERMISSION.getValue(), INVENTORY_ITEMS_ITEM_GET_PERMISSION.getValue())); + when(relationshipClient.getById(any())).thenReturn(new ElectronicAccessRelationship().name("Version of resource")); JobLauncherTestUtils testLauncher = createTestLauncher(bulkEditProcessItemIdentifiersJob); final JobParameters jobParameters = prepareJobParameters(BULK_EDIT_IDENTIFIERS, ITEM, BARCODE, ITEM_BARCODES_DOUBLE_QOUTES_CSV); diff --git a/src/test/java/org/folio/dew/service/ElectronicAccessServiceTest.java b/src/test/java/org/folio/dew/service/ElectronicAccessServiceTest.java index a91b72126..fa091e8cb 100644 --- a/src/test/java/org/folio/dew/service/ElectronicAccessServiceTest.java +++ b/src/test/java/org/folio/dew/service/ElectronicAccessServiceTest.java @@ -1,47 +1,24 @@ package org.folio.dew.service; -import org.apache.commons.lang3.StringUtils; -import org.folio.dew.client.ElectronicAccessRelationshipClient; +import org.folio.dew.BaseBatchTest; import org.folio.dew.domain.dto.ElectronicAccess; import org.folio.dew.domain.dto.ElectronicAccessRelationship; -import org.folio.dew.domain.dto.ElectronicAccessRelationshipCollection; import org.folio.dew.domain.dto.ErrorServiceArgs; import org.folio.dew.error.NotFoundException; -import org.folio.spring.FolioExecutionContext; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; +import org.springframework.beans.factory.annotation.Autowired; + import java.util.List; -import java.util.Map; import java.util.UUID; import static org.folio.dew.domain.dto.EntityType.HOLDINGS_RECORD; -import static org.folio.dew.service.FolioExecutionContextManager.X_OKAPI_TENANT; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@ExtendWith(MockitoExtension.class) -class ElectronicAccessServiceTest { - - @Mock - private ElectronicAccessRelationshipClient relationshipClient; - @Mock - private BulkEditProcessingErrorsService bulkEditProcessingErrorsService; - @Mock - private FolioExecutionContext folioExecutionContext; - @Spy - private SpecialCharacterEscaper escaper; +class ElectronicAccessServiceTest extends BaseBatchTest { - @InjectMocks + @Autowired private ElectronicAccessService electronicAccessService; @Test @@ -118,9 +95,6 @@ void getRelationshipNameAndIdByIdTest() { @Test void getRelationshipNameAndIdByIdNotFoundExceptionTest() { - Map> headers = new HashMap<>(); - headers.put(X_OKAPI_TENANT, List.of("original")); - when(folioExecutionContext.getAllHeaders()).thenReturn(headers); var id = UUID.randomUUID().toString(); var electronicAccessRelationship = new ElectronicAccessRelationship(); electronicAccessRelationship.setId(id); @@ -134,33 +108,6 @@ void getRelationshipNameAndIdByIdNotFoundExceptionTest() { assertEquals(expected, actual); } - @Test - void getElectronicAccessRelationshipIdByNameTest() { - var id = UUID.randomUUID().toString(); - var electronicAccessRelationship = new ElectronicAccessRelationship(); - electronicAccessRelationship.setId(id); - electronicAccessRelationship.name("name"); - - var electronicAccessRelationshipCollection = new ElectronicAccessRelationshipCollection(); - electronicAccessRelationshipCollection.setElectronicAccessRelationships(List.of(electronicAccessRelationship)); - - when(relationshipClient.getByQuery(isA(String.class))).thenReturn(electronicAccessRelationshipCollection); - - var actualId = electronicAccessService.getElectronicAccessRelationshipIdByName("name"); - assertEquals(id, actualId); - } - - @Test - void getElectronicAccessRelationshipIdByNameWithEmptyCollectionTest() { - var electronicAccessRelationshipCollection = new ElectronicAccessRelationshipCollection(); - electronicAccessRelationshipCollection.setElectronicAccessRelationships(new ArrayList<>()); - - when(relationshipClient.getByQuery(isA(String.class))).thenReturn(electronicAccessRelationshipCollection); - - var actualId = electronicAccessService.getElectronicAccessRelationshipIdByName("name"); - assertEquals(StringUtils.EMPTY, actualId); - } - private ErrorServiceArgs buildErrorServiceArgs() { return new ErrorServiceArgs(UUID.randomUUID().toString(), "identifier", "filename"); } diff --git a/src/test/java/org/folio/dew/service/HoldingsReferenceServiceTest.java b/src/test/java/org/folio/dew/service/HoldingsReferenceServiceTest.java index 8ef8cd16f..95c062bf7 100644 --- a/src/test/java/org/folio/dew/service/HoldingsReferenceServiceTest.java +++ b/src/test/java/org/folio/dew/service/HoldingsReferenceServiceTest.java @@ -1,20 +1,11 @@ package org.folio.dew.service; -import static org.folio.dew.service.FolioExecutionContextManager.X_OKAPI_TENANT; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; - import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; -import org.folio.dew.client.InstanceClient; -import org.folio.spring.FolioExecutionContext; -import org.junit.jupiter.api.extension.ExtendWith; +import org.folio.dew.BaseBatchTest; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; import java.io.File; import java.util.Collection; @@ -23,13 +14,14 @@ import java.util.Map; import java.util.UUID; -@ExtendWith(MockitoExtension.class) -class HoldingsReferenceServiceTest { - @Mock - private InstanceClient instanceClient; - @Mock - private FolioExecutionContext folioExecutionContext; - @InjectMocks +import static org.folio.dew.service.FolioExecutionContextManager.X_OKAPI_TENANT; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +class HoldingsReferenceServiceTest extends BaseBatchTest { + + @Autowired private HoldingsReferenceService service; @ParameterizedTest @@ -46,7 +38,6 @@ void shouldFormatInstanceTitle(String fileName, String expected) { var path = "src/test/resources/samples/" + fileName; var resultJson = mapper.readTree(new File(path)); - when(folioExecutionContext.getAllHeaders()).thenReturn(headers); when(instanceClient.getInstanceJsonById(anyString())).thenReturn(resultJson); var actual = service.getInstanceTitleById(UUID.randomUUID().toString(), "tenant"); diff --git a/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java b/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java index fea2f506c..30105bf8b 100644 --- a/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java +++ b/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java @@ -1,33 +1,29 @@ package org.folio.dew.service; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; + +import static java.lang.String.format; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.folio.dew.client.InstanceNoteTypesClient; +import org.folio.dew.BaseBatchTest; import org.folio.dew.domain.dto.ErrorServiceArgs; -import org.folio.dew.error.BulkEditException; import org.folio.dew.error.NotFoundException; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullAndEmptySource; -import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; import java.util.UUID; @ExtendWith(MockitoExtension.class) -class InstanceReferenceServiceTest { - @Mock - private InstanceNoteTypesClient instanceNoteTypesClient; - @Mock +class InstanceReferenceServiceTest extends BaseBatchTest { + @Autowired private BulkEditProcessingErrorsService errorsService; - @InjectMocks + @Autowired private InstanceReferenceService instanceReferenceService; @Test @@ -35,10 +31,15 @@ void shouldSaveErrorWhenInstanceNoteTypeNotFound() { when(instanceNoteTypesClient.getNoteTypeById(anyString())) .thenThrow(new NotFoundException("not found")); - instanceReferenceService.getInstanceNoteTypeNameById(UUID.randomUUID().toString(), + var id = UUID.randomUUID().toString(); + + instanceReferenceService.getInstanceNoteTypeNameById(id, new ErrorServiceArgs("jobId", "identifier", "errorFile")); - verify(errorsService).saveErrorInCSV(eq("jobId"), eq("identifier"), any(BulkEditException.class), eq("errorFile")); + var errors = errorsService.readErrorsFromCSV("jobId", "errorFile", Integer.MAX_VALUE); + + assertThat(errors.getErrors(), Matchers.hasSize(1)); + assertThat(errors.getErrors().get(0).getMessage(), Matchers.equalTo(format("identifier,Instance note type was not found by id: [%s]", id))); } @ParameterizedTest @@ -46,6 +47,6 @@ void shouldSaveErrorWhenInstanceNoteTypeNotFound() { void shouldReturnEmptyNameWhenInstanceNoteTypeIsNullOrEmpty(String id) { var name = instanceReferenceService.getInstanceTypeNameById(id, new ErrorServiceArgs("jobId", "identifier", "errorFile")); - assertThat(name).isEmpty(); + assertThat(name, Matchers.emptyOrNullString()); } } diff --git a/src/test/java/org/folio/dew/service/UserReferenceServiceTest.java b/src/test/java/org/folio/dew/service/UserReferenceServiceTest.java index c7738b842..c5cfc7518 100644 --- a/src/test/java/org/folio/dew/service/UserReferenceServiceTest.java +++ b/src/test/java/org/folio/dew/service/UserReferenceServiceTest.java @@ -1,40 +1,24 @@ package org.folio.dew.service; -import org.folio.dew.client.AddressTypeClient; +import org.folio.dew.BaseBatchTest; import org.folio.dew.client.DepartmentClient; -import org.folio.dew.domain.dto.AddressTypeCollection; import org.folio.dew.domain.dto.Department; -import org.folio.dew.domain.dto.DepartmentCollection; import org.folio.dew.domain.dto.ErrorServiceArgs; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@ExtendWith(MockitoExtension.class) -public class UserReferenceServiceTest { - @Mock - private AddressTypeClient addressTypeClient; - @Mock - private DepartmentClient departmentClient; +class UserReferenceServiceTest extends BaseBatchTest { - @InjectMocks + @MockBean + private DepartmentClient departmentClient; + @Autowired private UserReferenceService userReferenceService; - @Test - void getAddressTypeByDescTest() { - when(addressTypeClient.getAddressTypeByQuery("desc==\"abc\"")).thenReturn(new AddressTypeCollection()); - - userReferenceService.getAddressTypeIdByDesc("abc"); - - verify(addressTypeClient).getAddressTypeByQuery("desc==\"abc\""); - } - @Test void getDepartmentByIdTest() { when(departmentClient.getDepartmentById("id")).thenReturn(new Department()); @@ -44,13 +28,4 @@ void getDepartmentByIdTest() { verify(departmentClient).getDepartmentById("id"); } - @Test - void getDepartmentByNameTest() { - when(departmentClient.getDepartmentByQuery("name==\"name\"")).thenReturn(new DepartmentCollection()); - - userReferenceService.getDepartmentIdByName("name"); - - verify(departmentClient).getDepartmentByQuery("name==\"name\""); - } - } diff --git a/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java b/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java index 084f54ae3..71cee17f1 100644 --- a/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java +++ b/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java @@ -3,26 +3,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import org.folio.dew.client.InstanceNoteTypesClient; +import org.folio.dew.BaseBatchTest; import org.folio.dew.domain.dto.Instance; import org.folio.dew.domain.dto.InstanceNoteType; import org.folio.dew.domain.dto.InstanceNotesInner; import org.folio.dew.service.InstanceReferenceService; import org.folio.dew.service.SpecialCharacterEscaper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; import java.util.Collections; import java.util.UUID; -@ExtendWith(MockitoExtension.class) -class InstanceMapperTest { - @Mock - private InstanceNoteTypesClient instanceNoteTypesClient; - @InjectMocks +class InstanceMapperTest extends BaseBatchTest { + + @Autowired private InstanceReferenceService instanceReferenceService; @Test From ee9b9f1f134f8eda76c3132c4d7a8058b4676224 Mon Sep 17 00:00:00 2001 From: Aliaksei Harbuz Date: Mon, 16 Dec 2024 15:20:42 +0300 Subject: [PATCH 2/2] MODEXPW-537 - Add Statistical code column to instances CSV (#607) * MODEXPW-537 - statistical codes * MODEXPW-537 - test mapper to map statistical codes * MODEXPW-537 - test instance reference * MODEXPW-537 - fix misprint * MODEXPW-537 - rename Statistical codes to Statistical code * MODEXPW-537 - update tests * MODEXPW-537 - update shouldSaveErrorWhenInstanceNoteTypeNotFound * MODEXPW-537 - use mapper for statistical codes tests * MODEXPW-537 - fix sonar issues --- .../folio/dew/domain/dto/InstanceFormat.java | 33 ++++++++++--------- .../dew/service/InstanceReferenceService.java | 13 ++++++-- .../InstanceReferenceServiceCache.java | 10 ++++++ .../dew/service/mapper/InstanceMapper.java | 10 ++++++ .../service/InstanceReferenceServiceTest.java | 18 ++++++++-- .../service/mapper/InstanceMapperTest.java | 15 +++++++++ ...bulk_edit_instance_by_issn_isbn_output.csv | 4 +-- .../bulk_edit_instance_identifiers_output.csv | 6 ++-- ...ance_identifiers_output_some_not_found.csv | 4 +-- 9 files changed, 87 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/folio/dew/domain/dto/InstanceFormat.java b/src/main/java/org/folio/dew/domain/dto/InstanceFormat.java index 2548e93ed..68325a70a 100644 --- a/src/main/java/org/folio/dew/domain/dto/InstanceFormat.java +++ b/src/main/java/org/folio/dew/domain/dto/InstanceFormat.java @@ -9,7 +9,6 @@ import lombok.NoArgsConstructor; import lombok.With; import org.apache.commons.lang3.reflect.FieldUtils; -import org.folio.dew.domain.dto.IdentifierType; import java.lang.reflect.Field; import java.util.stream.Collectors; @@ -59,60 +58,64 @@ public class InstanceFormat implements Formatable codeIds, ErrorServiceArgs args) { + return isEmpty(codeIds) ? EMPTY : codeIds.stream() + .filter(Objects::nonNull) + .map(id -> instanceReferenceService.getStatisticalCodeNameById(id, args)) + .map(specialCharacterEscaper::escape) + .collect(Collectors.joining(ARRAY_DELIMITER)); + } } diff --git a/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java b/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java index 30105bf8b..4b470a936 100644 --- a/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java +++ b/src/test/java/org/folio/dew/service/InstanceReferenceServiceTest.java @@ -21,6 +21,7 @@ @ExtendWith(MockitoExtension.class) class InstanceReferenceServiceTest extends BaseBatchTest { + @Autowired private BulkEditProcessingErrorsService errorsService; @Autowired @@ -31,12 +32,13 @@ void shouldSaveErrorWhenInstanceNoteTypeNotFound() { when(instanceNoteTypesClient.getNoteTypeById(anyString())) .thenThrow(new NotFoundException("not found")); + var jobId = UUID.randomUUID().toString(); var id = UUID.randomUUID().toString(); instanceReferenceService.getInstanceNoteTypeNameById(id, - new ErrorServiceArgs("jobId", "identifier", "errorFile")); + new ErrorServiceArgs(jobId, "identifier", "errorFile")); - var errors = errorsService.readErrorsFromCSV("jobId", "errorFile", Integer.MAX_VALUE); + var errors = errorsService.readErrorsFromCSV(jobId, "errorFile", Integer.MAX_VALUE); assertThat(errors.getErrors(), Matchers.hasSize(1)); assertThat(errors.getErrors().get(0).getMessage(), Matchers.equalTo(format("identifier,Instance note type was not found by id: [%s]", id))); @@ -49,4 +51,16 @@ void shouldReturnEmptyNameWhenInstanceNoteTypeIsNullOrEmpty(String id) { new ErrorServiceArgs("jobId", "identifier", "errorFile")); assertThat(name, Matchers.emptyOrNullString()); } + + @Test + void shouldSaveErrorWhenStatisticalCodeNotFound() { + var jobId = UUID.randomUUID().toString(); + + instanceReferenceService.getStatisticalCodeNameById(UUID.randomUUID().toString(), + new ErrorServiceArgs(jobId, "identifier", "errorFile")); + + var errors = errorsService.readErrorsFromCSV(jobId, "errorFile", Integer.MAX_VALUE); + + assertThat(errors.getErrors(), Matchers.hasSize(1)); + } } diff --git a/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java b/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java index 71cee17f1..6bb598e3c 100644 --- a/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java +++ b/src/test/java/org/folio/dew/service/mapper/InstanceMapperTest.java @@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.util.Collections; +import java.util.List; import java.util.UUID; class InstanceMapperTest extends BaseBatchTest { @@ -37,4 +38,18 @@ void shouldMapInstanceNoteTypes() { assertThat(instanceFormat.getNotes()).isEqualTo("note type;test note;true"); } + + @Test + void shouldMapInstanceStatisticalCodes() { + var statisticalCodeId1 = "b5968c9e-cddc-4576-99e3-8e60aed8b0dd"; + var statisticalCodeId2 = "b5968c9e-cddc-4576-99e3-8e60aed8b0dd"; + var instance = new Instance() + .id(UUID.randomUUID().toString()) + .statisticalCodeIds(List.of(statisticalCodeId1, statisticalCodeId2)); + var mapper = new InstanceMapper(instanceReferenceService, new SpecialCharacterEscaper()); + + var instanceFormat = mapper.mapToInstanceFormat(instance, "identifier", UUID.randomUUID().toString(), "errorFile"); + + assertThat(instanceFormat.getStatisticalCode()).isEqualTo("Book, print (books);Book, print (books)"); + } } diff --git a/src/test/resources/output/bulk_edit_instance_by_issn_isbn_output.csv b/src/test/resources/output/bulk_edit_instance_by_issn_isbn_output.csv index f6db323ca..034571148 100644 --- a/src/test/resources/output/bulk_edit_instance_by_issn_isbn_output.csv +++ b/src/test/resources/output/bulk_edit_instance_by_issn_isbn_output.csv @@ -1,2 +1,2 @@ -Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes -7fbd5d84-62d1-44c6-9c45-6cb173998bbd,false,false,true,inst000000000006,FOLIO,2024-01-26,,,Cataloging data,Bridget Jones's Baby: the diaries,,,"Fielding, Helen",First American Edition,219 pages ; 20 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,,,eng,A frequency description,A publication range, +Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Statistical code,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes +7fbd5d84-62d1-44c6-9c45-6cb173998bbd,false,false,true,inst000000000006,FOLIO,2024-01-26,,,,Cataloging data,Bridget Jones's Baby: the diaries,,,"Fielding, Helen",First American Edition,219 pages ; 20 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,,,eng,A frequency description,A publication range, diff --git a/src/test/resources/output/bulk_edit_instance_identifiers_output.csv b/src/test/resources/output/bulk_edit_instance_identifiers_output.csv index 628ca17f4..5f12cc0f3 100644 --- a/src/test/resources/output/bulk_edit_instance_identifiers_output.csv +++ b/src/test/resources/output/bulk_edit_instance_identifiers_output.csv @@ -1,3 +1,3 @@ -Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes -00f10ab9-d845-4334-92d2-ff55862bf4f9,false,,false,inst000000000002,FOLIO,,,,,American Bar Association journal.,American Bar Association journal.,,American Bar Association; American Bar Association. Journal,,69 v. : ill. ; 23-30 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,,5cb91d15-96b1-4b8a-bf60-ec310538da66,eng,"Monthly, 1921-83 | Quarterly, 1915-20","Began with vol. 1, no. 1 (Jan. 1915); ceased with v. 69, [no.12] (Dec. 1983)", -549fad9e-7f8e-4d8e-9a71-00d251817866,false,true,false,inst000000000028,FOLIO,,,,,"Agile Organisation, Risiko- und Change Management Harald Augustin (Hrsg.)",,Umsetzung der DIN EN ISO 9001:2015 / Harald Augustin (Hrsg.) ; Band 2 | Berichte aus der Betriebswirtschaft | Umsetzung der DIN EN ISO 9001:2015 Band 2,"Augustin, Harald; Shaker Verlag GmbH",,"x, 148 Seiten Illustrationen 21 cm, 188 g",6312d172-f0cf-40f6-b27d-9fa8feaf332f,,,ger,,, +Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Statistical code,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes +00f10ab9-d845-4334-92d2-ff55862bf4f9,false,,false,inst000000000002,FOLIO,,,,,,American Bar Association journal.,American Bar Association journal.,,American Bar Association; American Bar Association. Journal,,69 v. : ill. ; 23-30 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,,5cb91d15-96b1-4b8a-bf60-ec310538da66,eng,"Monthly, 1921-83 | Quarterly, 1915-20","Began with vol. 1, no. 1 (Jan. 1915); ceased with v. 69, [no.12] (Dec. 1983)", +549fad9e-7f8e-4d8e-9a71-00d251817866,false,true,false,inst000000000028,FOLIO,,,,,,"Agile Organisation, Risiko- und Change Management Harald Augustin (Hrsg.)",,Umsetzung der DIN EN ISO 9001:2015 / Harald Augustin (Hrsg.) ; Band 2 | Berichte aus der Betriebswirtschaft | Umsetzung der DIN EN ISO 9001:2015 Band 2,"Augustin, Harald; Shaker Verlag GmbH",,"x, 148 Seiten Illustrationen 21 cm, 188 g",6312d172-f0cf-40f6-b27d-9fa8feaf332f,,,ger,,, diff --git a/src/test/resources/output/bulk_edit_instance_identifiers_output_some_not_found.csv b/src/test/resources/output/bulk_edit_instance_identifiers_output_some_not_found.csv index 28412004d..4d1dbd774 100644 --- a/src/test/resources/output/bulk_edit_instance_identifiers_output_some_not_found.csv +++ b/src/test/resources/output/bulk_edit_instance_identifiers_output_some_not_found.csv @@ -1,2 +1,2 @@ -Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes -00f10ab9-d845-4334-92d2-ff55862bf4f9,false,,false,inst000000000022,FOLIO,,,,,American Bar Association journal.,American Bar Association journal.,,American Bar Association; American Bar Association. Journal,,69 v. : ill. ; 23-30 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,921e6d93-bafb-4a02-b62f-dcd027c45406,5cb91d15-96b1-4b8a-bf60-ec310538da66,eng,"Monthly, 1921-83 | Quarterly, 1915-20","Began with vol. 1, no. 1 (Jan. 1915); ceased with v. 69, [no.12] (Dec. 1983)", +Instance UUID,Suppress from discovery,Staff suppress,Previously held,Instance HRID,Source,Cataloged date,Instance status term,Mode of issuance,Statistical code,Administrative note,Resource title,Index title,Series statements,Contributors,Edition,Physical description,Resource type,Nature of content,Formats,Languages,Publication frequency,Publication range,Notes +00f10ab9-d845-4334-92d2-ff55862bf4f9,false,,false,inst000000000022,FOLIO,,,,,,American Bar Association journal.,American Bar Association journal.,,American Bar Association; American Bar Association. Journal,,69 v. : ill. ; 23-30 cm.,6312d172-f0cf-40f6-b27d-9fa8feaf332f,921e6d93-bafb-4a02-b62f-dcd027c45406,5cb91d15-96b1-4b8a-bf60-ec310538da66,eng,"Monthly, 1921-83 | Quarterly, 1915-20","Began with vol. 1, no. 1 (Jan. 1915); ceased with v. 69, [no.12] (Dec. 1983)",